From 27e8a26ed8d789c663ffaf50e5f0abd7a3a40b1a Mon Sep 17 00:00:00 2001 From: mahan Date: Mon, 8 Dec 2025 14:47:03 +0330 Subject: [PATCH 01/15] Add new domain models and interfaces for project management features --- 0_Framework/0_Framework.csproj | 2 +- ...untManagement.Application.Contracts.csproj | 2 +- .../AccountManagement.Application.csproj | 2 +- .../AccountManagement.Configuration.csproj | 2 +- .../AccountManagement.Domain.csproj | 2 +- ...ountMangement.Infrastructure.EFCore.csproj | 2 +- .../BackgroundInstitutionContract.Task.csproj | 2 +- .../BackgroundJobs.Task.csproj | 2 +- Company.Domain/Company.Domain.csproj | 2 +- ...panyManagement.Infrastructure.Excel.csproj | 2 +- ...panyManagement.Infrastructure.Mongo.csproj | 2 +- .../CompanyManagment.App.Contracts.csproj | 2 +- .../CompanyManagment.Application.csproj | 2 +- .../CompanyManagment.EFCore.csproj | 2 +- DadmehrGostar.sln | 35 + .../PersonalContractingParty.Config.csproj | 2 +- .../CustomerRegisteredHandler.cs | 33 + .../ProjectSection/TaskSectionAddedHandler.cs | 23 + .../TaskSectionAssignedHandler.cs | 14 + ...zareshgirProgramManager.Application.csproj | 20 + .../Interfaces/IBoardNotificationService.cs | 6 + .../CreateOrEditCheckoutCommandHandler.cs | 266 +++ .../GetCheckoutListQueryHandler.cs | 130 + .../GetUserToGroupCreatingQueryHandler.cs | 174 ++ .../AddPhaseToProjectCommand.cs | 13 + .../AddPhaseToProjectCommandHandler.cs | 47 + .../AddTaskToPhase/AddTaskToPhaseCommand.cs | 16 + .../AddTaskToPhaseCommandHandler.cs | 53 + .../AssignProject/AssignProjectCommand.cs | 18 + .../AssignProjectCommandHandler.cs | 274 +++ .../AssignProjectCommandValidator.cs | 39 + .../ChangeStatusSectionCommandHandler.cs | 101 + .../ChangeStatusSectionCommandValidator.cs | 20 + .../CreateProject/CreateProjectCommand.cs | 7 + .../CreateProjectCommandHandler.cs | 82 + .../CreateProjectCommandValidator.cs | 26 + .../CreateProjectWithHierarchyCommand.cs | 13 + ...reateProjectWithHierarchyCommandHandler.cs | 49 + ...ateProjectWithHierarchyCommandValidator.cs | 21 + .../DeleteProjectCommandHandler.cs | 91 + .../DeleteProjectCommandValidator.cs | 19 + .../EditProject/EditProjectCommandHandler.cs | 80 + .../EditProjectCommandValidator.cs | 18 + .../SetTimeProject/SetTimeProjectCommand.cs | 13 + .../SetTimeProjectCommandHandler.cs | 164 ++ .../SetTimeProjectCommandValidator.cs | 50 + .../TransferSection/TransferSectionCommand.cs | 12 + .../TransferSectionCommandHandler.cs | 69 + .../TransferSectionCommandValidator.cs | 28 + .../Projects/DTOs/ProjectHierarchyDtos.cs | 127 + .../DTOs/SetTimeProjectSectionItem.cs | 10 + .../Extensions/ProjectMappingExtensions.cs | 258 ++ .../GetProjectAssignDetailsQueryHandler.cs | 122 + .../GetProjectsList/GetProjectListDto.cs | 18 + .../GetProjectsList/GetProjectsListQuery.cs | 8 + .../GetProjectsListQueryHandler.cs | 303 +++ .../GetProjectsListQueryValidator.cs | 19 + .../GetProjectsListResponse.cs | 5 + .../ProjectBoardList/ProjectBoardListQuery.cs | 10 + .../ProjectBoardListQueryHandler.cs | 98 + .../ProjectBoardListResponse.cs | 28 + .../ProjectSetTimeDetailsQuery.cs | 30 + .../ProjectSetTimeDetailsQueryHandler.cs | 80 + .../ProjectSetTimeDetailsQueryValidator.cs | 13 + .../CreateRole/CreateRoleCommandHandler.cs | 44 + .../EditRole/EditRoleCommandHandler.cs | 54 + .../Queries/GetRoles/GetRolesQueryHandler.cs | 76 + .../CreateSalarySettingsCommandHandler.cs | 173 ++ .../EditSalarySettingsCommandHandler.cs | 120 + .../GetSalarySettingToEditQueryHandler.cs | 88 + .../GetUserListWhoHaveSettingsQueryHandler.cs | 111 + .../Modules/Skills/DTOs/SkillDto.cs | 7 + .../GetSkillListCommandHandler.cs | 33 + .../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 + .../_Bootstrapper/DependencyInjection.cs | 22 + .../_Common/Behaviors/CachingBehavior.cs | 0 .../_Common/Behaviors/LoggingBehavior.cs | 0 .../_Common/Behaviors/PerformanceBehavior.cs | 0 .../_Common/Behaviors/TransactionBehavior.cs | 42 + .../_Common/Behaviors/ValidationBehavior.cs | 40 + .../_Common/Extensions/EnumExtensions.cs | 0 .../_Common/Extensions/QueryableExtensions.cs | 19 + .../_Common/Extensions/StringExtensions.cs | 0 .../_Common/Interfaces/IAuthHelper.cs | 114 + .../_Common/Interfaces/IBaseCommand.cs | 14 + .../_Common/Interfaces/IBaseCommandHandler.cs | 13 + .../Interfaces/IBasePaginationQuery.cs | 10 + .../Interfaces/IBasePaginationQueryHandler.cs | 12 + .../_Common/Interfaces/IBaseQuery.cs | 9 + .../_Common/Interfaces/IBaseQueryHandler.cs | 10 + .../Interfaces/IGozareshgirDbContext.cs | 12 + .../Interfaces/IProgramManagerDbContext.cs | 32 + .../_Common/Models/AccessTokenResponse.cs | 14 + .../_Common/Models/AuthViewModel.cs | 11 + .../_Common/Models/DomainEventNotification.cs | 19 + .../_Common/Models/ErrorDetails.cs | 0 .../_Common/Models/LoginResponse.cs | 15 + .../_Common/Models/OperationResult.cs | 60 + .../_Common/Models/PaginationRequest.cs | 8 + .../_Common/Models/PaginationResult.cs | 11 + .../_Common/Models/TokenValidationResult.cs | 24 + .../CheckoutAgg/Entities/Checkout.cs | 134 ++ .../CheckoutAgg/Enums/CreateCheckoutStatus.cs | 18 + .../CheckoutAgg/Enums/PersianMonthName.cs | 18 + .../Enums/TypeOfCheckoutHandler.cs | 22 + .../Repositories/ICheckoutRepository.cs | 9 + .../CustomerAgg/Customer.cs | 34 + .../CustomerAgg/Entities/Address.cs | 0 .../CustomerAgg/Entities/Customer.cs | 0 .../CustomerAgg/Events/CustomerRegistered.cs | 12 + .../Events/CustomerRegisteredEvent.cs | 0 .../Exceptions/CustomerNotFoundException.cs | 10 + .../Exceptions/DuplicateEmailException.cs | 0 .../Repositories/ICustomerRepository.cs | 10 + .../CustomerAgg/ValueObjects/Email.cs | 0 .../CustomerAgg/ValueObjects/PhoneNumber.cs | 0 .../GozareshgirProgramManager.Domain.csproj | 14 + .../HolidayAgg/Holiday.cs | 25 + .../HolidayItemAgg/HolidayItem.cs | 28 + .../PermissionAgg/Entities/Permission.cs | 21 + .../ProjectAgg/Entities/PhaseSection.cs | 41 + .../ProjectAgg/Entities/Project.cs | 174 ++ .../Entities/ProjectHierarchyNode.cs | 78 + .../ProjectAgg/Entities/ProjectPhase.cs | 199 ++ .../ProjectAgg/Entities/ProjectSection.cs | 34 + .../ProjectAgg/Entities/ProjectTask.cs | 249 ++ .../ProjectAgg/Entities/TaskSection.cs | 223 ++ .../Entities/TaskSectionActivity.cs | 57 + .../Entities/TaskSectionAdditionalTime.cs | 29 + .../ProjectAgg/Entities/UserTimeReport.cs | 18 + .../ProjectAgg/Enums/PhaseStatus.cs | 37 + .../ProjectAgg/Enums/ProjectHierarchyLevel.cs | 23 + .../ProjectAgg/Enums/ProjectStatus.cs | 37 + .../ProjectAgg/Enums/TaskPriority.cs | 27 + .../ProjectAgg/Enums/TaskSectionStatus.cs | 10 + .../ProjectAgg/Enums/TaskStatus.cs | 9 + .../ProjectAgg/Events/ProjectEvents.cs | 177 ++ .../ProjectAgg/Models/UserTimeReport.cs | 12 + .../Repositories/IPhaseSectionRepository.cs | 6 + .../Repositories/IProjectPhaseRepository.cs | 33 + .../Repositories/IProjectRepository.cs | 38 + .../Repositories/IProjectSectionRepository.cs | 9 + .../Repositories/IProjectTaskRepository.cs | 47 + .../ITaskSectionActivityRepository.cs | 16 + .../Repositories/ITaskSectionRepository.cs | 12 + .../ProjectAgg/ValueObjects/TimeTracking.cs | 75 + .../ValueObjects/UserSkillAssignment.cs | 31 + .../RoleAgg/Entities/Role.cs | 48 + .../RoleAgg/Repositories/IRoleRepository.cs | 12 + .../RoleUserAgg/RoleUser.cs | 19 + .../DTOs/UserSalarySettingDto.cs | 43 + .../Entities/SalaryPaymentSetting.cs | 94 + .../Entities/WorkingHours.cs | 164 ++ .../Enums/HasSalarySettings.cs | 20 + .../Enums/PersianDayOfWeek.cs | 29 + .../ISalaryPaymentSettingRepository.cs | 26 + .../SkillAgg/Entities/Skill.cs | 16 + .../SkillAgg/Repositories/ISkillRepository.cs | 9 + .../UserAgg/Entities/User.cs | 169 ++ .../UserAgg/Entities/UserRefreshToken.cs | 90 + .../UserAgg/Enums/ExternalAuthProvider.cs | 1 + .../UserAgg/Events/UserEvents.cs | 47 + .../IUserRefreshTokenRepository.cs | 9 + .../UserAgg/Repositories/IUserRepository.cs | 32 + .../_Common/EntityBase.cs | 25 + .../_Common/Exceptions/BadRequestException.cs | 24 + .../_Common/Exceptions/NotFoundException.cs | 13 + .../Exceptions/UnAuthorizedException.cs | 8 + .../_Common/IAggregateRoot.cs | 8 + .../_Common/IDomainEvent.cs | 6 + .../_Common/IRepository.cs | 17 + .../_Common/IUnitOfWork.cs | 9 + .../_Common/Tools.cs | 2089 +++++++++++++++++ .../_Common/ValueObject.cs | 38 + .../DependencyInjection.cs | 105 + ...eshgirProgramManager.Infrastructure.csproj | 22 + .../20251119114157_Initial.Designer.cs | 393 ++++ .../Migrations/20251119114157_Initial.cs | 262 +++ ...20251119152314_ChangeUsertable.Designer.cs | 320 +++ .../20251119152314_ChangeUsertable.cs | 192 ++ .../20251123123226_RoleInit.Designer.cs | 372 +++ .../Migrations/20251123123226_RoleInit.cs | 64 + .../20251123135308_RoleUpdate.Designer.cs | 375 +++ .../Migrations/20251123135308_RoleUpdate.cs | 28 + ...125111142_add skills to entity.Designer.cs | 346 +++ .../20251125111142_add skills to entity.cs | 222 ++ ...112542_change section key name.Designer.cs | 346 +++ .../20251125112542_change section key name.cs | 62 + ...ject node on delete to cascade.Designer.cs | 346 +++ ...hange project node on delete to cascade.cs | 22 + ...and additionalTime description.Designer.cs | 349 +++ ... section and additionalTime description.cs | 142 ++ ...0251126122836_AddUserRoleTable.Designer.cs | 406 ++++ .../20251126122836_AddUserRoleTable.cs | 46 + ...nodes to three seprated pieces.Designer.cs | 556 +++++ ...cts from nodes to three seprated pieces.cs | 287 +++ ...50949_SalaryPaymentSettingInit.Designer.cs | 524 +++++ ...20251201150949_SalaryPaymentSettingInit.cs | 87 + ...3519_IsActiveDayToWorkingHours.Designer.cs | 648 +++++ ...0251202113519_IsActiveDayToWorkingHours.cs | 29 + .../20251202145954_CheckoutInit.Designer.cs | 706 ++++++ .../Migrations/20251202145954_CheckoutInit.cs | 50 + ...3071011_add user refresh token.Designer.cs | 707 ++++++ .../20251203071011_add user refresh token.cs | 62 + .../20251203174140_add sections.Designer.cs | 786 +++++++ .../Migrations/20251203174140_add sections.cs | 288 +++ ...phase section and task section.Designer.cs | 839 +++++++ ...4818_add phase section and task section.cs | 138 ++ ...eAndRolePermissionTablerenamed.Designer.cs | 905 +++++++ ...80830_RoleAndRolePermissionTablerenamed.cs | 109 + .../Migrations/AppDbContextModelSnapshot.cs | 902 +++++++ .../Context/GozareshgirDbContext.cs | 22 + .../Context/ProgramManagerDbContext.cs | 61 + .../Mappings/AdditionalTimeMapping.cs | 23 + .../Persistence/Mappings/CheckoutMapping.cs | 19 + .../Persistence/Mappings/CustomerMapping.cs | 29 + .../Mappings/HolidayItemMapping.cs | 20 + .../Persistence/Mappings/HolidayMapping.cs | 20 + .../Mappings/PhaseSectionMapping.cs | 21 + .../Persistence/Mappings/ProjectMapping.cs | 58 + .../Mappings/ProjectPhaseMapping.cs | 64 + .../Mappings/ProjectSectionMapping.cs | 20 + .../Mappings/ProjectTaskMapping.cs | 79 + .../Mappings/RefreshTokenMapping.cs | 50 + .../Persistence/Mappings/RoleMapping.cs | 23 + .../Mappings/SalaryPaymentSettingMapping.cs | 50 + .../Persistence/Mappings/SkillMapping.cs | 27 + .../Mappings/TaskSectionActivityMapping.cs | 53 + .../TaskSectionAdditionalTimeMapping.cs | 39 + .../Mappings/TaskSectionMapping.cs | 53 + .../Persistence/Mappings/UserMapping.cs | 34 + .../Repositories/CheckoutRepository.cs | 22 + .../Repositories/CustomerRepository.cs | 38 + .../Repositories/OrderRepository.cs | 0 .../Repositories/PhaseSectionRepository.cs | 18 + .../Repositories/ProductRepository.cs | 0 .../Repositories/ProjectPhaseRepository.cs | 60 + .../Repositories/ProjectRepository.cs | 70 + .../Repositories/ProjectSectionRepository.cs | 17 + .../Repositories/ProjectTaskRepository.cs | 79 + .../Repositories/RoleRepository.cs | 24 + .../SalaryPaymentSettingRepository.cs | 60 + .../Repositories/SkillRepository.cs | 16 + .../TaskSectionActivityRepository.cs | 83 + .../Repositories/TaskSectionRepository.cs | 31 + .../UserRefreshTokenRepository.cs | 20 + .../Repositories/UserRepository.cs | 87 + .../Persistence/Seed/DataSeeder.cs | 36 + .../Persistence/Seed/IDataSeeder.cs | 10 + .../Persistence/UnitOfWork.cs | 53 + .../_Common/PropertyBuilderExtensions.cs | 21 + .../Persistence/_Common/RepositoryBase.cs | 70 + .../Services/Authentication/AuthHelper.cs | 215 ++ .../Services/Authentication/JwtSettings.cs | 14 + .../Authentication/JwtTokenGenerator.cs | 153 ++ .../Services/CacheService.cs | 0 .../Services/DateTimeService.cs | 0 .../Services/EmailService.cs | 0 .../Services/FileService.cs | 0 Query.Bootstrapper/Query.Bootstrapper.csproj | 2 +- Query/Query.csproj | 2 +- .../Areas/Admin/Controllers/AuthController.cs | 143 ++ .../Admin/Controllers/CheckoutController.cs | 93 + .../Admin/Controllers/GeneralController.cs | 29 + .../Admin/Controllers/ProjectController.cs | 102 + .../Areas/Admin/Controllers/RoleController.cs | 46 + .../SalaryPaymentSettingsController.cs | 67 + .../Admin/Controllers/SkillController.cs | 24 + .../Areas/Admin/Controllers/UserController.cs | 67 + ServiceHost/Program.cs | 11 + ServiceHost/ServiceHost.csproj | 6 +- .../WorkFlow.Application.Contracts.csproj | 2 +- .../WorkFlow.Application.csproj | 2 +- .../WorkFlow.Domain/WorkFlow.Domain.csproj | 2 +- .../WorkFlow.Infrastructure.ACL.csproj | 2 +- .../WorkFlow.Infrastructure.Config.csproj | 2 +- .../WorkFlow.Infrastructure.EfCore.csproj | 2 +- _0_Framework/_0_Framework_b.csproj | 2 +- backService/backService.csproj | 2 +- 295 files changed, 24896 insertions(+), 26 deletions(-) create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/CustomerRegisteredHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAddedHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAssignedHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetCheckoutList/GetCheckoutListQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetUserToGropCreate/GetUserToGroupCreatingQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/SetTimeProjectSectionItem.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectAssignDetails/GetProjectAssignDetailsQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQuery.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryValidator.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQuery.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryValidator.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/SalaryPaymentSettings/Commands/CreateSalarySettings/CreateSalarySettingsCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Commands/EditSalarySettings/EditSalarySettingsCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetSalarySettingToEdit/GetSalarySettingToEditQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetUserListWhoHaveSettings/GetUserListWhoHaveSettingsQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/DTOs/SkillDto.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/Queries/GetSkillList/GetSkillListCommandHandler.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/Application/GozareshgirProgramManager.Application/_Bootstrapper/DependencyInjection.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/CachingBehavior.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/LoggingBehavior.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/PerformanceBehavior.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/TransactionBehavior.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/ValidationBehavior.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/EnumExtensions.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/QueryableExtensions.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/StringExtensions.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommand.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommandHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQuery.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQuery.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQueryHandler.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IProgramManagerDbContext.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AccessTokenResponse.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AuthViewModel.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/DomainEventNotification.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/ErrorDetails.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/LoginResponse.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/OperationResult.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationRequest.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationResult.cs create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/TokenValidationResult.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Entities/Checkout.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/CreateCheckoutStatus.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/PersianMonthName.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/TypeOfCheckoutHandler.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Repositories/ICheckoutRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Customer.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Entities/Address.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Entities/Customer.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegistered.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegisteredEvent.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/CustomerNotFoundException.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/DuplicateEmailException.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Repositories/ICustomerRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/ValueObjects/Email.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/ValueObjects/PhoneNumber.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/Project.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectHierarchyNode.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionActivity.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionAdditionalTime.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/UserTimeReport.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/PhaseStatus.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectHierarchyLevel.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectStatus.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskPriority.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskSectionStatus.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskStatus.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Models/UserTimeReport.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IPhaseSectionRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectPhaseRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectSectionRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectTaskRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionActivityRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/TimeTracking.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/UserSkillAssignment.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/DTOs/UserSalarySettingDto.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/WorkingHours.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/HasSalarySettings.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/PersianDayOfWeek.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Repositories/ISalaryPaymentSettingRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Entities/Skill.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Repositories/ISkillRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/EntityBase.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/BadRequestException.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/NotFoundException.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/UnAuthorizedException.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IAggregateRoot.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IDomainEvent.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IUnitOfWork.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/ValueObject.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.Designer.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/AdditionalTimeMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CheckoutMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CustomerMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectPhaseMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectTaskMapping.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/SalaryPaymentSettingMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/SkillMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionActivityMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionAdditionalTimeMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CheckoutRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CustomerRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/OrderRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/PhaseSectionRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProductRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectPhaseRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectSectionRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectTaskRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SkillRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionActivityRepository.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.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 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/DataSeeder.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/IDataSeeder.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/UnitOfWork.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/PropertyBuilderExtensions.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/RepositoryBase.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtSettings.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtTokenGenerator.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/CacheService.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/DateTimeService.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/EmailService.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileService.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/AuthController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/CheckoutController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/GeneralController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/ProjectController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/RoleController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/SkillController.cs create mode 100644 ServiceHost/Areas/Admin/Controllers/UserController.cs diff --git a/0_Framework/0_Framework.csproj b/0_Framework/0_Framework.csproj index 54b62986..d4a5ba2f 100644 --- a/0_Framework/0_Framework.csproj +++ b/0_Framework/0_Framework.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 _0_Framework diff --git a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj index 36069642..393ad8f9 100644 --- a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj +++ b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 diff --git a/AccountManagement.Application/AccountManagement.Application.csproj b/AccountManagement.Application/AccountManagement.Application.csproj index 7fcb4ebe..270c0e13 100644 --- a/AccountManagement.Application/AccountManagement.Application.csproj +++ b/AccountManagement.Application/AccountManagement.Application.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 diff --git a/AccountManagement.Configuration/AccountManagement.Configuration.csproj b/AccountManagement.Configuration/AccountManagement.Configuration.csproj index 0b172228..3914494a 100644 --- a/AccountManagement.Configuration/AccountManagement.Configuration.csproj +++ b/AccountManagement.Configuration/AccountManagement.Configuration.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 diff --git a/AccountManagement.Domain/AccountManagement.Domain.csproj b/AccountManagement.Domain/AccountManagement.Domain.csproj index 031bd6e0..b0cc8442 100644 --- a/AccountManagement.Domain/AccountManagement.Domain.csproj +++ b/AccountManagement.Domain/AccountManagement.Domain.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 diff --git a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj index 7899acfa..d75abbba 100644 --- a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj +++ b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj index d30ce3b8..d003ac92 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable BackgroundInstitutionContract.Task diff --git a/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj b/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj index 0ab571f8..892e6b99 100644 --- a/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj +++ b/BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable diff --git a/Company.Domain/Company.Domain.csproj b/Company.Domain/Company.Domain.csproj index 924cc212..cde1f022 100644 --- a/Company.Domain/Company.Domain.csproj +++ b/Company.Domain/Company.Domain.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 diff --git a/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj b/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj index a62b92f9..7053b025 100644 --- a/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj +++ b/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj b/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj index 4c09d4ae..75b4e0f3 100644 --- a/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj +++ b/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj b/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj index b2977176..07606229 100644 --- a/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj +++ b/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 true diff --git a/CompanyManagment.Application/CompanyManagment.Application.csproj b/CompanyManagment.Application/CompanyManagment.Application.csproj index 36154b43..d6b12f2d 100644 --- a/CompanyManagment.Application/CompanyManagment.Application.csproj +++ b/CompanyManagment.Application/CompanyManagment.Application.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 diff --git a/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj b/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj index 7ea4c3cd..381b2623 100644 --- a/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj +++ b/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 diff --git a/DadmehrGostar.sln b/DadmehrGostar.sln index b6cf7ab9..358d6d87 100644 --- a/DadmehrGostar.sln +++ b/DadmehrGostar.sln @@ -88,6 +88,22 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompanyManagement.Infrastru EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackgroundInstitutionContract.Task", "BackgroundInstitutionContract\BackgroundInstitutionContract.Task\BackgroundInstitutionContract.Task.csproj", "{F78FBB92-294B-88BA-168D-F0C578B0D7D6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ProgramManager", "ProgramManager", "{67AFF7B6-4C4F-464C-A90D-9BDB644D83A9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{9D85672B-D48E-40B5-9804-0CE220E0E64C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{D74D1E3B-3BE3-47EE-9914-785A8AD536E5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{C0AE9368-D4E7-450B-9713-929D319DE690}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Application", "ProgramManager\src\Application\GozareshgirProgramManager.Application\GozareshgirProgramManager.Application.csproj", "{B57EB542-C028-4A77-9386-9DFF1E60FDCB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Domain", "ProgramManager\src\Domain\GozareshgirProgramManager.Domain\GozareshgirProgramManager.Domain.csproj", "{D2B4F1D7-6336-4B30-910C-219F4119303F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GozareshgirProgramManager.Infrastructure", "ProgramManager\src\Infrastructure\GozareshgirProgramManager.Infrastructure\GozareshgirProgramManager.Infrastructure.csproj", "{408281FE-615F-4CBE-BD95-2E86F5ACC6C3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -198,6 +214,18 @@ Global {F78FBB92-294B-88BA-168D-F0C578B0D7D6}.Debug|Any CPU.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 + {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}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B57EB542-C028-4A77-9386-9DFF1E60FDCB}.Release|Any CPU.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}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2B4F1D7-6336-4B30-910C-219F4119303F}.Release|Any CPU.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}.Release|Any CPU.ActiveCfg = Release|Any CPU + {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -234,6 +262,13 @@ Global {BF98173C-42AF-4897-A7CB-4CACEB2B52A2} = {86921E1B-2AFA-4B8A-9403-EE16D58B5B26} {97E148FA-3C36-40DD-B121-D90C1C0F3B47} = {C10E256D-7E7D-4C77-B416-E577A34AF924} {F78FBB92-294B-88BA-168D-F0C578B0D7D6} = {C10E256D-7E7D-4C77-B416-E577A34AF924} + {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1} = {67AFF7B6-4C4F-464C-A90D-9BDB644D83A9} + {9D85672B-D48E-40B5-9804-0CE220E0E64C} = {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1} + {D74D1E3B-3BE3-47EE-9914-785A8AD536E5} = {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1} + {C0AE9368-D4E7-450B-9713-929D319DE690} = {48F6F6A5-7340-42F8-9216-BEB7A4B7D5A1} + {B57EB542-C028-4A77-9386-9DFF1E60FDCB} = {9D85672B-D48E-40B5-9804-0CE220E0E64C} + {D2B4F1D7-6336-4B30-910C-219F4119303F} = {D74D1E3B-3BE3-47EE-9914-785A8AD536E5} + {408281FE-615F-4CBE-BD95-2E86F5ACC6C3} = {C0AE9368-D4E7-450B-9713-929D319DE690} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E6CFB3A7-A7C8-4E82-8F06-F750408F0BA9} diff --git a/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj b/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj index 3e55f945..9e36ff54 100644 --- a/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj +++ b/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/CustomerRegisteredHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/CustomerRegisteredHandler.cs new file mode 100644 index 00000000..778f3104 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/CustomerRegisteredHandler.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using GozareshgirProgramManager.Domain.CustomerAgg.Events; +using GozareshgirProgramManager.Application._Common.Models; + +namespace GozareshgirProgramManager.Application.DomainEventHandlers; + +public class CustomerRegisteredHandler : INotificationHandler> +{ + private readonly ILogger _logger; + + public CustomerRegisteredHandler(ILogger logger) + { + _logger = logger; + } + + public Task Handle(DomainEventNotification notification, CancellationToken cancellationToken) + { + var domainEvent = notification.DomainEvent; + + _logger.LogInformation( + "Customer registered: {CustomerId}, Name: {Name}, Email: {Email}", + domainEvent.CustomerId, + domainEvent.Name, + domainEvent.Email); + + + // اینجا می‌توانید email ارسال کنید یا کارهای دیگر انجام دهید + + return Task.CompletedTask; + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAddedHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAddedHandler.cs new file mode 100644 index 00000000..a7538ef2 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAddedHandler.cs @@ -0,0 +1,23 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; +using MediatR; +using Microsoft.Extensions.Logging; + +namespace GozareshgirProgramManager.Application.DomainEventHandlers.ProjectSection; + +public class ProjectSectionAddedHandler:INotificationHandler> +{ + private readonly ILogger _logger; + + public ProjectSectionAddedHandler(ILogger logger) + { + _logger = logger; + } + + public Task Handle(DomainEventNotification notification, CancellationToken cancellationToken) + { + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAssignedHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAssignedHandler.cs new file mode 100644 index 00000000..3f86a177 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/DomainEventHandlers/ProjectSection/TaskSectionAssignedHandler.cs @@ -0,0 +1,14 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; +using MediatR; + +namespace GozareshgirProgramManager.Application.DomainEventHandlers.ProjectSection; + +public class ProjectSectionAssignedHandler:INotificationHandler> +{ + public Task Handle(DomainEventNotification notification, CancellationToken cancellationToken) + { + var domainEvent = notification.DomainEvent; + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj new file mode 100644 index 00000000..7bd51642 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj @@ -0,0 +1,20 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + + + + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs new file mode 100644 index 00000000..959e7fbf --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Interfaces/IBoardNotificationService.cs @@ -0,0 +1,6 @@ +namespace GozareshgirProgramManager.Application.Interfaces; + +public interface IBoardNotificationService +{ + Task SendProjectAssignedAsync(); +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs new file mode 100644 index 00000000..d7704b1f --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs @@ -0,0 +1,266 @@ + +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CheckoutAgg.Entities; +using GozareshgirProgramManager.Domain.CheckoutAgg.Enums; +using GozareshgirProgramManager.Domain.CheckoutAgg.Repositories; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using MediatR; +using PersianTools.Core; +using System.Runtime.InteropServices; +using Microsoft.EntityFrameworkCore; + + +namespace GozareshgirProgramManager.Application.Modules.Checkouts.Commands.CreateCheckout; + +public class CreateOrEditCheckoutCommandHandler : IBaseCommandHandler +{ + private readonly ICheckoutRepository _checkoutRepository; + private readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository; + private readonly ITaskSectionActivityRepository _taskSectionActivityRepository; + private readonly IUnitOfWork _unitOfWork; + private readonly IGozareshgirDbContext _gozareshgirDbContext; + + + public CreateOrEditCheckoutCommandHandler(ICheckoutRepository checkoutRepository, IUnitOfWork unitOfWork, ISalaryPaymentSettingRepository salaryPaymentSettingRepository, ITaskSectionActivityRepository taskSectionActivityRepository, IGozareshgirDbContext gozareshgirDbContext) + { + _checkoutRepository = checkoutRepository; + _unitOfWork = unitOfWork; + _salaryPaymentSettingRepository = salaryPaymentSettingRepository; + _taskSectionActivityRepository = taskSectionActivityRepository; + _gozareshgirDbContext = gozareshgirDbContext; + } + + public async Task Handle(CreateOrEditCheckoutCommand request, CancellationToken cancellationToken) + { + + switch (request.TypeOfCheckoutHandler) + { + case TypeOfCheckoutHandler.CreateInGroup: + return await Create(request.Year, request.Month, request.UserIdList); + break; + case TypeOfCheckoutHandler.SingleEdit: + case TypeOfCheckoutHandler.GroupEditing: + return await GroupOrSingleEditing(request.CheckoutIdList); + break; + + } + return OperationResult.Failure("نوع متد انتخاب نشده است"); + } + + /// + /// ایجاد گروهی فیش حقوقی + /// + /// + /// + /// + /// + public async Task Create(string? Year, string? Month, List? UserIdList) + { + if (string.IsNullOrWhiteSpace(Month)) + return OperationResult.Failure("ماه خالی است"); + if (string.IsNullOrWhiteSpace(Year)) + return OperationResult.Failure("سال خالی است"); + if (UserIdList == null) + return OperationResult.Failure("هیچ موردی برای ایجاد انتخاب نشده اشت"); + if (UserIdList.Count == 0) + return OperationResult.Failure("هیچ موردی برای ایجاد انتخاب نشده اشت"); + + var startDateGr = new DateTime(); + var EndDateGr = new DateTime(); + var persianStart = new PersianDateTime(); + + int year = 0; + int month = 0; + try + { + year = Convert.ToInt32(Year); + month = Convert.ToInt32(Month); + persianStart = new PersianDateTime(year, month, 1); + var startDateFa = $"{persianStart}"; + startDateGr = startDateFa.ToGeorgianDateTime(); + + var endDateFa = startDateFa.FindeEndOfMonth(); + + EndDateGr = endDateFa.ToGeorgianDateTime(); + + + } + catch (Exception) + { + + return OperationResult.Failure( + "خطا در ورود سال و ماه"); + } + + var totalDays = Convert.ToInt32((EndDateGr - startDateGr).TotalDays + 1); + + var getAllSettings = await _salaryPaymentSettingRepository.GetAllSettings(UserIdList); + var get = await _taskSectionActivityRepository.GetTotalTimeSpentPerUserInRangeAsync(startDateGr, EndDateGr); + + foreach (var user in getAllSettings) + { + var totalWorked = get.FirstOrDefault(x => x.UserId == user.UserId); + var totalTimeTotalMinutes = (int)totalWorked.TotalTime.TotalMinutes; + var res = await ComputeSalary(user.WorkingHoursListDto, totalTimeTotalMinutes, user.MonthlySalary, startDateGr, EndDateGr, user.HolidayWorking); + var createCheckout = new Checkout(startDateGr, EndDateGr, year, month, user.FullName, user.UserId, + res.MandatoryHours, totalTimeTotalMinutes, + totalDays, res.RemainingHours, user.MonthlySalary, res.MonthlySalaryPay, res.DeductionFromSalary); + await _checkoutRepository.CreateAsync(createCheckout); + } + + await _unitOfWork.SaveChangesAsync(); + + return OperationResult.Success(); + } + + /// + /// متد ویراش گروهی و تکی + /// + /// + /// + /// + /// + public async Task GroupOrSingleEditing(List? CheckoutIdList) + { + + if (CheckoutIdList == null) + return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت"); + if (CheckoutIdList.Count == 0) + return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت"); + + var checkouts = await _checkoutRepository.GetCheckoutListByIds(CheckoutIdList); + if (!checkouts.Any()) + return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت"); + var UserIdList = checkouts.Select(x => x.UserId).ToList(); + var getAllSettings = await _salaryPaymentSettingRepository.GetAllSettings(UserIdList); + if (!getAllSettings.Any()) + return OperationResult.Failure("تنظیمات ساعت و حقوق یافت نشد"); + foreach (var checkoutId in CheckoutIdList) + { + var checkout = checkouts.FirstOrDefault(x => x.Id == checkoutId); + if (checkout == null) + return OperationResult.Failure("فیش مورد نظر یافت نشد"); + + var userSetting = getAllSettings.FirstOrDefault(x => x.UserId == checkout.UserId); + + var get = await _taskSectionActivityRepository.GetTotalTimeSpentByUserInRangeAsync(checkout.UserId, checkout.CheckoutStartDate, checkout.CheckoutEndDate); + + var totalTimeTotalMinutes = (int)get.TotalMinutes; + + var totalDays = Convert.ToInt32((checkout.CheckoutEndDate - checkout.CheckoutStartDate).TotalDays + 1); + var res = await ComputeSalary(userSetting.WorkingHoursListDto, totalTimeTotalMinutes, userSetting.MonthlySalary, checkout.CheckoutStartDate, checkout.CheckoutEndDate, userSetting.HolidayWorking); + checkout.Edit(res.MandatoryHours, totalTimeTotalMinutes, totalDays, res.RemainingHours, userSetting.MonthlySalary, res.MonthlySalaryPay, res.DeductionFromSalary); + + await _unitOfWork.SaveChangesAsync(); + } + + + + return OperationResult.Success(); + } + + /// + /// محاسبه حقوق + /// + /// + public async Task ComputeSalary(List workingHoursListDto, int totalHoursWorked, double monthlySalaryDefined, DateTime start, DateTime end, bool holidayWorking) + { + var startDate = start.ToFarsi(); + var startYear = Convert.ToInt32(startDate.Substring(0, 4)); + var startMonth = Convert.ToInt32(startDate.Substring(5, 2)); + var startDay = Convert.ToInt32(startDate.Substring(8, 2)); + var persianStart = new PersianDateTime(startYear, startMonth, startDay); + var endDate = end.ToFarsi(); + var endYear = Convert.ToInt32(endDate.Substring(0, 4)); + var endMonth = Convert.ToInt32(endDate.Substring(5, 2)); + var endDay = Convert.ToInt32(endDate.Substring(8, 2)); + var persianEnd = new PersianDateTime(endYear, endMonth, endDay); + var holidays = await _gozareshgirDbContext.HolidayItems.Where(x=>x.Holidaydate >= start && x.Holidaydate <= end).ToListAsync(); + + + int mandatoryHours = 0; + for (var currentDay = persianStart; currentDay <= persianEnd; currentDay = currentDay.AddDays(1)) + { + var currentDayOfWeek = new DNTPersianUtils.Core.PersianDateTime(currentDay.Year, currentDay.Month, currentDay.Day); + var holidayDate = currentDay.ShamsiDate.ToGeorgianDateTime(); + var day = (PersianDayOfWeek)currentDayOfWeek.WeekDayNumber!; + var getDaySetting = workingHoursListDto.FirstOrDefault(x => x.PersianDayOfWeek == day); + if (getDaySetting != null) + { + if (!holidayWorking && holidays.Any(x => x.Holidaydate == holidayDate)) + { + + } + else + { + mandatoryHours += (int)getDaySetting.ShiftDuration.TotalMinutes; + Console.WriteLine((int)getDaySetting.ShiftDuration.TotalMinutes + " " + currentDay + " - " + day); + } + + + + } + + + + + } + //حقوق نهایی + var monthlySalaryPay = (totalHoursWorked * monthlySalaryDefined) / mandatoryHours; + // اگر اضافه کار داشت حقوق تعین شده به عنوان حقوق نهایی در نظر گرفته میشود + monthlySalaryPay = monthlySalaryPay > monthlySalaryDefined ? monthlySalaryDefined : monthlySalaryPay; + + //حقوق کسر شده + var deductionFromSalary = monthlySalaryDefined - monthlySalaryPay; + + //زمان باقی مانده + var remainingTime = totalHoursWorked - mandatoryHours; + + var computeResult = new ComputeResultDto + { + MandatoryHours = mandatoryHours, + MonthlySalaryPay = monthlySalaryPay, + DeductionFromSalary = deductionFromSalary, + RemainingHours = remainingTime + }; + Console.WriteLine(mandatoryHours); + return computeResult; + } + +} + + +public record CreateOrEditCheckoutCommand(TypeOfCheckoutHandler TypeOfCheckoutHandler, string? Year, string? Month, List? UserIdList, List? CheckoutIdList) : IBaseCommand; + +public record ComputeResultDto +{ + + /// + /// ساعات باقی مانده + /// کسر کار یا اضافه کار + /// + public int RemainingHours { get; set; } + + + /// + /// حقوق نهایی که به پرسنل داده می شود + /// + public double MonthlySalaryPay { get; set; } + + /// + /// کسر از حقوق + /// + public double DeductionFromSalary { get; set; } + + /// + /// ساعت موظفی + /// + public int MandatoryHours { get; set; } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetCheckoutList/GetCheckoutListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetCheckoutList/GetCheckoutListQueryHandler.cs new file mode 100644 index 00000000..f2a93459 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetCheckoutList/GetCheckoutListQueryHandler.cs @@ -0,0 +1,130 @@ +using GozareshgirProgramManager.Application._Common.Extensions; +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate; +using GozareshgirProgramManager.Domain._Common; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetCheckoutList; + +public class GetCheckoutListQueryHandler : IBasePaginationQueryHandler +{ + private readonly IProgramManagerDbContext _programManagerDbContext; + + public GetCheckoutListQueryHandler(IProgramManagerDbContext programManagerDbContext) + { + _programManagerDbContext = programManagerDbContext; + } + + public async Task>> Handle(GetCheckoutListQuery request, CancellationToken cancellationToken) + { + var query = _programManagerDbContext.Checkouts.AsQueryable(); + + if (!string.IsNullOrWhiteSpace(request.Year)) + { + var year = Convert.ToInt32(request.Year); + query = query.Where(x => x.Year == year); + + } + + if (!string.IsNullOrWhiteSpace(request.Month)) + { + var month = Convert.ToInt32(request.Month); + query = query.Where(x => x.Month == month); + } + + if (!string.IsNullOrWhiteSpace(request.FullName)) + query = query.Where(x => x.FullName.Contains(request.FullName)); + + var res =await query.Select(x => new GetCheckoutListResponse() + { + CheckoutId = x.Id, + Year = x.Year, + Month = x.PersianMonthName, + FullName = x.FullName, + MandatoryHours = x.MandatoryHours, + TotalHoursWorked = x.TotalHoursWorked, + RemainingHours = x.RemainingHours, + MonthlySalaryDefined = x.MonthlySalaryDefined.ToMoney(), + DeductionFromSalary = x.DeductionFromSalary.ToMoney(), + MonthlySalaryPay = x.MonthlySalaryPay.ToMoney() + + + }).ApplyPagination(request.PageIndex,request.PageSize).ToListAsync(cancellationToken: cancellationToken); + + var response = new PaginationResult + { + List = res, + TotalCount = query.Count(), + }; + + return OperationResult>.Success(response); + } +} + +public record GetCheckoutListQuery(string? Month, string? Year, string? FullName) : PaginationRequest, IBasePaginationQuery; + +public record GetCheckoutListResponse +{ + /// + /// آی دی فیش حقوقی + /// + public Guid CheckoutId { get; set; } + + /// + /// سال + /// + public int Year { get; set; } + + /// + /// ماه + /// + public string Month { get; set; } + + /// + /// نام کامل پرسنل + /// + public string FullName { get; set; } + + + /// + /// ساعت موظفی + /// + public int MandatoryHours { get; set; } + + /// + /// مجموع ساعات کارکرد پرسنل + /// + public int TotalHoursWorked { get; set; } + + /// + /// ساعات باقی مانده + /// کسر کار یا اضافه کار + /// + public int RemainingHours { get; set; } + + + /// + /// حقوق ماهانه + /// تعیین شده + /// + public string MonthlySalaryDefined { get; set; } + + + /// + /// کسر از حقوق + /// + public string DeductionFromSalary { get; set; } + + + /// + /// حقوق نهایی که به پرسنل داده می شود + /// + public string MonthlySalaryPay { get; set; } +} + + + + + + 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 new file mode 100644 index 00000000..1b04026a --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Queries/GetUserToGropCreate/GetUserToGroupCreatingQueryHandler.cs @@ -0,0 +1,174 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetUserListWhoHaveSettings; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CheckoutAgg.Enums; +using Microsoft.EntityFrameworkCore; +using PersianTools.Core; + +namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate; + +/// +/// دریافت کاربران برای ایجاد گروهی فیش حقوقی با سال و ماه +/// +public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetUserToGroupCreatingQuery request, CancellationToken cancellationToken) + { + //سال و ماه انتخاب شده از فرانت + var selectedDate = new DateTime(); + try + { + int year = Convert.ToInt32(request.Year); + int month = Convert.ToInt32(request.Month); + selectedDate = ($"{new PersianDateTime(year,month,1)}").ToGeorgianDateTime(); + } + catch (Exception) + { + + return OperationResult.Failure( + "خطا در ورود سال و ماه"); + } + + //آخرین تاریخ مجاز برای ایجاد فیش + var lastMonth = ($"{DateTime.Now.ToFarsi().Substring(0, 8)}01").ToGeorgianDateTime().AddDays(-1); + + if (selectedDate > lastMonth) + return OperationResult.Failure( + "ایجاد فیش فقط برای ماه های گذشته امکان پذیر است"); + + + var lastMonthStart = lastMonth; + var lastMonthEnd = lastMonth; + + var query = + await (from u in _context.Users + + // LEFT JOIN + // تنظیمات حقوق + join s in _context.SalaryPaymentSettings + on u.Id equals s.UserId into sJoin + from s in sJoin.DefaultIfEmpty() + + // 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() + + 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); + + + + + + var responseList = query.Select(x => + { + + bool validToCreate = x.HasSalarySettings && !x.HasCheckout; + string message = "آماده تنظیم"; + CreateCheckoutStatus createCheckoutStatus = CreateCheckoutStatus.ReadyToCreate; + if (x.HasCheckout) + { + message = "موجود است"; + createCheckoutStatus = CreateCheckoutStatus.AlreadyCreated; + } + + + if (!x.HasSalarySettings) + { + message = "فاقد تنظیمات"; + createCheckoutStatus = CreateCheckoutStatus.NotSetSalaryPaymentSettings; + } + + + return new GetUserToGroupCreatingDto + { + UserId = x.UserId, + FullName = x.FullName, + IsValidToCreate = validToCreate, + StatusMessage = message, + CreateCheckoutStatus = createCheckoutStatus + + }; + + }).OrderByDescending(x=>x.IsValidToCreate).ToList(); + + var response = new GetUserToGroupCreatingResponse(responseList); + + return OperationResult.Success(response); + } +} + + +public record GetUserToGroupCreatingQuery(string Year, string Month) : IBaseQuery; + +public record GetUserToGroupCreatingResponse(List GetUserToGroupCreatingDtoList); + +public record GetUserToGroupCreatingDto +{ + /// + /// آی دی کاربر + /// + public long UserId { get; set; } + + /// + /// نام کامل پرسنل + /// + public string FullName { get; set; } + + + /// + /// پیام وضعیت ایجاد فیش + /// + public string StatusMessage { get; set; } + + /// + /// آیا مجاز به ایجاد فیش می باشد + /// + public bool IsValidToCreate { get; set; } + + public CreateCheckoutStatus CreateCheckoutStatus { get; set; } + +} + + +public record GetUserWhoHaveSettingsAndCheckoutDto +{ + /// + /// آی دی کاربر + /// + public long UserId { get; set; } + + /// + /// نام کامل پرسنل + /// + public string FullName { get; set; } + + /// + /// داشتن تنظیمات + /// + public bool HasSalarySettings { get; set; } + + + public bool HasCheckout { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommand.cs new file mode 100644 index 00000000..427904e0 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommand.cs @@ -0,0 +1,13 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddPhaseToProject; + +/// +/// Command to add a phase to an existing project +/// +public record AddPhaseToProjectCommand( + Guid ProjectId, + string Name, + string? Description = null, + int OrderIndex = 0 +) : IBaseCommand; diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommandHandler.cs new file mode 100644 index 00000000..3eadac95 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddPhaseToProject/AddPhaseToProjectCommandHandler.cs @@ -0,0 +1,47 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddPhaseToProject; + +public class AddPhaseToProjectCommandHandler : IRequestHandler +{ + private readonly IProjectRepository _projectRepository; + private readonly IUnitOfWork _unitOfWork; + + public AddPhaseToProjectCommandHandler( + IProjectRepository projectRepository, + IUnitOfWork unitOfWork) + { + _projectRepository = projectRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(AddPhaseToProjectCommand request, CancellationToken cancellationToken) + { + try + { + // Get project + var project = await _projectRepository.GetByIdAsync(request.ProjectId); + if (project == null) + { + return OperationResult.NotFound("پروژه یافت نشد"); + } + + // Add phase + var phase = project.AddPhase(request.Name, request.Description); + phase.SetOrderIndex(request.OrderIndex); + + // Save changes + await _unitOfWork.SaveChangesAsync(cancellationToken); + + return OperationResult.Success(); + } + catch (Exception ex) + { + return OperationResult.Failure($"خطا در افزودن فاز: {ex.Message}"); + } + } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs new file mode 100644 index 00000000..ba82f57c --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommand.cs @@ -0,0 +1,16 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddTaskToPhase; + +/// +/// Command to add a task to an existing phase +/// +public record AddTaskToPhaseCommand( + Guid PhaseId, + string Name, + string? Description = null, + TaskPriority Priority = TaskPriority.Medium, + int OrderIndex = 0, + DateTime? DueDate = null +) : IBaseCommand; diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs new file mode 100644 index 00000000..360811a7 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AddTaskToPhase/AddTaskToPhaseCommandHandler.cs @@ -0,0 +1,53 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AddTaskToPhase; + +public class AddTaskToPhaseCommandHandler : IRequestHandler +{ + private readonly IProjectPhaseRepository _phaseRepository; + private readonly IUnitOfWork _unitOfWork; + + public AddTaskToPhaseCommandHandler( + IProjectPhaseRepository phaseRepository, + IUnitOfWork unitOfWork) + { + _phaseRepository = phaseRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(AddTaskToPhaseCommand request, CancellationToken cancellationToken) + { + try + { + // Get phase + var phase = await _phaseRepository.GetByIdAsync(request.PhaseId); + if (phase == null) + { + return OperationResult.NotFound("فاز یافت نشد"); + } + + // Add task + var task = phase.AddTask(request.Name, request.Description); + task.SetPriority(request.Priority); + task.SetOrderIndex(request.OrderIndex); + + if (request.DueDate.HasValue) + { + task.SetDates(dueDate: request.DueDate); + } + + // Save changes + await _unitOfWork.SaveChangesAsync(cancellationToken); + + return OperationResult.Success(); + } + catch (Exception ex) + { + return OperationResult.Failure($"خطا در افزودن تسک: {ex.Message}"); + } + } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommand.cs new file mode 100644 index 00000000..805ddb50 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommand.cs @@ -0,0 +1,18 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject; + +public class AssignProjectCommand:IBaseCommand +{ + public List Items { get; set; } + public Guid Id { get; set; } + public ProjectHierarchyLevel Level { get; set; } + public bool CascadeToChildren { get; set; } +} + +public class AssignProjectCommandItem +{ + public long UserId { get; set; } + public Guid SkillId { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandHandler.cs new file mode 100644 index 00000000..7dddf33e --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandHandler.cs @@ -0,0 +1,274 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Domain.SkillAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject; + +public class AssignProjectCommandHandler:IBaseCommandHandler +{ + private readonly IUnitOfWork _unitOfWork; + private readonly IProjectRepository _projectRepository; + private readonly IProjectPhaseRepository _projectPhaseRepository; + private readonly IProjectTaskRepository _projectTaskRepository; + private readonly ISkillRepository _skillRepository; + private readonly IPhaseSectionRepository _phaseSectionRepository; + private readonly IProjectSectionRepository _projectSectionRepository; + private readonly ITaskSectionRepository _taskSectionRepository; + + + public AssignProjectCommandHandler( + IProjectRepository projectRepository, + IProjectPhaseRepository projectPhaseRepository, + IProjectTaskRepository projectTaskRepository, + IUnitOfWork unitOfWork, + ISkillRepository skillRepository, + IPhaseSectionRepository phaseSectionRepository, + IProjectSectionRepository projectSectionRepository, + ITaskSectionRepository taskSectionRepository) + { + _projectRepository = projectRepository; + _projectPhaseRepository = projectPhaseRepository; + _projectTaskRepository = projectTaskRepository; + _unitOfWork = unitOfWork; + _skillRepository = skillRepository; + _phaseSectionRepository = phaseSectionRepository; + _projectSectionRepository = projectSectionRepository; + _taskSectionRepository = taskSectionRepository; + } + + public async Task Handle(AssignProjectCommand request, CancellationToken cancellationToken) + { + switch (request.Level) + { + case ProjectHierarchyLevel.Project: + return await AssignProject(request); + case ProjectHierarchyLevel.Phase: + return await AssignProjectPhase(request); + case ProjectHierarchyLevel.Task: + return await AssignProjectTask(request); + default: + return OperationResult.Failure("سطح پروژه نامعتبر است"); + } + } + + private async Task AssignProject(AssignProjectCommand request) + { + var project = await _projectRepository.GetWithFullHierarchyAsync(request.Id); + if (project is null) + { + return OperationResult.NotFound("پروژه یافت نشد"); + } + + // تخصیص در سطح پروژه + foreach (var item in request.Items) + { + var skill = await _skillRepository.GetByIdAsync(item.SkillId); + if (skill is null) + { + return OperationResult.NotFound($"مهارت با شناسه {item.SkillId} یافت نشد"); + } + + // بررسی و به‌روزرسانی یا اضافه کردن ProjectSection + var existingSection = project.ProjectSections.FirstOrDefault(s => s.SkillId == item.SkillId); + if (existingSection != null) + { + // اگر وجود داشت، فقط userId را به‌روزرسانی کن + existingSection.UpdateUser(item.UserId); + } + else + { + // اگر وجود نداشت، اضافه کن + var newSection = new ProjectSection(project.Id, item.UserId, item.SkillId); + await _projectSectionRepository.CreateAsync(newSection); + } + } + + // حالا برای تمام فازها و تسک‌ها cascade کن + foreach (var phase in project.Phases) + { + // اگر CascadeToChildren true است یا فاز override ندارد + if (request.CascadeToChildren || !phase.HasAssignmentOverride) + { + // برای phase هم باید section‌ها را به‌روزرسانی کنیم + foreach (var item in request.Items) + { + var existingSection = phase.PhaseSections.FirstOrDefault(s => s.SkillId == item.SkillId); + if (existingSection != null) + { + existingSection.Update(item.UserId, item.SkillId); + } + else + { + var newPhaseSection = new PhaseSection(phase.Id, item.UserId, item.SkillId); + await _phaseSectionRepository.CreateAsync(newPhaseSection); + } + } + + foreach (var task in phase.Tasks) + { + // اگر CascadeToChildren true است یا تسک override ندارد + if (request.CascadeToChildren || !task.HasAssignmentOverride) + { + foreach (var item in request.Items) + { + var section = task.Sections.FirstOrDefault(s => s.SkillId == item.SkillId); + if (section != null) + { + // استفاده از TransferToUser + if (section.CurrentAssignedUserId != item.UserId) + { + if (section.CurrentAssignedUserId > 0) + { + section.TransferToUser(section.CurrentAssignedUserId, item.UserId); + } + else + { + section.AssignToUser(item.UserId); + } + } + } + else + { + var newTaskSection = new TaskSection(task.Id, item.SkillId, item.UserId); + await _taskSectionRepository.CreateAsync(newTaskSection); + } + } + } + } + } + } + + await _unitOfWork.SaveChangesAsync(); + return OperationResult.Success(); + } + + private async Task AssignProjectPhase(AssignProjectCommand request) + { + var phase = await _projectPhaseRepository.GetWithTasksAsync(request.Id); + if (phase is null) + { + return OperationResult.NotFound("فاز پروژه یافت نشد"); + } + + // تخصیص در سطح فاز + foreach (var item in request.Items) + { + var skill = await _skillRepository.GetByIdAsync(item.SkillId); + if (skill is null) + { + return OperationResult.NotFound($"مهارت با شناسه {item.SkillId} یافت نشد"); + } + } + + // علامت‌گذاری که این فاز نسبت به parent متمایز است + phase.MarkAsOverridden(); + + // به‌روزرسانی یا اضافه کردن PhaseSection + foreach (var item in request.Items) + { + var existingSection = phase.PhaseSections.FirstOrDefault(s => s.SkillId == item.SkillId); + if (existingSection != null) + { + // اگر وجود داشت، فقط userId را به‌روزرسانی کن + existingSection.Update(item.UserId, item.SkillId); + } + else + { + // اگر وجود نداشت، اضافه کن + var newPhaseSection = new PhaseSection(phase.Id, item.UserId, item.SkillId); + await _phaseSectionRepository.CreateAsync(newPhaseSection); + } + } + + // cascade به تمام تسک‌ها + foreach (var task in phase.Tasks) + { + // اگر CascadeToChildren true است یا تسک override ندارد + if (request.CascadeToChildren || !task.HasAssignmentOverride) + { + foreach (var item in request.Items) + { + var section = task.Sections.FirstOrDefault(s => s.SkillId == item.SkillId); + if (section != null) + { + // استفاده از TransferToUser + if (section.CurrentAssignedUserId != item.UserId) + { + if (section.CurrentAssignedUserId > 0) + { + section.TransferToUser(section.CurrentAssignedUserId, item.UserId); + } + else + { + section.AssignToUser(item.UserId); + } + } + } + else + { + var newTaskSection = new TaskSection(task.Id, item.SkillId, item.UserId); + await _taskSectionRepository.CreateAsync(newTaskSection); + } + } + } + } + + await _unitOfWork.SaveChangesAsync(); + return OperationResult.Success(); + } + + private async Task AssignProjectTask(AssignProjectCommand request) + { + var task = await _projectTaskRepository.GetWithSectionsAsync(request.Id); + if (task is null) + { + return OperationResult.NotFound("تسک یافت نشد"); + } + + foreach (var item in request.Items) + { + var skill = await _skillRepository.GetByIdAsync(item.SkillId); + if (skill is null) + { + return OperationResult.NotFound($"مهارت با شناسه {item.SkillId} یافت نشد"); + } + } + + // علامت‌گذاری که این تسک نسبت به parent متمایز است + task.MarkAsOverridden(); + + // به‌روزرسانی یا اضافه کردن TaskSection + foreach (var item in request.Items) + { + var section = task.Sections.FirstOrDefault(s => s.SkillId == item.SkillId); + if (section != null) + { + // اگر وجود داشت، از TransferToUser استفاده کن + if (section.CurrentAssignedUserId != item.UserId) + { + if (section.CurrentAssignedUserId > 0) + { + section.TransferToUser(section.CurrentAssignedUserId, item.UserId); + } + else + { + section.AssignToUser(item.UserId); + } + } + } + else + { + // اگر وجود نداشت، اضافه کن + var newTaskSection = new TaskSection(task.Id, item.SkillId, item.UserId); + await _taskSectionRepository.CreateAsync(newTaskSection); + } + } + + await _unitOfWork.SaveChangesAsync(); + return OperationResult.Success(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandValidator.cs new file mode 100644 index 00000000..6c1e80a8 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AssignProject/AssignProjectCommandValidator.cs @@ -0,0 +1,39 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject; + +public class AssignProjectCommandValidator : AbstractValidator +{ + public AssignProjectCommandValidator() + { + RuleFor(x => x.Id) + .NotEmpty() + .NotNull() + .WithMessage("شناسه پروژه نمیتواند خالی باشد"); + + RuleFor(x => x.CascadeToChildren) + .NotNull() + .WithMessage("مقدار CascadeToChildren نمیتواند خالی باشد"); + + RuleForEach(x => x.Items) + .SetValidator(new AssignProjectItemValidator()); + } +} + +public class AssignProjectItemValidator : AbstractValidator +{ + public AssignProjectItemValidator() + { + RuleFor(x => x.UserId) + .NotEmpty() + .NotNull() + .GreaterThan(0) + .WithMessage("شناسه کاربر نمیتواند خالی باشد"); + + + RuleFor(x => x.SkillId) + .NotEmpty() + .NotNull() + .WithMessage("شناسه مهارت نمیتواند خالی باشد"); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandHandler.cs new file mode 100644 index 00000000..9e37cdc8 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandHandler.cs @@ -0,0 +1,101 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain._Common.Exceptions; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection; + +public record ChangeStatusSectionCommand(Guid SectionId, TaskSectionStatus Status) : IBaseCommand; + +public class ChangeStatusSectionCommandHandler : IBaseCommandHandler +{ + private readonly IUnitOfWork _unitOfWork; + private readonly ITaskSectionRepository _taskSectionRepository; + private readonly IAuthHelper _authHelper; + + public ChangeStatusSectionCommandHandler(ITaskSectionRepository taskSectionRepository, + IUnitOfWork unitOfWork, IAuthHelper authHelper) + { + _taskSectionRepository = taskSectionRepository; + _unitOfWork = unitOfWork; + _authHelper = authHelper; + } + + public async Task Handle(ChangeStatusSectionCommand request, CancellationToken cancellationToken) + { + // استفاده از متد مخصوص که Activities رو load می‌کنه + var section = await _taskSectionRepository.GetByIdWithActivitiesAsync(request.SectionId, cancellationToken); + if (section == null) + return OperationResult.NotFound("بخش مورد نظر یافت نشد"); + + if (section.Status == request.Status) + return OperationResult.Success(); + + long currentUser = _authHelper.GetCurrentUserId() + ?? throw new UnAuthorizedException("کاربر احراز هویت نشده است"); + + // Validate state transitions + var validationResult = ValidateStateTransition(section.Status, request.Status); + if (!validationResult.IsSuccess) + return validationResult; + + // Handle state machine logic + if (section.Status == TaskSectionStatus.InProgress) + { + // Coming FROM InProgress: Stop the active activity + section.StopWork(currentUser, request.Status); + } + else if (request.Status == TaskSectionStatus.InProgress) + { + // Going TO InProgress: Start work and create activity + section.StartWork(currentUser); + } + else + { + // All other transitions: Just update status + section.UpdateStatus(request.Status); + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + /// + /// Validates state transitions based on business rules: + /// - ReadyToStart: شروع نشده - Initial state only, cannot return to it once left + /// - InProgress: درحال انجام - Can transition from ReadyToStart, can go to Incomplete or Completed + /// - Incomplete: نیمه کاره - Can come from InProgress or other states + /// - Completed: اتمام رسیده - Can come from InProgress or other states + /// + private OperationResult ValidateStateTransition(TaskSectionStatus currentStatus, TaskSectionStatus targetStatus) + { + // Cannot transition to ReadyToStart once the section has been started + if (targetStatus == TaskSectionStatus.ReadyToStart) + return OperationResult.ValidationError("بخش نمی‌تواند به وضعیت 'آماده برای شروع' تغییر کند"); + + // From ReadyToStart, can only go to InProgress + if (currentStatus == TaskSectionStatus.ReadyToStart && targetStatus != TaskSectionStatus.InProgress) + return OperationResult.ValidationError("از وضعیت 'آماده برای شروع' فقط می‌توان به 'درحال انجام' رفت"); + + // Valid transitions matrix + var validTransitions = new Dictionary> + { + { TaskSectionStatus.ReadyToStart, new List { TaskSectionStatus.InProgress } }, + { TaskSectionStatus.InProgress, new List { TaskSectionStatus.Incomplete, TaskSectionStatus.Completed } }, + { TaskSectionStatus.Incomplete, new List { TaskSectionStatus.InProgress, TaskSectionStatus.Completed } }, + { TaskSectionStatus.Completed, new List { TaskSectionStatus.InProgress, TaskSectionStatus.Incomplete } }, // Can return to InProgress or Incomplete + { TaskSectionStatus.NotAssigned, new List { TaskSectionStatus.InProgress, TaskSectionStatus.ReadyToStart } } + }; + + if (!validTransitions.TryGetValue(currentStatus, out var allowedTargets)) + return OperationResult.ValidationError($"وضعیت فعلی '{currentStatus}' نامعتبر است"); + + if (!allowedTargets.Contains(targetStatus)) + return OperationResult.ValidationError( + $"نمی‌توان از وضعیت '{currentStatus}' به '{targetStatus}' رفت"); + + return OperationResult.Success(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandValidator.cs new file mode 100644 index 00000000..1de430c9 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeStatusSection/ChangeStatusSectionCommandValidator.cs @@ -0,0 +1,20 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection; + +public class ChangeStatusSectionCommandValidator:AbstractValidator +{ + public ChangeStatusSectionCommandValidator() + { + RuleFor(c => c.SectionId) + .NotEmpty() + .NotNull() + .WithMessage("شناسه بخش نمی‌تواند خالی باشد"); + + RuleFor(c => c.Status) + .IsInEnum() + .NotEmpty() + .NotNull() + .WithMessage("وضعیت بخش نامعتبر است"); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs new file mode 100644 index 00000000..475e7aab --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommand.cs @@ -0,0 +1,7 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; + +public record CreateProjectCommand(string Name,ProjectHierarchyLevel Level, + Guid? ParentId):IBaseCommand; \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs new file mode 100644 index 00000000..1ba61509 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandHandler.cs @@ -0,0 +1,82 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain._Common.Exceptions; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; + +public class CreateProjectCommandHandler : IBaseCommandHandler +{ + private readonly IProjectRepository _projectRepository; + private readonly IProjectPhaseRepository _projectPhaseRepository; + private readonly IProjectTaskRepository _projectTaskRepository; + private readonly IUnitOfWork _unitOfWork; + + + public CreateProjectCommandHandler(IProjectRepository projectRepository, IUnitOfWork unitOfWork, IProjectTaskRepository projectTaskRepository, IProjectPhaseRepository projectPhaseRepository) + { + _projectRepository = projectRepository; + _unitOfWork = unitOfWork; + _projectTaskRepository = projectTaskRepository; + _projectPhaseRepository = projectPhaseRepository; + } + + public async Task Handle(CreateProjectCommand request, CancellationToken cancellationToken) + { + switch (request.Level) + { + case ProjectHierarchyLevel.Project: + await CreateProject(request); + break; + case ProjectHierarchyLevel.Phase: + await CreateProjectPhase(request); + break; + case ProjectHierarchyLevel.Task: + await CreateProjectTask(request); + break; + default: + return OperationResult.Failure("سطح پروژه نامعتبر است"); + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + private async Task CreateProject(CreateProjectCommand request) + { + var project = new Project(request.Name); + await _projectRepository.CreateAsync(project); + } + + private async Task CreateProjectPhase(CreateProjectCommand request) + { + if (!request.ParentId.HasValue) + throw new BadRequestException("برای ایجاد فاز، شناسه پروژه الزامی است"); + + if(!_projectRepository.Exists(x=>x.Id == request.ParentId.Value)) + { + throw new BadRequestException("والد پروژه یافت نشد"); + } + + var projectPhase = new ProjectPhase(request.Name, request.ParentId.Value); + await _projectPhaseRepository.CreateAsync(projectPhase); + } + + private async Task CreateProjectTask(CreateProjectCommand request) + { + if (!request.ParentId.HasValue) + throw new BadRequestException("برای ایجاد تسک، شناسه فاز الزامی است"); + + if(!_projectPhaseRepository.Exists(x=>x.Id == request.ParentId.Value)) + { + throw new BadRequestException("والد پروژه یافت نشد"); + } + + var projectTask = new ProjectTask(request.Name, request.ParentId.Value); + await _projectTaskRepository.CreateAsync(projectTask); + } +} + \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs new file mode 100644 index 00000000..790e1f79 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProject/CreateProjectCommandValidator.cs @@ -0,0 +1,26 @@ +using FluentValidation; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; + +public class CreateProjectCommandValidator:AbstractValidator +{ + public CreateProjectCommandValidator() + { + RuleFor(x => x.Name) + .NotEmpty() + .NotNull() + .WithMessage("نام نمیتواند خالی باشد"); + + RuleFor(y => y.Level) + .NotNull() + .IsInEnum(); + When(x=>x.Level>ProjectHierarchyLevel.Project,()=> + { + RuleFor(x => x.ParentId) + .NotNull() + .NotEmpty() + .WithMessage("شناسه والد نمیتواند خالی باشد"); + }); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommand.cs new file mode 100644 index 00000000..385f516d --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommand.cs @@ -0,0 +1,13 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProjectWithHierarchy; + +/// +/// Command to create a new project with the new hierarchy structure +/// +public record CreateProjectWithHierarchyCommand( + string Name, + string? Description = null, + DateTime? PlannedStartDate = null, + DateTime? PlannedEndDate = null +) : IBaseCommand; diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandHandler.cs new file mode 100644 index 00000000..0a899924 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandHandler.cs @@ -0,0 +1,49 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using MediatR; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProjectWithHierarchy; + +public class CreateProjectWithHierarchyCommandHandler : IRequestHandler +{ + private readonly IProjectRepository _projectRepository; + private readonly IUnitOfWork _unitOfWork; + + public CreateProjectWithHierarchyCommandHandler( + IProjectRepository projectRepository, + IUnitOfWork unitOfWork) + { + _projectRepository = projectRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(CreateProjectWithHierarchyCommand request, CancellationToken cancellationToken) + { + try + { + // Create new project + var project = new Project(request.Name, request.Description); + + // Set planned dates if provided + if (request.PlannedStartDate.HasValue || request.PlannedEndDate.HasValue) + { + project.SetPlannedDates(request.PlannedStartDate, request.PlannedEndDate); + } + + // Add to repository + await _projectRepository.CreateAsync(project); + + // Save changes + await _unitOfWork.SaveChangesAsync(cancellationToken); + + return OperationResult.Success(); + } + catch (Exception ex) + { + return OperationResult.Failure($"خطا در ایجاد پروژه: {ex.Message}"); + } + } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandValidator.cs new file mode 100644 index 00000000..2e425dc9 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/CreateProjectWithHierarchy/CreateProjectWithHierarchyCommandValidator.cs @@ -0,0 +1,21 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProjectWithHierarchy; + +public class CreateProjectWithHierarchyCommandValidator : AbstractValidator +{ + public CreateProjectWithHierarchyCommandValidator() + { + RuleFor(x => x.Name) + .NotEmpty().WithMessage("نام پروژه نمی‌تواند خالی باشد") + .MaximumLength(200).WithMessage("نام پروژه نمی‌تواند بیش از 200 کاراکتر باشد"); + + RuleFor(x => x.Description) + .MaximumLength(1000).WithMessage("توضیحات نمی‌تواند بیش از 1000 کاراکتر باشد") + .When(x => !string.IsNullOrEmpty(x.Description)); + + RuleFor(x => x) + .Must(x => x.PlannedStartDate == null || x.PlannedEndDate == null || x.PlannedStartDate <= x.PlannedEndDate) + .WithMessage("تاریخ شروع برنامه‌ریزی شده نمی‌تواند بعد از تاریخ پایان برنامه‌ریزی شده باشد"); + } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandHandler.cs new file mode 100644 index 00000000..57677395 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandHandler.cs @@ -0,0 +1,91 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain._Common.Exceptions; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject; + +public record DeleteProjectCommand(Guid Id,ProjectHierarchyLevel Level) : IBaseCommand; + +public class DeleteProjectCommandHandler : IBaseCommandHandler +{ + private readonly IUnitOfWork _unitOfWork; + private readonly IProjectRepository _projectRepository; + private readonly IProjectPhaseRepository _projectPhaseRepository; + private readonly IProjectTaskRepository _projectTaskRepository; + + public DeleteProjectCommandHandler( + IUnitOfWork unitOfWork, + IProjectRepository projectRepository, + IProjectPhaseRepository projectPhaseRepository, + IProjectTaskRepository projectTaskRepository) + { + _unitOfWork = unitOfWork; + _projectRepository = projectRepository; + _projectPhaseRepository = projectPhaseRepository; + _projectTaskRepository = projectTaskRepository; + } + + public async Task Handle(DeleteProjectCommand request, CancellationToken cancellationToken) + { + switch (request.Level) + { + case ProjectHierarchyLevel.Project: + await DeleteProject(request.Id); + break; + case ProjectHierarchyLevel.Phase: + await DeleteProjectPhase(request.Id); + break; + case ProjectHierarchyLevel.Task: + await DeleteProjectTask(request.Id); + break; + default: + return OperationResult.Failure("سطح پروژه نامعتبر است"); + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + private async Task DeleteProject(Guid projectId) + { + var projectWithPhases = await _projectRepository.GetWithFullHierarchyAsync(projectId); + + if (projectWithPhases == null) + throw new NotFoundException("پروژه یافت نشد"); + + // بررسی اینکه پروژه فاز یا زیرمجموعه دارد یا نه + if (projectWithPhases.Phases != null && projectWithPhases.Phases.Any()) + throw new BadRequestException("نمی‌توان پروژه‌ای را حذف کرد که دارای فاز است. ابتدا تمام فازها را حذف کنید."); + + _projectRepository.Remove(projectWithPhases); + } + + private async Task DeleteProjectPhase(Guid phaseId) + { + var phase = await _projectPhaseRepository.GetByIdAsync(phaseId); + + if (phase == null) + throw new NotFoundException("فاز پروژه یافت نشد"); + + // بررسی اینکه فاز تسک یا زیرمجموعه دارد یا نه + var phaseWithTasks = await _projectPhaseRepository.GetWithTasksAsync(phaseId); + if (phaseWithTasks?.Tasks != null && phaseWithTasks.Tasks.Any()) + throw new InvalidOperationException("نمی‌توان فازی را حذف کرد که دارای تسک است. ابتدا تمام تسک‌ها را حذف کنید."); + + _projectPhaseRepository.Remove(phase); + } + + private async Task DeleteProjectTask(Guid taskId) + { + var task = await _projectTaskRepository.GetByIdAsync(taskId); + + if (task == null) + throw new NotFoundException("تسک یافت نشد"); + + // حذف خود تسک + _projectTaskRepository.Remove(task); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandValidator.cs new file mode 100644 index 00000000..47ae2eeb --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/DeleteProject/DeleteProjectCommandValidator.cs @@ -0,0 +1,19 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject; + +public class DeleteProjectCommandValidator:AbstractValidator +{ + public DeleteProjectCommandValidator() + { + RuleFor(x=>x.Id) + .NotEmpty() + .NotNull() + .WithMessage("شناسه پروژه نمی‌تواند خالی باشد."); + RuleFor(x=>x.Level) + .IsInEnum() + .NotNull() + .WithMessage("سطح حذف پروژه نامعتبر است."); + + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandHandler.cs new file mode 100644 index 00000000..af993664 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandHandler.cs @@ -0,0 +1,80 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain._Common.Exceptions; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.EditProject; + +public record EditProjectCommand(string Name, Guid Id, ProjectHierarchyLevel Level): IBaseCommand; +public class EditProjectCommandHandler: IBaseCommandHandler +{ + private readonly IProjectRepository _projectRepository; + private readonly IProjectPhaseRepository _projectPhaseRepository; + private readonly IProjectTaskRepository _projectTaskRepository; + private readonly IUnitOfWork _unitOfWork; + + public EditProjectCommandHandler( + IProjectRepository projectRepository, + IProjectPhaseRepository projectPhaseRepository, + IProjectTaskRepository projectTaskRepository, + IUnitOfWork unitOfWork) + { + _projectRepository = projectRepository; + _projectPhaseRepository = projectPhaseRepository; + _projectTaskRepository = projectTaskRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(EditProjectCommand request, CancellationToken cancellationToken) + { + switch (request.Level) + { + case ProjectHierarchyLevel.Project: + await EditProject(request); + break; + case ProjectHierarchyLevel.Phase: + await EditProjectPhase(request); + break; + case ProjectHierarchyLevel.Task: + await EditProjectTask(request); + break; + default: + return OperationResult.Failure("سطح پروژه نامعتبر است"); + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + private async Task EditProject(EditProjectCommand request) + { + var project = await _projectRepository.GetByIdAsync(request.Id); + + if (project == null) + throw new NotFoundException("پروژه یافت نشد"); + + project.UpdateName(request.Name); + } + + private async Task EditProjectPhase(EditProjectCommand request) + { + var phase = await _projectPhaseRepository.GetByIdAsync(request.Id); + + if (phase == null) + throw new NotFoundException("فاز پروژه یافت نشد"); + + phase.UpdateName(request.Name); + } + + private async Task EditProjectTask(EditProjectCommand request) + { + var task = await _projectTaskRepository.GetByIdAsync(request.Id); + + if (task == null) + throw new NotFoundException("تسک یافت نشد"); + + task.UpdateName(request.Name); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandValidator.cs new file mode 100644 index 00000000..4c50a3b1 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/EditProject/EditProjectCommandValidator.cs @@ -0,0 +1,18 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.EditProject; + +public class EditProjectCommandValidator:AbstractValidator +{ + public EditProjectCommandValidator() + { + RuleFor(x => x.Name) + .NotEmpty() + .WithMessage("نام پروژه نمی‌تواند خالی باشد."); + + RuleFor(x=>x.Id) + .NotEmpty() + .NotNull().WithMessage("شناسه پروژه نمی‌تواند خالی باشد."); + + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommand.cs new file mode 100644 index 00000000..230754b5 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommand.cs @@ -0,0 +1,13 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application.Modules.Projects.DTOs; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; + +public record SetTimeProjectCommand(List SectionItems, Guid Id, ProjectHierarchyLevel Level):IBaseCommand; + +public class SetTimeSectionTime +{ + public string Description { get; set; } + public int Hours { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs new file mode 100644 index 00000000..3b1a7b1f --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs @@ -0,0 +1,164 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Projects.DTOs; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; + +public class SetTimeProjectCommandHandler:IBaseCommandHandler +{ + private readonly IProjectRepository _projectRepository; + private readonly IProjectPhaseRepository _projectPhaseRepository; + private readonly IProjectTaskRepository _projectTaskRepository; + private readonly IUnitOfWork _unitOfWork; + private readonly IAuthHelper _authHelper; + private long? _userId; + + + public SetTimeProjectCommandHandler( + IProjectRepository projectRepository, + IProjectPhaseRepository projectPhaseRepository, + IProjectTaskRepository projectTaskRepository, + IUnitOfWork unitOfWork, IAuthHelper authHelper) + { + _projectRepository = projectRepository; + _projectPhaseRepository = projectPhaseRepository; + _projectTaskRepository = projectTaskRepository; + _unitOfWork = unitOfWork; + _authHelper = authHelper; + _userId = authHelper.GetCurrentUserId(); + } + + public async Task Handle(SetTimeProjectCommand request, CancellationToken cancellationToken) + { + switch (request.Level) + { + case ProjectHierarchyLevel.Task: + return await SetTimeForProjectTask(request, cancellationToken); + default: + return OperationResult.Failure("سطح پروژه نامعتبر است"); + + } + } + + private async Task SetTimeForProject(SetTimeProjectCommand request, CancellationToken cancellationToken) + { + var project = await _projectRepository.GetWithFullHierarchyAsync(request.Id); + if (project == null) + { + return OperationResult.NotFound("پروژه یافت نشد"); + return OperationResult.NotFound("���� ���� ���"); + } + + long? addedByUserId = _userId; + + // تنظیم زمان برای تمام sections در تمام فازها و تسک‌های پروژه + foreach (var phase in project.Phases) + { + foreach (var task in phase.Tasks) + { + foreach (var section in task.Sections) + { + var sectionItem = request.SectionItems.FirstOrDefault(si => si.SectionId == section.Id); + if (sectionItem != null) + { + SetSectionTime(section, sectionItem, addedByUserId); + } + } + } + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + private async Task SetTimeForProjectPhase(SetTimeProjectCommand request, CancellationToken cancellationToken) + { + var phase = await _projectPhaseRepository.GetWithTasksAsync(request.Id); + if (phase == null) + { + return OperationResult.NotFound("فاز پروژه یافت نشد"); + return OperationResult.NotFound("��� ���� ���� ���"); + } + + long? addedByUserId = _userId; + + // تنظیم زمان برای تمام sections در تمام تسک‌های این فاز + foreach (var task in phase.Tasks) + { + foreach (var section in task.Sections) + { + var sectionItem = request.SectionItems.FirstOrDefault(si => si.SectionId == section.Id); + if (sectionItem != null) + { + SetSectionTime(section, sectionItem, addedByUserId); + } + } + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + private async Task SetTimeForProjectTask(SetTimeProjectCommand request, CancellationToken cancellationToken) + { + var task = await _projectTaskRepository.GetWithSectionsAsync(request.Id); + if (task == null) + { + return OperationResult.NotFound("تسک یافت نشد"); + return OperationResult.NotFound("�Ә ���� ���"); + } + + long? addedByUserId = _userId; + + // تنظیم زمان مستقیماً برای sections این تسک + foreach (var section in task.Sections) + { + var sectionItem = request.SectionItems.FirstOrDefault(si => si.SectionId == section.Id); + if (sectionItem != null) + { + SetSectionTime(section, sectionItem, addedByUserId); + } + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + + private void SetSectionTime(TaskSection section, SetTimeProjectSectionItem sectionItem, long? addedByUserId) + { + var initData = sectionItem.InitData; + var initialTime = TimeSpan.FromHours(initData.Hours); + + // تنظیم زمان اولیه + section.UpdateInitialEstimatedHours(initialTime, initData.Description); + + section.ClearAdditionalTimes(); + // افزودن زمان‌های اضافی + foreach (var additionalTime in sectionItem.AdditionalTime) + { + var additionalTimeSpan = TimeSpan.FromHours(additionalTime.Hours); + section.AddAdditionalTime(additionalTimeSpan, additionalTime.Description, addedByUserId); + } + } + + // private void SetSectionTime(ProjectSection section, SetTimeProjectSectionItem sectionItem, long? addedByUserId) + // { + // var initData = sectionItem.InitData; + // var initialTime = TimeSpan.FromHours(initData.Hours); + // + // // تنظیم زمان اولیه + // section.UpdateInitialEstimatedHours(initialTime, initData.Description); + // + // section.ClearAdditionalTimes(); + // // افزودن زمان‌های اضافی + // foreach (var additionalTime in sectionItem.AdditionalTime) + // { + // var additionalTimeSpan = TimeSpan.FromHours(additionalTime.Hours); + // section.AddAdditionalTime(additionalTimeSpan, additionalTime.Description, addedByUserId); + // } + // } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandValidator.cs new file mode 100644 index 00000000..7fb182b7 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandValidator.cs @@ -0,0 +1,50 @@ +using FluentValidation; +using GozareshgirProgramManager.Application.Modules.Projects.DTOs; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; + +public class SetTimeProjectCommandValidator:AbstractValidator +{ + public SetTimeProjectCommandValidator() + { + RuleFor(x=>x.Id) + .NotEmpty() + .NotNull() + .WithMessage("شناسه پروژه نمی‌تواند خالی باشد."); + + RuleForEach(x => x.SectionItems) + .SetValidator(command => new SetTimeProjectSectionItemValidator()); + + } +} +public class SetTimeProjectSectionItemValidator:AbstractValidator +{ + public SetTimeProjectSectionItemValidator() + { + RuleFor(x=>x.SectionId) + .NotEmpty() + .NotNull() + .WithMessage("شناسه بخش نمی‌تواند خالی باشد."); + + RuleFor(x=>x.InitData) + .SetValidator(new TimeDataValidator()); + + RuleForEach(x=>x.AdditionalTime) + .SetValidator(new TimeDataValidator()); + } +} + +public class TimeDataValidator : AbstractValidator +{ + public TimeDataValidator() + { + RuleFor(x => x.Hours) + .GreaterThanOrEqualTo(0) + .WithMessage("ساعت نمی‌تواند منفی باشد."); + + RuleFor(x=>x.Description) + .MaximumLength(500) + .WithMessage("توضیحات نمی‌تواند بیشتر از 500 کاراکتر باشد."); + + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommand.cs new file mode 100644 index 00000000..b32f49a2 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommand.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; + +public record TransferSectionCommand : IBaseCommand +{ + public Guid SectionId { get; set; } + public long FromUserId { get; set; } + public long ToUserId { get; set; } + public string? Notes { get; set; } +} + 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 new file mode 100644 index 00000000..4f27773a --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandHandler.cs @@ -0,0 +1,69 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Domain.UserAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; + +public class TransferSectionCommandHandler : IBaseCommandHandler +{ + private readonly IUnitOfWork _unitOfWork; + private readonly ITaskSectionRepository _taskSectionRepository; + private readonly IUserRepository _userRepository; + + public TransferSectionCommandHandler( + ITaskSectionRepository taskSectionRepository, + IUserRepository userRepository, + IUnitOfWork unitOfWork) + { + _taskSectionRepository = taskSectionRepository; + _userRepository = userRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(TransferSectionCommand request, CancellationToken cancellationToken) + { + // دریافت section با activities + var section = await _taskSectionRepository.GetByIdWithActivitiesAsync(request.SectionId, cancellationToken); + if (section == null) + { + return OperationResult.NotFound("بخش پروژه یافت نشد"); + } + + // بررسی وجود کاربر مبدا + var fromUser = await _userRepository.GetByIdAsync(request.FromUserId); + if (fromUser == null) + { + return OperationResult.NotFound($"کاربر مبدا با شناسه {request.FromUserId} یافت نشد"); + } + + // بررسی وجود کاربر مقصد + var toUser = await _userRepository.GetByIdAsync(request.ToUserId); + if (toUser == null) + { + return OperationResult.NotFound($"کاربر مقصد با شناسه {request.ToUserId} یافت نشد"); + } + + // بررسی اینکه کاربر مبدا و مقصد یکسان نباشند + if (request.FromUserId == request.ToUserId) + { + return OperationResult.Failure("کاربر مبدا و مقصد نمی‌توانند یکسان باشند"); + } + + try + { + // انتقال به کاربر جدید + section.TransferToUser(request.FromUserId, request.ToUserId); + + await _unitOfWork.SaveChangesAsync(cancellationToken); + + return OperationResult.Success(); + } + catch (InvalidOperationException ex) + { + return OperationResult.Failure(ex.Message); + } + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandValidator.cs new file mode 100644 index 00000000..e7b041f3 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/TransferSection/TransferSectionCommandValidator.cs @@ -0,0 +1,28 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; + +public class TransferSectionCommandValidator : AbstractValidator +{ + public TransferSectionCommandValidator() + { + RuleFor(x => x.SectionId) + .NotEmpty() + .WithMessage("شناسه بخش نمیتواند خالی باشد"); + + RuleFor(x => x.FromUserId) + .NotEmpty() + .GreaterThan(0) + .WithMessage("شناسه کاربر مبدا نمیتواند خالی یا صفر باشد"); + + RuleFor(x => x.ToUserId) + .NotEmpty() + .GreaterThan(0) + .WithMessage("شناسه کاربر مقصد نمیتواند خالی یا صفر باشد"); + + RuleFor(x => x) + .Must(x => x.FromUserId != x.ToUserId) + .WithMessage("کاربر مبدا و مقصد نمی‌توانند یکسان باشند"); + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs new file mode 100644 index 00000000..3cbc8cec --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/ProjectHierarchyDtos.cs @@ -0,0 +1,127 @@ +namespace GozareshgirProgramManager.Application.Modules.Projects.DTOs; + +/// +/// DTO for Project entity +/// +public class ProjectDto +{ + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Description { get; set; } + public DateTime CreationDate { get; set; } + public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } + public DateTime? PlannedStartDate { get; set; } + public DateTime? PlannedEndDate { get; set; } + public string Status { get; set; } = string.Empty; + public TimeSpan? AllocatedTime { get; set; } + public bool HasTimeOverride { get; set; } + public bool HasAssignmentOverride { get; set; } + public TimeSpan TotalTimeSpent { get; set; } + public TimeSpan TotalEstimatedTime { get; set; } + + public List Phases { get; set; } = new(); +} + +/// +/// DTO for ProjectPhase entity +/// +public class ProjectPhaseDto +{ + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Description { get; set; } + public DateTime CreationDate { get; set; } + public Guid ProjectId { get; set; } + public string Status { get; set; } = string.Empty; + public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } + public int OrderIndex { get; set; } + public TimeSpan? AllocatedTime { get; set; } + public bool HasTimeOverride { get; set; } + public bool HasAssignmentOverride { get; set; } + public TimeSpan TotalTimeSpent { get; set; } + public TimeSpan TotalEstimatedTime { get; set; } + + public List Tasks { get; set; } = new(); +} + +/// +/// DTO for ProjectTask entity +/// +public class ProjectTaskDto +{ + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Description { get; set; } + public DateTime CreationDate { get; set; } + public Guid PhaseId { get; set; } + public string Status { get; set; } = string.Empty; + public string Priority { get; set; } = string.Empty; + public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } + public DateTime? DueDate { get; set; } + public int OrderIndex { get; set; } + public TimeSpan? AllocatedTime { get; set; } + public bool HasTimeOverride { get; set; } + public bool HasAssignmentOverride { get; set; } + public TimeSpan TotalTimeSpent { get; set; } + public TimeSpan TotalEstimatedTime { get; set; } + + public List Sections { get; set; } = new(); +} + +/// +/// DTO for TaskSection entity +/// +public class ProjectSectionDto +{ + public Guid Id { get; set; } + public Guid TaskId { get; set; } + public Guid SkillId { get; set; } + public string SkillName { get; set; } = string.Empty; + public TimeSpan InitialEstimatedHours { get; set; } + public string? InitialDescription { get; set; } + public string Status { get; set; } = string.Empty; + public long CurrentAssignedUserId { get; set; } + public string? CurrentAssignedUserName { get; set; } + public DateTime CreationDate { get; set; } + + public TimeSpan FinalEstimatedHours { get; set; } + public TimeSpan TotalTimeSpent { get; set; } + public bool IsCompleted { get; set; } + public bool IsInProgress { get; set; } + + public List Activities { get; set; } = new(); + public List AdditionalTimes { get; set; } = new(); +} + +/// +/// DTO for ProjectSectionActivity entity +/// +public class TaskSectionActivityDto +{ + public Guid Id { get; set; } + public Guid SectionId { get; set; } + public long UserId { get; set; } + public string? UserName { get; set; } + public DateTime StartDate { get; set; } + public DateTime? EndDate { get; set; } + public string? Notes { get; set; } + public string? EndNotes { get; set; } + public bool IsActive { get; set; } + public TimeSpan TimeSpent { get; set; } +} + +/// +/// DTO for ProjectSectionAdditionalTime entity +/// +public class TaskSectionAdditionalTimeDto +{ + public Guid Id { get; set; } + public TimeSpan Hours { get; set; } + public string? Reason { get; set; } + public long? AddedByUserId { get; set; } + public string? AddedByUserName { get; set; } + public DateTime AddedAt { get; set; } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/SetTimeProjectSectionItem.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/SetTimeProjectSectionItem.cs new file mode 100644 index 00000000..04566e4e --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/DTOs/SetTimeProjectSectionItem.cs @@ -0,0 +1,10 @@ +using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; + +namespace GozareshgirProgramManager.Application.Modules.Projects.DTOs; + +public class SetTimeProjectSectionItem +{ + public Guid SectionId { get; set; } + public SetTimeSectionTime InitData { get; set; } + public List AdditionalTime { get; set; } = []; +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs new file mode 100644 index 00000000..67ce006e --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Extensions/ProjectMappingExtensions.cs @@ -0,0 +1,258 @@ +using GozareshgirProgramManager.Application.Modules.Projects.DTOs; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Extensions; + +/// +/// Mapping extensions for project hierarchy entities to DTOs +/// +public static class ProjectMappingExtensions +{ + #region Project Mappings + + public static ProjectDto ToDto(this Project project) + { + return new ProjectDto + { + Id = project.Id, + Name = project.Name, + Description = project.Description, + CreationDate = project.CreationDate, + StartDate = project.StartDate, + EndDate = project.EndDate, + PlannedStartDate = project.PlannedStartDate, + PlannedEndDate = project.PlannedEndDate, + Status = project.Status.ToString(), + HasAssignmentOverride = project.HasAssignmentOverride, + TotalTimeSpent = project.GetTotalTimeSpent(), + TotalEstimatedTime = project.GetTotalEstimatedTime(), + Phases = project.Phases.Select(p => p.ToDto()).ToList() + }; + } + + public static ProjectDto ToSummaryDto(this Project project) + { + return new ProjectDto + { + Id = project.Id, + Name = project.Name, + Description = project.Description, + CreationDate = project.CreationDate, + StartDate = project.StartDate, + EndDate = project.EndDate, + PlannedStartDate = project.PlannedStartDate, + PlannedEndDate = project.PlannedEndDate, + Status = project.Status.ToString(), + HasAssignmentOverride = project.HasAssignmentOverride, + TotalTimeSpent = project.GetTotalTimeSpent(), + TotalEstimatedTime = project.GetTotalEstimatedTime() + // No phases for summary + }; + } + + #endregion + + #region Phase Mappings + + public static ProjectPhaseDto ToDto(this ProjectPhase phase) + { + return new ProjectPhaseDto + { + Id = phase.Id, + Name = phase.Name, + Description = phase.Description, + CreationDate = phase.CreationDate, + ProjectId = phase.ProjectId, + Status = phase.Status.ToString(), + StartDate = phase.StartDate, + EndDate = phase.EndDate, + OrderIndex = phase.OrderIndex, + HasAssignmentOverride = phase.HasAssignmentOverride, + TotalTimeSpent = phase.GetTotalTimeSpent(), + TotalEstimatedTime = phase.GetTotalEstimatedTime(), + Tasks = phase.Tasks.Select(t => t.ToDto()).ToList() + }; + } + + public static ProjectPhaseDto ToSummaryDto(this ProjectPhase phase) + { + return new ProjectPhaseDto + { + Id = phase.Id, + Name = phase.Name, + Description = phase.Description, + CreationDate = phase.CreationDate, + ProjectId = phase.ProjectId, + Status = phase.Status.ToString(), + StartDate = phase.StartDate, + EndDate = phase.EndDate, + OrderIndex = phase.OrderIndex, + HasAssignmentOverride = phase.HasAssignmentOverride, + TotalTimeSpent = phase.GetTotalTimeSpent(), + TotalEstimatedTime = phase.GetTotalEstimatedTime() + // No tasks for summary + }; + } + + #endregion + + #region Task Mappings + + public static ProjectTaskDto ToDto(this ProjectTask task) + { + return new ProjectTaskDto + { + Id = task.Id, + Name = task.Name, + Description = task.Description, + CreationDate = task.CreationDate, + PhaseId = task.PhaseId, + Status = task.Status.ToString(), + Priority = task.Priority.ToString(), + StartDate = task.StartDate, + EndDate = task.EndDate, + DueDate = task.DueDate, + OrderIndex = task.OrderIndex, + AllocatedTime = task.AllocatedTime, + HasTimeOverride = task.HasTimeOverride, + HasAssignmentOverride = task.HasAssignmentOverride, + TotalTimeSpent = task.GetTotalTimeSpent(), + TotalEstimatedTime = task.GetTotalEstimatedTime(), + Sections = task.Sections.Select(s => s.ToDto()).ToList() + }; + } + + public static ProjectTaskDto ToSummaryDto(this ProjectTask task) + { + return new ProjectTaskDto + { + Id = task.Id, + Name = task.Name, + Description = task.Description, + CreationDate = task.CreationDate, + PhaseId = task.PhaseId, + Status = task.Status.ToString(), + Priority = task.Priority.ToString(), + StartDate = task.StartDate, + EndDate = task.EndDate, + DueDate = task.DueDate, + OrderIndex = task.OrderIndex, + AllocatedTime = task.AllocatedTime, + HasTimeOverride = task.HasTimeOverride, + HasAssignmentOverride = task.HasAssignmentOverride, + TotalTimeSpent = task.GetTotalTimeSpent(), + TotalEstimatedTime = task.GetTotalEstimatedTime() + // No sections for summary + }; + } + + #endregion + + #region Section Mappings + + public static ProjectSectionDto ToDto(this TaskSection section) + { + return new ProjectSectionDto + { + Id = section.Id, + TaskId = section.TaskId, + SkillId = section.SkillId, + SkillName = section.Skill?.Name ?? string.Empty, + InitialEstimatedHours = section.InitialEstimatedHours, + InitialDescription = section.InitialDescription, + Status = section.Status.ToString(), + CurrentAssignedUserId = section.CurrentAssignedUserId, + CreationDate = section.CreationDate, + FinalEstimatedHours = section.FinalEstimatedHours, + TotalTimeSpent = section.GetTotalTimeSpent(), + IsCompleted = section.IsCompleted(), + IsInProgress = section.IsInProgress(), + Activities = section.Activities.Select(a => a.ToDto()).ToList(), + AdditionalTimes = section.AdditionalTimes.Select(at => at.ToDto()).ToList() + }; + } + + public static ProjectSectionDto ToSummaryDto(this TaskSection section) + { + return new ProjectSectionDto + { + Id = section.Id, + TaskId = section.TaskId, + SkillId = section.SkillId, + SkillName = section.Skill?.Name ?? string.Empty, + InitialEstimatedHours = section.InitialEstimatedHours, + InitialDescription = section.InitialDescription, + Status = section.Status.ToString(), + CurrentAssignedUserId = section.CurrentAssignedUserId, + CreationDate = section.CreationDate, + FinalEstimatedHours = section.FinalEstimatedHours, + TotalTimeSpent = section.GetTotalTimeSpent(), + IsCompleted = section.IsCompleted(), + IsInProgress = section.IsInProgress() + // No activities or additional times for summary + }; + } + + #endregion + + #region Activity Mappings + + public static TaskSectionActivityDto ToDto(this TaskSectionActivity activity) + { + return new TaskSectionActivityDto + { + Id = activity.Id, + SectionId = activity.SectionId, + UserId = activity.UserId, + StartDate = activity.StartDate, + EndDate = activity.EndDate, + Notes = activity.Notes, + EndNotes = activity.EndNotes, + IsActive = activity.IsActive, + TimeSpent = activity.GetTimeSpent() + }; + } + + #endregion + + #region Additional Time Mappings + + public static TaskSectionAdditionalTimeDto ToDto(this TaskSectionAdditionalTime additionalTime) + { + return new TaskSectionAdditionalTimeDto + { + Id = additionalTime.Id, + Hours = additionalTime.Hours, + Reason = additionalTime.Reason, + AddedByUserId = additionalTime.AddedByUserId, + AddedAt = additionalTime.AddedAt + }; + } + + #endregion + + #region Collection Mappings + + public static List ToSummaryDtos(this IEnumerable projects) + { + return projects.Select(p => p.ToSummaryDto()).ToList(); + } + + public static List ToSummaryDtos(this IEnumerable phases) + { + return phases.Select(p => p.ToSummaryDto()).ToList(); + } + + public static List ToSummaryDtos(this IEnumerable tasks) + { + return tasks.Select(t => t.ToSummaryDto()).ToList(); + } + + public static List ToSummaryDtos(this IEnumerable sections) + { + return sections.Select(s => s.ToSummaryDto()).ToList(); + } + + #endregion +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectAssignDetails/GetProjectAssignDetailsQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectAssignDetails/GetProjectAssignDetailsQueryHandler.cs new file mode 100644 index 00000000..7932fd4c --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectAssignDetails/GetProjectAssignDetailsQueryHandler.cs @@ -0,0 +1,122 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectAssignDetails; + +public record GetProjectAssignDetailsResponse(List Items); + +public record GetProjectAssignSectionDetails(string Skill,Guid SkillId,Guid? SectionId,long UserId); + +public record GetProjectAssignDetailsQuery(Guid Id,ProjectHierarchyLevel Level) : IBaseQuery; + +public class GetProjectAssignDetailsQueryHandler:IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _dbContext; + + public GetProjectAssignDetailsQueryHandler(IProgramManagerDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task> Handle(GetProjectAssignDetailsQuery request, CancellationToken cancellationToken) + { + switch (request.Level) + { + case ProjectHierarchyLevel.Project: + return await GetProjectAssignDetails(request.Id, cancellationToken); + case ProjectHierarchyLevel.Phase: + return await GetPhaseAssignDetails(request.Id, cancellationToken); + case ProjectHierarchyLevel.Task: + return await GetTaskAssignDetails(request.Id, cancellationToken); + default: + return OperationResult.Failure("سطح پروژه نامعتبر است"); + } + } + + private async Task> GetProjectAssignDetails(Guid projectId, CancellationToken cancellationToken) + { + // گرفتن تمام فازهای پروژه + + var skills = _dbContext.Skills.ToList(); + var sectionsData =await _dbContext.ProjectSections + .Where(p => p.ProjectId == projectId).ToListAsync(cancellationToken); + + if (skills.Count == 0) + { + return OperationResult.Success(new GetProjectAssignDetailsResponse(new List())); + } + var sections = skills.Select(x=> + { + var section = sectionsData.FirstOrDefault(s => s.SkillId == x.Id); + + return new GetProjectAssignSectionDetails( + x.Name, + x.Id, + section?.Id, + section?.UserId ?? 0 + ); + + }).ToList(); + var response = new GetProjectAssignDetailsResponse(sections); + return OperationResult.Success(response); + } + + private async Task> GetPhaseAssignDetails(Guid phaseId, CancellationToken cancellationToken) + { + var skills = _dbContext.Skills.ToList(); + + var sectionsData =await _dbContext.PhaseSections + .Where(p => p.PhaseId == phaseId) + .ToListAsync(cancellationToken: cancellationToken); + + if (skills.Count == 0) + { + return OperationResult.Success(new GetProjectAssignDetailsResponse(new List())); + } + + var sections = skills.Select(x=> + { + var section = sectionsData.FirstOrDefault(s => s.SkillId == x.Id); + + return new GetProjectAssignSectionDetails( + x.Name, + x.Id, + section?.Id, + section?.UserId ?? 0 + ); + + }).ToList(); + + var response = new GetProjectAssignDetailsResponse(sections); + return OperationResult.Success(response); + } + + private async Task> GetTaskAssignDetails(Guid taskId, CancellationToken cancellationToken) + { + var skills = _dbContext.Skills.ToList(); + var sectionsData =await _dbContext.TaskSections + .Where(p => p.TaskId == taskId).ToListAsync(cancellationToken); + + if (skills.Count == 0) + { + return OperationResult.Success(new GetProjectAssignDetailsResponse(new List())); + } + var sections = skills.Select(x=> + { + var section = sectionsData.FirstOrDefault(s => s.SkillId == x.Id); + + return new GetProjectAssignSectionDetails( + x.Name, + x.Id, + section?.Id, + section?.OriginalAssignedUserId ?? 0 + ); + + }).ToList(); + + var response = new GetProjectAssignDetailsResponse(sections); + return OperationResult.Success(response); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs new file mode 100644 index 00000000..74a58946 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectListDto.cs @@ -0,0 +1,18 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; +public record GetProjectListDto +{ + public Guid Id { get; init; } + public string Name { get; init; } = string.Empty; + public int Percentage { get; init; } + public ProjectHierarchyLevel Level { get; init; } + public Guid? ParentId { get; init; } + public bool HasFront { get; set; } + public bool HasBackend { get; set; } + public bool HasDesign { get; set; } + +} + + + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQuery.cs new file mode 100644 index 00000000..472af143 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQuery.cs @@ -0,0 +1,8 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; + +public record GetProjectsListQuery(ProjectHierarchyLevel HierarchyLevel, + Guid? ParentId) : IBaseQuery; + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs new file mode 100644 index 00000000..523943aa --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs @@ -0,0 +1,303 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; + +public class GetProjectsListQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetProjectsListQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetProjectsListQuery request, CancellationToken cancellationToken) + { + List projects; + + switch (request.HierarchyLevel) + { + case ProjectHierarchyLevel.Project: + projects = await GetProjects(request.ParentId, cancellationToken); + break; + case ProjectHierarchyLevel.Phase: + projects = await GetPhases(request.ParentId, cancellationToken); + break; + case ProjectHierarchyLevel.Task: + projects = await GetTasks(request.ParentId, cancellationToken); + break; + default: + return OperationResult.Failure("سطح سلسله مراتب نامعتبر است"); + } + await SetSkillFlags(projects, cancellationToken); + + var response = new GetProjectsListResponse(projects); + return OperationResult.Success(response); + } + + private async Task> GetProjects(Guid? parentId, CancellationToken cancellationToken) + { + var query = _context.Projects.AsQueryable(); + + // پروژه‌ها سطح بالا هستند و parentId ندارند، فقط در صورت null بودن parentId نمایش داده می‌شوند + if (parentId.HasValue) + { + return new List(); // پروژه‌ها parent ندارند + } + + var projects = await query + .OrderByDescending(p => p.CreationDate) + .ToListAsync(cancellationToken); + var result = new List(); + + foreach (var project in projects) + { + var percentage = await CalculateProjectPercentage(project, cancellationToken); + result.Add(new GetProjectListDto + { + Id = project.Id, + Name = project.Name, + Level = ProjectHierarchyLevel.Project, + ParentId = null, + Percentage = percentage + }); + } + + return result; + } + + private async Task> GetPhases(Guid? parentId, CancellationToken cancellationToken) + { + var query = _context.ProjectPhases.AsQueryable(); + + if (parentId.HasValue) + { + query = query.Where(x => x.ProjectId == parentId); + } + + var phases = await query + .OrderByDescending(p => p.CreationDate) + .ToListAsync(cancellationToken); + var result = new List(); + + foreach (var phase in phases) + { + var percentage = await CalculatePhasePercentage(phase, cancellationToken); + result.Add(new GetProjectListDto + { + Id = phase.Id, + Name = phase.Name, + Level = ProjectHierarchyLevel.Phase, + ParentId = phase.ProjectId, + Percentage = percentage + }); + } + + return result; + } + + private async Task> GetTasks(Guid? parentId, CancellationToken cancellationToken) + { + var query = _context.ProjectTasks.AsQueryable(); + + if (parentId.HasValue) + { + query = query.Where(x => x.PhaseId == parentId); + } + + var tasks = await query + .OrderByDescending(t => t.CreationDate) + .ToListAsync(cancellationToken); + var result = new List(); + + foreach (var task in tasks) + { + var percentage = await CalculateTaskPercentage(task, cancellationToken); + result.Add(new GetProjectListDto + { + Id = task.Id, + Name = task.Name, + Level = ProjectHierarchyLevel.Task, + ParentId = task.PhaseId, + Percentage = percentage + }); + } + + return result; + } + + private async Task SetSkillFlags(List projects, CancellationToken cancellationToken) + { + var projectIds = projects.Select(x => x.Id).ToList(); + + // تنها تسک‌ها sections دارند، بنابراین برای سطوح مختلف باید متفاوت عمل کنیم + List taskIds; + + switch (projects.FirstOrDefault()?.Level) + { + case ProjectHierarchyLevel.Project: + // برای پروژه‌ها، باید تمام تسک‌های زیرمجموعه را پیدا کنیم + var phaseIds = await _context.ProjectPhases + .Where(ph => projectIds.Contains(ph.ProjectId)) + .Select(ph => ph.Id) + .ToListAsync(cancellationToken); + + taskIds = await _context.ProjectTasks + .Where(t => phaseIds.Contains(t.PhaseId)) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + break; + + case ProjectHierarchyLevel.Phase: + // برای فازها، تمام تسک‌های آن فازها را پیدا کنیم + taskIds = await _context.ProjectTasks + .Where(t => projectIds.Contains(t.PhaseId)) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + break; + + case ProjectHierarchyLevel.Task: + // برای تسک‌ها، خود آنها taskIds هستند + taskIds = projectIds; + break; + + default: + return; + } + + if (!taskIds.Any()) + return; + + var sections = await _context.TaskSections + .Include(x => x.Skill) + .Where(x => taskIds.Contains(x.TaskId)) + .ToListAsync(cancellationToken); + + foreach (var project in projects) + { + List relevantTaskIds; + + switch (project.Level) + { + case ProjectHierarchyLevel.Project: + // برای پروژه، تمام تسک‌های زیرمجموعه + var projectPhaseIds = await _context.ProjectPhases + .Where(ph => ph.ProjectId == project.Id) + .Select(ph => ph.Id) + .ToListAsync(cancellationToken); + + relevantTaskIds = await _context.ProjectTasks + .Where(t => projectPhaseIds.Contains(t.PhaseId)) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + break; + + case ProjectHierarchyLevel.Phase: + // برای فاز، تمام تسک‌های آن فاز + relevantTaskIds = await _context.ProjectTasks + .Where(t => t.PhaseId == project.Id) + .Select(t => t.Id) + .ToListAsync(cancellationToken); + break; + + case ProjectHierarchyLevel.Task: + // برای تسک، خود آن + relevantTaskIds = new List { project.Id }; + break; + + default: + continue; + } + + var projectSections = sections.Where(x => relevantTaskIds.Contains(x.TaskId)).ToList(); + project.HasBackend = projectSections.Any(x => x.Skill.Name == "Backend"); + project.HasFront = projectSections.Any(x => x.Skill.Name == "Frontend"); + project.HasDesign = projectSections.Any(x => x.Skill.Name == "UI/UX Design"); + } + } + + private async Task CalculateProjectPercentage(Project project, CancellationToken cancellationToken) + { + // گرفتن تمام فازهای پروژه + var phases = await _context.ProjectPhases + .Where(ph => ph.ProjectId == project.Id) + .ToListAsync(cancellationToken); + + if (!phases.Any()) + return 0; + + // محاسبه درصد هر فاز و میانگین‌گیری + var phasePercentages = new List(); + foreach (var phase in phases) + { + var phasePercentage = await CalculatePhasePercentage(phase, cancellationToken); + phasePercentages.Add(phasePercentage); + } + + return phasePercentages.Any() ? (int)phasePercentages.Average() : 0; + } + + private async Task CalculatePhasePercentage(ProjectPhase phase, CancellationToken cancellationToken) + { + // گرفتن تمام تسک‌های فاز + var tasks = await _context.ProjectTasks + .Where(t => t.PhaseId == phase.Id) + .ToListAsync(cancellationToken); + + if (!tasks.Any()) + return 0; + + // محاسبه درصد هر تسک و میانگین‌گیری + var taskPercentages = new List(); + foreach (var task in tasks) + { + var taskPercentage = await CalculateTaskPercentage(task, cancellationToken); + taskPercentages.Add(taskPercentage); + } + + return taskPercentages.Any() ? (int)taskPercentages.Average() : 0; + } + + private async Task CalculateTaskPercentage(ProjectTask task, CancellationToken cancellationToken) + { + // گرفتن تمام سکشن‌های تسک با activities + var sections = await _context.TaskSections + .Include(s => s.Activities) + .Where(s => s.TaskId == task.Id) + .ToListAsync(cancellationToken); + + if (!sections.Any()) + return 0; + + // محاسبه درصد هر سکشن و میانگین‌گیری + var sectionPercentages = new List(); + foreach (var section in sections) + { + var sectionPercentage = CalculateSectionPercentage(section); + sectionPercentages.Add(sectionPercentage); + } + + return sectionPercentages.Any() ? (int)sectionPercentages.Average() : 0; + } + + private static int CalculateSectionPercentage(TaskSection section) + { + // محاسبه کل زمان تخمین زده شده (اولیه + اضافی) + var totalEstimatedHours = section.FinalEstimatedHours.TotalHours; + + if (totalEstimatedHours <= 0) + return 0; + + // محاسبه کل زمان صرف شده از activities + var totalSpentHours = section.Activities.Sum(a => a.GetTimeSpent().TotalHours); + + // محاسبه درصد (حداکثر 100%) + var percentage = (totalSpentHours / totalEstimatedHours) * 100; + return Math.Min((int)Math.Round(percentage), 100); + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryValidator.cs new file mode 100644 index 00000000..33141e46 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryValidator.cs @@ -0,0 +1,19 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; + +public class GetProjectsListQueryValidator : AbstractValidator +{ + public GetProjectsListQueryValidator() + { + RuleFor(x => x.HierarchyLevel) + .IsInEnum().WithMessage("سطح ارسال شده معتبر نمی‌باشد."); + + When(x => x.HierarchyLevel != Domain.ProjectAgg.Enums.ProjectHierarchyLevel.Project, () => + { + RuleFor(x => x.ParentId) + .NotNull().WithMessage("شناسه والد باید برای سطوح غیر از پروژه ارسال شود."); + }); + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs new file mode 100644 index 00000000..928501dd --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListResponse.cs @@ -0,0 +1,5 @@ +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; + +public record GetProjectsListResponse( + List Projects); + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs new file mode 100644 index 00000000..db180808 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQuery.cs @@ -0,0 +1,10 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList; + +public record ProjectBoardListQuery: IBaseQuery> +{ +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs new file mode 100644 index 00000000..0edfdc0b --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs @@ -0,0 +1,98 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList; + +public class ProjectBoardListQueryHandler : IBaseQueryHandler> +{ + private readonly IProgramManagerDbContext _programManagerDbContext; + private readonly IAuthHelper _authHelper; + + public ProjectBoardListQueryHandler(IProgramManagerDbContext programManagerDbContext, IAuthHelper authHelper) + { + _programManagerDbContext = programManagerDbContext; + _authHelper = authHelper; + } + + public async Task>> Handle(ProjectBoardListQuery request, + CancellationToken cancellationToken) + { + var currentUserId = _authHelper.GetCurrentUserId(); + var data = await _programManagerDbContext.TaskSections.AsNoTracking() + .Where(x => x.CurrentAssignedUserId == currentUserId) + .Where(x => x.InitialEstimatedHours > TimeSpan.Zero) + .Include(x => x.Task) + .ThenInclude(x => x.Phase) + .ThenInclude(x => x.Project) + .Include(x => x.Activities) + .Include(x => x.AdditionalTimes) + .ToListAsync(cancellationToken); + + var activityUserIds = data.SelectMany(x => x.Activities).Select(a => a.UserId).Distinct().ToList(); + 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 => + { + // محاسبه یکبار برای هر Activity و Cache کردن نتیجه + var activityTimeData = x.Activities.Select(a => + { + var timeSpent = a.GetTimeSpent(); + return new + { + Activity = a, + TimeSpent = timeSpent, + TotalSeconds = timeSpent.TotalSeconds, + FormattedTime = timeSpent.ToString(@"hh\:mm") + }; + }).ToList(); + + // ادغام پشت سر هم فعالیت‌های یک کاربر + var mergedHistories = new List(); + foreach (var activityData in activityTimeData) + { + var lastHistory = mergedHistories.LastOrDefault(); + + // اگر آخرین history برای همین کاربر باشد، زمان‌ها را جمع می‌کنیم + if (lastHistory != null && lastHistory.UserId == activityData.Activity.UserId) + { + var totalTimeSpan = lastHistory.WorkedTimeSpan + activityData.TimeSpent; + lastHistory.WorkedTimeSpan = totalTimeSpan; + lastHistory.WorkedTime = totalTimeSpan.ToString(@"hh\:mm"); + } + else + { + // در غیر این صورت، یک history جدید اضافه می‌کنیم + mergedHistories.Add(new ProjectProgressHistoryDto() + { + UserId = activityData.Activity.UserId, + IsCurrentUser = activityData.Activity.UserId == currentUserId, + Name = users.GetValueOrDefault(activityData.Activity.UserId, "ناشناس"), + WorkedTime = activityData.FormattedTime, + WorkedTimeSpan = activityData.TimeSpent, + }); + } + } + + return new ProjectBoardListResponse() + { + Id = x.Id, + PhaseName = x.Task.Phase.Name, + ProjectName = x.Task.Phase.Project.Name, + TaskName = x.Task.Name, + SectionStatus = x.Status, + Progress = new ProjectProgressDto() + { + CompleteSecond = x.FinalEstimatedHours.TotalSeconds, + CurrentSecond = activityTimeData.Sum(a => a.TotalSeconds), + Histories = mergedHistories + } + }; + }).ToList(); + + return OperationResult>.Success(result); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs new file mode 100644 index 00000000..83421e89 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListResponse.cs @@ -0,0 +1,28 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList; + +public class ProjectBoardListResponse +{ + public Guid Id { get; set; } + public string ProjectName { get; set; } + public string PhaseName { get; set; } + public string TaskName { get; set; } + public ProjectProgressDto Progress { get; set; } + public TaskSectionStatus SectionStatus { get; set; } +} +public class ProjectProgressDto +{ + public double CurrentSecond { get; set; } + public double CompleteSecond { get; set; } + public List Histories { get; set; } +} + +public class ProjectProgressHistoryDto +{ + public string Name { get; set; } + public long UserId { get; set; } + public string WorkedTime { get; set; } + public TimeSpan WorkedTimeSpan { get; set; } + public bool IsCurrentUser { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQuery.cs new file mode 100644 index 00000000..4b2c08b9 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQuery.cs @@ -0,0 +1,30 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails; + +public record ProjectSetTimeDetailsQuery(Guid TaskId) + : IBaseQuery; +public record ProjectSetTimeResponse( + List SectionItems, + Guid Id, + ProjectHierarchyLevel Level); + +public record ProjectSetTimeResponseSections +{ + public string SkillName { get; init; } + public string UserName { get; init; } + public int InitialTime { get; set; } + public string InitialDescription { get; set; } + public int TotalEstimateTime { get; init; } + public int TotalAdditionalTime { get; init; } + public string InitCreationTime { get; init; } + public List AdditionalTimes { get; init; } + public Guid SectionId { get; set; } +} + +public class ProjectSetTimeResponseSectionAdditionalTime +{ + public int Time { get; init; } + public string Description { get; init; } +} 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 new file mode 100644 index 00000000..f99f3370 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryHandler.cs @@ -0,0 +1,80 @@ +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; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails; + + +public class ProjectSetTimeDetailsQueryHandler + : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public ProjectSetTimeDetailsQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(ProjectSetTimeDetailsQuery request, + CancellationToken cancellationToken) + { + var task = await _context.ProjectTasks + .Where(p => p.Id == request.TaskId) + .Include(x => x.Sections) + .ThenInclude(x => x.AdditionalTimes).AsNoTracking() + .FirstOrDefaultAsync(cancellationToken); + + if (task == null) + { + return OperationResult.NotFound("Project not found"); + } + var userIds = task.Sections.Select(x => x.OriginalAssignedUserId) + .Distinct().ToList(); + + var users = await _context.Users + .Where(x => userIds.Contains(x.Id)) + .AsNoTracking() + .ToListAsync(cancellationToken); + var skillIds = task.Sections.Select(x => x.SkillId) + .Distinct().ToList(); + + var skills = await _context.Skills + .Where(x => skillIds.Contains(x.Id)) + .AsNoTracking() + .ToListAsync(cancellationToken); + + 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); + return new ProjectSetTimeResponseSections + { + AdditionalTimes = ts.AdditionalTimes + .Select(x => new ProjectSetTimeResponseSectionAdditionalTime + { + Description = x.Reason ?? "", + Time = (int)x.Hours.TotalHours + }).ToList(), + InitCreationTime = ts.CreationDate.ToFarsi(), + SkillName = skill?.Name ?? "", + TotalAdditionalTime = (int)ts.GetTotalAdditionalTime().TotalHours, + TotalEstimateTime = (int)ts.FinalEstimatedHours.TotalHours, + UserName = user?.UserName ?? "", + SectionId = ts.Id, + InitialDescription = ts.InitialDescription ?? "", + InitialTime = (int)ts.InitialEstimatedHours.TotalHours + }; + }).ToList(), + task.Id, + ProjectHierarchyLevel.Task); + + + return OperationResult.Success(res); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryValidator.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryValidator.cs new file mode 100644 index 00000000..13952f46 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectSetTimeDetails/ProjectSetTimeDetailsQueryValidator.cs @@ -0,0 +1,13 @@ +using FluentValidation; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails; + +public class ProjectSetTimeDetailsQueryValidator:AbstractValidator +{ + public ProjectSetTimeDetailsQueryValidator() + { + RuleFor(x => x.TaskId) + .NotEmpty() + .WithMessage("شناسه پروژه نمی‌تواند خالی باشد."); + } +} \ No newline at end of file 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/Commands/CreateSalarySettings/CreateSalarySettingsCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Commands/CreateSalarySettings/CreateSalarySettingsCommandHandler.cs new file mode 100644 index 00000000..95e57809 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Commands/CreateSalarySettings/CreateSalarySettingsCommandHandler.cs @@ -0,0 +1,173 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; + +public class CreateSalarySettingsCommandHandler : IBaseCommandHandler +{ + readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository; + readonly IUnitOfWork _unitOfWork; + + public CreateSalarySettingsCommandHandler(ISalaryPaymentSettingRepository salaryPaymentSettingRepository, IUnitOfWork unitOfWork) + { + _salaryPaymentSettingRepository = salaryPaymentSettingRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(CreateSalarySettingsCommand request, CancellationToken cancellationToken) + { + + if(_salaryPaymentSettingRepository.Exists(x=>x.UserId == request.UserId)) + return OperationResult.Failure(" برای این پرسنل قبلا تنظیمات ایجاد شده است"); + + + if (string.IsNullOrWhiteSpace(request.MonthlySalary)) + return OperationResult.Failure("حقوق ماهانه وارد نشده اشت"); + double monthlySalary = 0; + try + { + monthlySalary = request.MonthlySalary.MoneyToDouble(); + } + catch (Exception e) + { + return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است"); + } + + + if (monthlySalary == 0) + return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است"); + + var workingHoursList = new List(); + foreach (var workingHours in request.WorkingHoursList) + { + var startShiftOne = new TimeSpan(); + var endShiftOne = new TimeSpan(); + var startShiftTwo = new TimeSpan(); + var endShiftTwo = new TimeSpan(); + var restTime = new TimeSpan(); + workingHours.HasShiftOne = false; + workingHours.HasRestTime = false; + workingHours.HasShiftTow = false; + try + { + if (!string.IsNullOrWhiteSpace(workingHours.StartShiftOne) && !string.IsNullOrWhiteSpace(workingHours.EndShiftOne)) + { + startShiftOne = TimeSpan.ParseExact(workingHours.StartShiftOne, @"hh\:mm", null); + endShiftOne = TimeSpan.ParseExact(workingHours.EndShiftOne, @"hh\:mm", null); + + workingHours.HasShiftOne = true; + + + if (!string.IsNullOrWhiteSpace(workingHours.RestTime)) + { + try + { + restTime = TimeSpan.ParseExact(workingHours.RestTime, @"hh\:mm", null); + workingHours.HasRestTime = true; + } + catch (Exception e) + { + return OperationResult.Failure("فرمت ساعت استراحت اشتباه وارد شده است"); + } + } + + } + + if (!string.IsNullOrWhiteSpace(workingHours.StartShiftTwo) && + !string.IsNullOrWhiteSpace(workingHours.EndShiftTwo)) + { + workingHours.HasRestTime = false; + workingHours.HasShiftTow = true; + + startShiftTwo = TimeSpan.ParseExact(workingHours.StartShiftTwo, @"hh\:mm", null); + endShiftTwo = TimeSpan.ParseExact(workingHours.EndShiftTwo, @"hh\:mm", null); + } + } + catch (Exception) + { + return OperationResult.Failure("فرمت ساعت اشتباه وارد شده است"); + } + + + + + workingHoursList.Add(new WorkingHours(startShiftOne,endShiftOne,startShiftTwo, endShiftTwo,restTime,workingHours.HasShiftOne,workingHours.HasShiftTow,workingHours.HasRestTime, workingHours.PersianDayOfWeek, workingHours.IsActiveDay)); + + } + + if(workingHoursList.Count < 7) + return OperationResult.Failure("خطا در تعداد روز های ارسال شده"); + var salarySetting = new SalaryPaymentSetting(request.HolidayWorking, request.UserId,monthlySalary, workingHoursList); + await _salaryPaymentSettingRepository.CreateAsync(salarySetting); + await _unitOfWork.SaveChangesAsync(); + return OperationResult.Success(); + + } +} + + +public record CreateSalarySettingsCommand(bool HolidayWorking, long UserId, string? MonthlySalary, List WorkingHoursList) : IBaseCommand; + + +public record WorkingHoursListDto +{ + /// + /// ساعت شروع شیفت کاری + /// + public string? StartShiftOne { get; set; } + + /// + /// ساعت پایان شیفت کاری + /// + public string? EndShiftOne { get; set; } + + + /// + /// ساعت شروع شیفت دوم کاری + /// + public string? StartShiftTwo { get; set; } + + /// + /// ساعت پایان شیفت دوم کاری + /// + public string? EndShiftTwo { get; set; } + + /// + /// مدت استراحت + /// + public string? RestTime { get; set; } + + + /// + /// آیا مقطع مار اول دارد + /// + public bool HasShiftOne { get; set; } + + /// + /// آیا مقطع کار دوم دارد + /// + public bool HasShiftTow { get; set; } + + /// + /// آیا ساعت استراحت دارد + /// + public bool HasRestTime { get; set; } + + + /// + /// عدد روز از ماه + /// + public PersianDayOfWeek PersianDayOfWeek { get; set; } + + + /// + /// آیا این روز هفته + /// فعال است + /// + public bool IsActiveDay { get; set; } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Commands/EditSalarySettings/EditSalarySettingsCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Commands/EditSalarySettings/EditSalarySettingsCommandHandler.cs new file mode 100644 index 00000000..fe202a61 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Commands/EditSalarySettings/EditSalarySettingsCommandHandler.cs @@ -0,0 +1,120 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.EditSalarySettings; + +public class EditSalarySettingsCommandHandler : IBaseCommandHandler +{ + private readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository; + private readonly IUnitOfWork _unitOfWork; + + public EditSalarySettingsCommandHandler(ISalaryPaymentSettingRepository salaryPaymentSettingRepository, IUnitOfWork unitOfWork) + { + _salaryPaymentSettingRepository = salaryPaymentSettingRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(EditSalarySettingsCommand request, CancellationToken cancellationToken) + { + + var getSettings =await _salaryPaymentSettingRepository.GetSalarySettingByUserId(request.UserId); + if(getSettings == null) + return OperationResult.NotFound("یافت نشد"); + + if(string.IsNullOrWhiteSpace(request.MonthlySalary)) + return OperationResult.Failure("حقوق ماهانه وارد نشده اشت"); + double monthlySalary = 0; + try + { + monthlySalary = request.MonthlySalary.MoneyToDouble(); + } + catch (Exception e) + { + return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است"); + } + + if (monthlySalary == 0) + return OperationResult.Failure("مبلغ حقوق به درستی وارد نشده است"); + + + var workingHoursList = new List(); + foreach (var workingHours in request.WorkingHoursList) + { + var startShiftOne = new TimeSpan(); + var endShiftOne = new TimeSpan(); + var startShiftTwo = new TimeSpan(); + var endShiftTwo = new TimeSpan(); + var restTime = new TimeSpan(); + workingHours.HasShiftOne = false; + workingHours.HasRestTime = false; + workingHours.HasShiftTow = false; + try + { + if (!string.IsNullOrWhiteSpace(workingHours.StartShiftOne) && !string.IsNullOrWhiteSpace(workingHours.EndShiftOne)) + { + startShiftOne = TimeSpan.ParseExact(workingHours.StartShiftOne, @"hh\:mm", null); + endShiftOne = TimeSpan.ParseExact(workingHours.EndShiftOne, @"hh\:mm", null); + + workingHours.HasShiftOne = true; + + + if (!string.IsNullOrWhiteSpace(workingHours.RestTime)) + { + try + { + restTime = TimeSpan.ParseExact(workingHours.RestTime, @"hh\:mm", null); + workingHours.HasRestTime = true; + } + catch (Exception e) + { + return OperationResult.Failure("فرمت ساعت استراحت اشتباه وارد شده است"); + } + } + } + + if (!string.IsNullOrWhiteSpace(workingHours.StartShiftTwo) && + !string.IsNullOrWhiteSpace(workingHours.EndShiftTwo)) + { + workingHours.HasRestTime = false; + workingHours.HasShiftTow = true; + + startShiftTwo = TimeSpan.ParseExact(workingHours.StartShiftTwo, @"hh\:mm", null); + endShiftTwo = TimeSpan.ParseExact(workingHours.EndShiftTwo, @"hh\:mm", null); + } + } + catch (Exception) + { + return OperationResult.Failure("فرمت ساعت اشتباه وارد شده است"); + } + + + + + workingHoursList.Add(new WorkingHours(startShiftOne, endShiftOne, startShiftTwo, endShiftTwo, restTime, workingHours.HasShiftOne, workingHours.HasShiftTow, workingHours.HasRestTime, workingHours.PersianDayOfWeek, workingHours.IsActiveDay)); + + + + } + + + getSettings.Edit(request.HolidayWorking,monthlySalary, workingHoursList); + + + await _unitOfWork.SaveChangesAsync(); + return OperationResult.Success(); + } +} + + +public record EditSalarySettingsCommand(long UserId, bool HolidayWorking,string? MonthlySalary, List WorkingHoursList) : IBaseCommand; + + + + + + + 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 new file mode 100644 index 00000000..c3bd3385 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetSalarySettingToEdit/GetSalarySettingToEditQueryHandler.cs @@ -0,0 +1,88 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; +using GozareshgirProgramManager.Domain._Common; +using Microsoft.EntityFrameworkCore; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; + +namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; + +public class GetSalarySettingToEditQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetSalarySettingToEditQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetSalarySettingToEditQuery request, CancellationToken cancellationToken) + { + var user =await _context.Users.FirstOrDefaultAsync(x => x.Id == request.UserId); + if(user == null) + return OperationResult.NotFound("کاربر یافت نشد"); + + var editSalarySettingsList = await _context.SalaryPaymentSettings + .Select(x => new GetSalarySettingToEdit() + { + Id = x.Id, + HolidayWorking = x.HolidayWorking, + UserId = x.UserId, + MonthlySalary = x.MonthlySalary.ToMoney(), + + WorkingHoursList = x.WorkingHoursList.Select(wh => new WorkingHoursListDto + { + 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, + 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(), + + }).FirstOrDefaultAsync(x => x.UserId == request.UserId); + + 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 GetSalarySettingToEdit +{ + /// + /// ای دی کاربر + /// + public long Id { get; set; } + /// + /// آی دی کاربر + /// + public long UserId { get; set; } + + /// + /// کار در تعطیلات رسمی + /// + public bool HolidayWorking { get; set; } + + /// + /// حقوق ماهانه + /// + public string MonthlySalary { get; set; } + + /// + /// لیست روزهای هفته و ساعات کاری + /// + 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 new file mode 100644 index 00000000..2e9361e6 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/SalaryPaymentSettings/Queries/GetUserListWhoHaveSettings/GetUserListWhoHaveSettingsQueryHandler.cs @@ -0,0 +1,111 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; + +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetUserListWhoHaveSettings; + +public class GetUserListWhoHaveSettingsQueryHandler : IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _context; + + public GetUserListWhoHaveSettingsQueryHandler(IProgramManagerDbContext context) + { + _context = context; + } + + public async Task> Handle(GetUserListWhoHaveSettingsQuery request, CancellationToken cancellationToken) + { + var query = await ( + from u in _context.Users + join s in _context.SalaryPaymentSettings + on u.Id equals s.UserId into settingsGroup + select new GetUserWhoHaveSettingsDto + { + 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)) + query = query.Where(x => x.FullName.Contains(request.FullName)).ToList(); + + if (request.HasSalarySettings != HasSalarySettings.Default) + { + bool hasSettings = request.HasSalarySettings == HasSalarySettings.HasSettings; + + query = query.Where(x => x.HasSalarySettings == hasSettings).ToList(); + } + + var operationQuery = query.Select(user => + { + var weeklyWorkingTimeAvrage = user.WeeklyWorkingTimeAvrageInt.ConvertIntDurationToHoursAndMinutes(); + + 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); + + + } +} + + +public record GetUserListWhoHaveSettingsQuery(string? FullName, HasSalarySettings HasSalarySettings) : IBaseQuery; + +public record GetUserListWhoHaveSettingsResponse(List UserList); + +public record GetUserWhoHaveSettingsDto +{ + /// + /// نام و نام خانوادگی + /// + public string FullName { get; set; } + + /// + /// آی دی کاربر + /// + public long UserId { get; set; } + + /// + /// آیا کاربر دارای تنظیمات حقوق است؟ + /// + public bool HasSalarySettings { get; set; } + + /// + /// میانگین ساعت کار + /// عددی مجموع دقایق + /// + public int WeeklyWorkingTimeAvrageInt { get; set; } + + /// + /// میانگین ساعت کار در هفته + /// رشته ساعت و دقیقه + /// + public string WeeklyWorkingTimeAvrage { get; set; } + + + /// + /// حقوق ماهانه + /// + public string MontlySalary { get; set; } + +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/DTOs/SkillDto.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/DTOs/SkillDto.cs new file mode 100644 index 00000000..75d052ce --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/DTOs/SkillDto.cs @@ -0,0 +1,7 @@ +namespace GozareshgirProgramManager.Application.Modules.Skills.DTOs; + +public class SkillDto +{ + public Guid Id { get; set; } + public string Name { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/Queries/GetSkillList/GetSkillListCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/Queries/GetSkillList/GetSkillListCommandHandler.cs new file mode 100644 index 00000000..061597c9 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Skills/Queries/GetSkillList/GetSkillListCommandHandler.cs @@ -0,0 +1,33 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Skills.DTOs; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application.Modules.Skills.Queries.GetSkillList; + +public record GetSkillListQuery() : IBaseQuery; +public record GetSkillListResponse(List Skills); + +public class GetSkillListCommandHandler:IBaseQueryHandler +{ + private readonly IProgramManagerDbContext _dbContext; + + public GetSkillListCommandHandler(IProgramManagerDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task> Handle(GetSkillListQuery request, CancellationToken cancellationToken) + { + var skills =await _dbContext.Skills + .Select(s => new SkillDto + { + Id = s.Id, + Name = s.Name + }) + .ToListAsync(cancellationToken: cancellationToken); + + var response = new GetSkillListResponse(skills); + return OperationResult.Success(response); + } +} \ No newline at end of file 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/Application/GozareshgirProgramManager.Application/_Bootstrapper/DependencyInjection.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Bootstrapper/DependencyInjection.cs new file mode 100644 index 00000000..07aaa222 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Bootstrapper/DependencyInjection.cs @@ -0,0 +1,22 @@ +using System.Reflection; +using GozareshgirProgramManager.Application.Interfaces; +using Microsoft.Extensions.DependencyInjection; + +namespace GozareshgirProgramManager.Application._Bootstrapper; + +public static class DependencyInjection +{ + public static IServiceCollection AddProgramManagerApplication(this IServiceCollection services) + { + services.AddMediatR(cfg => + { + cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); + cfg.LicenseKey = + "eyJhbGciOiJSUzI1NiIsImtpZCI6Ikx1Y2t5UGVubnlTb2Z0d2FyZUxpY2Vuc2VLZXkvYmJiMTNhY2I1OTkwNGQ4OWI0Y2IxYzg1ZjA4OGNjZjkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2x1Y2t5cGVubnlzb2Z0d2FyZS5jb20iLCJhdWQiOiJMdWNreVBlbm55U29mdHdhcmUiLCJleHAiOiIxNzk2MDgzMjAwIiwiaWF0IjoiMTc2NDU5NTE2OSIsImFjY291bnRfaWQiOiIwMTlhZGExMDA0MzA3M2Y5ODhhNWY0MmJmZDdlYTE3OCIsImN1c3RvbWVyX2lkIjoiY3RtXzAxa2JkMTJ4eXNnMHB6MjR0YnhqeXA0a2p3Iiwic3ViX2lkIjoiLSIsImVkaXRpb24iOiIwIiwidHlwZSI6IjIifQ.Gl0FB9XoQMJQgzdCh9gplRirYvmkDJYXD8tfLiWkRAeQJ2zlFdoHw7btxGrUVisI_ZfSxK2kkUB_LLty2eArbeZb5Ja1_xexgzTv3CJ4TnacT0FoVOc8eLeGCbJmmXtSt6CW89XwzvV_taiSSkcdsnATNTH0MEBLqCkKw4FMpSXqrPxCgakXB-pcyeqeTO9a0DD5XjBVITGaslUUFgnBGirsLdHRgL9AYVty3EzWTBH9WBcc4dHyZ5YUDMzsIab5elc-pmOLCXAJviamG9Afsaq4N88IMjsYvq6ihw_EAsmQH1K8WNunFMN8VjwO5csHmgKJ6wajONH7kUaMWNxRrQ"; + }); + + + return services; + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/CachingBehavior.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/CachingBehavior.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/LoggingBehavior.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/LoggingBehavior.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/PerformanceBehavior.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/PerformanceBehavior.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/TransactionBehavior.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/TransactionBehavior.cs new file mode 100644 index 00000000..c6cd15d5 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/TransactionBehavior.cs @@ -0,0 +1,42 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application._Common.Behaviors; + +public class TransactionBehavior : IPipelineBehavior + where TRequest : IBaseCommand +{ + private readonly IProgramManagerDbContext _dbContext; + + public TransactionBehavior(IProgramManagerDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken) + { + // اگر تراکنش فعال است، ادامه بده + if (_dbContext is not DbContext efContext) + return await next(); + if (efContext.Database.CurrentTransaction != null) + return await next(); + + await using var transaction = await efContext.Database.BeginTransactionAsync(cancellationToken); + try + { + var response = await next(); + await _dbContext.SaveChangesAsync(cancellationToken); + await transaction.CommitAsync(cancellationToken); + return response; + } + catch + { + await transaction.RollbackAsync(cancellationToken); + throw; + } + } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/ValidationBehavior.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/ValidationBehavior.cs new file mode 100644 index 00000000..a1473666 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Behaviors/ValidationBehavior.cs @@ -0,0 +1,40 @@ +using FluentValidation; +using GozareshgirProgramManager.Application._Common.Interfaces; +using MediatR; + +namespace GozareshgirProgramManager.Application._Common.Behaviors; + +public class ValidationBehavior : IPipelineBehavior + where TRequest : IBaseCommand +{ + private readonly IEnumerable> _validators; + + public ValidationBehavior(IEnumerable> validators) + { + _validators = validators; + } + + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken) + { + if (!_validators.Any()) + return await next(); + + var context = new ValidationContext(request); + + var validationResults = await Task.WhenAll( + _validators.Select(v => v.ValidateAsync(context, cancellationToken))); + + var failures = validationResults + .SelectMany(r => r.Errors) + .Where(f => f != null) + .ToList(); + + if (failures.Count != 0) + throw new ValidationException(failures); + + return await next(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/EnumExtensions.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/EnumExtensions.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/QueryableExtensions.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/QueryableExtensions.cs new file mode 100644 index 00000000..979befac --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/QueryableExtensions.cs @@ -0,0 +1,19 @@ +namespace GozareshgirProgramManager.Application._Common.Extensions; + +public static class QueryableExtensions +{ + public static IQueryable ApplyPagination(this IQueryable query, int page, int pageSize = 30) + { + if (page <= 0) page = 1; + if (pageSize <= 0) pageSize = 10; + + return query.Skip((page - 1) * pageSize).Take(pageSize); + } + public static IEnumerable ApplyPagination(this IEnumerable source, int page, int pageSize = 30) + { + if (page <= 0) page = 1; + if (pageSize <= 0) pageSize = 10; + + return source.Skip((page - 1) * pageSize).Take(pageSize); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/StringExtensions.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Extensions/StringExtensions.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs new file mode 100644 index 00000000..7b392d47 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs @@ -0,0 +1,114 @@ +using System.Security.Claims; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +/// +/// رابط کمکی برای کار با JWT و HttpContext +/// این interface فقط متدهای helper دارد و هیچ عملیات دیتابیسی ندارد +/// +public interface IAuthHelper +{ + // ==================== Token Generation ==================== + LoginSession SignIn(long userId, string userName, string fullName, long accountId, List roles); + /// + /// تولید Access Token + /// + string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles); + + /// + /// تولید Refresh Token + /// + string GenerateRefreshToken(); + + /// + /// دریافت تاریخ انقضای Refresh Token + /// + DateTime GetRefreshTokenExpiration(); + + // ==================== Token Validation ==================== + + /// + /// اعتبارسنجی توکن و استخراج Claims + /// + ClaimsPrincipal? ValidateToken(string token); + + /// + /// اعتبارسنجی توکن منقضی شده (بدون چک زمان انقضا) + /// + ClaimsPrincipal? ValidateExpiredToken(string token); + + /// + /// استخراج UserId از توکن (حتی اگر منقضی شده باشد) + /// + long? GetUserIdFromToken(string token); + + // ==================== HttpContext Helpers ==================== + + /// + /// دریافت IP Address کاربر جاری + /// + string? GetClientIpAddress(); + + /// + /// دریافت User Agent کاربر جاری + /// + string? GetUserAgent(); + + /// + /// دریافت Refresh Token از Cookie + /// + string? GetRefreshTokenFromCookie(); + + // ==================== Current User Claims ==================== + + /// + /// بررسی احراز هویت کاربر جاری + /// + bool IsAuthenticated(); + + /// + /// دریافت شناسه کاربر جاری از Claims + /// + long? GetCurrentUserId(); + + /// + /// دریافت نام کاربری جاری از Claims + /// + string? GetCurrentUserName(); + + /// + /// دریافت نام کامل کاربر جاری از Claims + /// + string? GetCurrentFullName(); + + /// + /// دریافت AccountId کاربر جاری از Claims + /// + long? GetCurrentAccountId(); + + /// + /// دریافت نقش‌های کاربر جاری از Claims + /// + List GetCurrentUserRoles(); + + // ==================== Role Checking ==================== + + /// + /// بررسی دسترسی کاربر به نقش خاص + /// + bool HasRole(string roleName); + + /// + /// بررسی دسترسی کاربر به یکی از نقش‌ها + /// + bool HasAnyRole(params string[] roleNames); + + void SignOut(); +} +public class LoginSession +{ + public string AccessToken { get; set; } + public string RefreshToken { get; set; } + public DateTime RefreshTokenExpiration { get; set; } + public DateTime AccessTokenExpiration { get; set; } +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommand.cs new file mode 100644 index 00000000..1b469f03 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommand.cs @@ -0,0 +1,14 @@ +using GozareshgirProgramManager.Application._Common.Models; +using MediatR; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IBaseCommand : IRequest +{ +} + +public interface IBaseCommand : IRequest> +{ +} + + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommandHandler.cs new file mode 100644 index 00000000..3b699cb3 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseCommandHandler.cs @@ -0,0 +1,13 @@ +using GozareshgirProgramManager.Application._Common.Models; +using MediatR; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IBaseCommandHandler : IRequestHandler + where TCommand : IBaseCommand +{ +} +public interface IBaseCommandHandler : IRequestHandler> + where TCommand : IBaseCommand +{ +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQuery.cs new file mode 100644 index 00000000..979a93f3 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQuery.cs @@ -0,0 +1,10 @@ +using MediatR; +using GozareshgirProgramManager.Application._Common.Models; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IBasePaginationQuery : IRequest>> +{ + int PageIndex { get; set; } + int PageSize { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQueryHandler.cs new file mode 100644 index 00000000..5d9c4bbf --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBasePaginationQueryHandler.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Application._Common.Models; +using MediatR; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IBasePaginationQueryHandler + : IRequestHandler>> + where TQuery : PaginationRequest, IBasePaginationQuery + where TResponse : class +{ + +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQuery.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQuery.cs new file mode 100644 index 00000000..146e2c33 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQuery.cs @@ -0,0 +1,9 @@ +using MediatR; +using GozareshgirProgramManager.Application._Common.Models; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IBaseQuery : IRequest> +{ +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQueryHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQueryHandler.cs new file mode 100644 index 00000000..bd8650ba --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IBaseQueryHandler.cs @@ -0,0 +1,10 @@ +using MediatR; +using GozareshgirProgramManager.Application._Common.Models; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IBaseQueryHandler : IRequestHandler> + where TQuery : IBaseQuery +{ +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs new file mode 100644 index 00000000..8baad5be --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Domain.HolidayAgg; +using GozareshgirProgramManager.Domain.HolidayItemAgg; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IGozareshgirDbContext +{ + DbSet HolidayItems { get; set; } + DbSet Holidays { get; set; } + +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IProgramManagerDbContext.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IProgramManagerDbContext.cs new file mode 100644 index 00000000..1a477bec --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IProgramManagerDbContext.cs @@ -0,0 +1,32 @@ +using GozareshgirProgramManager.Domain.CheckoutAgg.Entities; +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.SkillAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Entities; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Application._Common.Interfaces; + +public interface IProgramManagerDbContext +{ + DbSet Checkouts { set; get; } + DbSet SalaryPaymentSettings { set; get; } + DbSet Roles { get; set; } + DbSet Users { get; set; } + DbSet RefreshTokens { get; set; } + DbSet Customers { get; } + DbSet Projects { get; set; } + DbSet ProjectPhases { get; set; } + DbSet TaskSections { get; set; } + DbSet ProjectSections { get; set; } + DbSet PhaseSections { get; set; } + + DbSet ProjectTasks { get; set; } + + DbSet Skills { get; set; } + Task SaveChangesAsync(CancellationToken cancellationToken = default); +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AccessTokenResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AccessTokenResponse.cs new file mode 100644 index 00000000..3c4a68ec --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AccessTokenResponse.cs @@ -0,0 +1,14 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +/// +/// پاسخ تازه‌سازی توکن دسترسی +/// +public class AccessTokenResponse +{ + public string AccessToken { get; set; } = string.Empty; + public DateTime ExpiresAt { get; set; } + public long UserId { get; set; } + public string FullName { get; set; } = string.Empty; + public string UserName { get; set; } = string.Empty; +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AuthViewModel.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AuthViewModel.cs new file mode 100644 index 00000000..64de4d90 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/AuthViewModel.cs @@ -0,0 +1,11 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +/// +/// مدل ورودی برای احراز هویت +/// +public class AuthViewModel +{ + public long UserId { get; set; } +} + + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/DomainEventNotification.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/DomainEventNotification.cs new file mode 100644 index 00000000..bf580abc --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/DomainEventNotification.cs @@ -0,0 +1,19 @@ +using GozareshgirProgramManager.Domain._Common; +using MediatR; + +namespace GozareshgirProgramManager.Application._Common.Models; + +/// +/// Wrapper to convert Domain Events to MediatR Notifications +/// +public class DomainEventNotification : INotification + where TDomainEvent : IDomainEvent +{ + public TDomainEvent DomainEvent { get; } + + public DomainEventNotification(TDomainEvent domainEvent) + { + DomainEvent = domainEvent; + } +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/ErrorDetails.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/ErrorDetails.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/LoginResponse.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/LoginResponse.cs new file mode 100644 index 00000000..f4b98e4f --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/LoginResponse.cs @@ -0,0 +1,15 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +/// +/// پاسخ ورود به سیستم +/// +public class LoginResponse +{ + public string AccessToken { get; set; } = string.Empty; + public DateTime ExpiresAt { get; set; } + public long UserId { get; set; } + public string FullName { get; set; } = string.Empty; + public string UserName { get; set; } = string.Empty; + public List Roles { get; set; } = new(); +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/OperationResult.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/OperationResult.cs new file mode 100644 index 00000000..324e9895 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/OperationResult.cs @@ -0,0 +1,60 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +public enum ErrorType +{ + None, + BadRequest, + NotFound, + Unauthorized, + Validation, + InternalServerError +} + +public class OperationResult +{ + public bool IsSuccess { get; private set; } + public string? ErrorMessage { get; private set; } + public List Errors { get; private set; } + public ErrorType ErrorType { get; private set; } + + protected OperationResult(bool isSuccess, string? errorMessage = null, List? errors = null, ErrorType errorType = ErrorType.None) + { + IsSuccess = isSuccess; + ErrorMessage = errorMessage; + Errors = errors ?? new List(); + ErrorType = errorType; + } + + public static OperationResult Success() => new(true); + public static OperationResult Failure(string errorMessage, ErrorType errorType = ErrorType.BadRequest) => new(false, errorMessage, errorType: errorType); + public static OperationResult Failure(List errors, ErrorType errorType = ErrorType.BadRequest) => new(false, errors: errors, errorType: errorType); + + // Helper methods for specific error types + public static OperationResult NotFound(string errorMessage) => new(false, errorMessage, errorType: ErrorType.NotFound); + public static OperationResult Unauthorized(string errorMessage) => new(false, errorMessage, errorType: ErrorType.Unauthorized); + public static OperationResult ValidationError(string errorMessage) => new(false, errorMessage, errorType: ErrorType.Validation); + public static OperationResult ValidationError(List errors) => new(false, errors: errors, errorType: ErrorType.Validation); + public static OperationResult InternalServerError(string errorMessage) => new(false, errorMessage, errorType: ErrorType.InternalServerError); +} + +public class OperationResult : OperationResult +{ + public T? Data { get; private set; } + + private OperationResult(bool isSuccess, T? data = default, string? errorMessage = null, List? errors = null, ErrorType errorType = ErrorType.None) + : base(isSuccess, errorMessage, errors, errorType) + { + Data = data; + } + + public static OperationResult Success(T data) => new(true, data); + public static new OperationResult Failure(string errorMessage, ErrorType errorType = ErrorType.BadRequest) => new(false, default, errorMessage, errorType: errorType); + public static new OperationResult Failure(List errors, ErrorType errorType = ErrorType.BadRequest) => new(false, default, errors: errors, errorType: errorType); + + // Helper methods for specific error types + public static new OperationResult NotFound(string errorMessage) => new(false, default, errorMessage, errorType: ErrorType.NotFound); + public static new OperationResult Unauthorized(string errorMessage) => new(false, default, errorMessage, errorType: ErrorType.Unauthorized); + public static new OperationResult ValidationError(string errorMessage) => new(false, default, errorMessage, errorType: ErrorType.Validation); + public static new OperationResult ValidationError(List errors) => new(false, default, errors: errors, errorType: ErrorType.Validation); + public static new OperationResult InternalServerError(string errorMessage) => new(false, default, errorMessage, errorType: ErrorType.InternalServerError); +} diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationRequest.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationRequest.cs new file mode 100644 index 00000000..6c55bae2 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationRequest.cs @@ -0,0 +1,8 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +public record PaginationRequest +{ + public int PageIndex { get; set; } = 1; + public int PageSize { get; set; } = 30; +} + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationResult.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationResult.cs new file mode 100644 index 00000000..8249f241 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/PaginationResult.cs @@ -0,0 +1,11 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +public class PaginationResult +{ + public int TotalCount { get; set; } + public List List { get; set; } +} +public class PaginationResult:PaginationResult +{ + public TMeta? Meta { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/TokenValidationResult.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/TokenValidationResult.cs new file mode 100644 index 00000000..37889e20 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Models/TokenValidationResult.cs @@ -0,0 +1,24 @@ +namespace GozareshgirProgramManager.Application._Common.Models; + +/// +/// نتیجه اعتبارسنجی توکن +/// +public class TokenValidationResult +{ + public bool IsValid { get; set; } + public long? UserId { get; set; } + public string? ErrorMessage { get; set; } + + public static TokenValidationResult Success(long userId) => new() + { + IsValid = true, + UserId = userId + }; + + public static TokenValidationResult Failure(string errorMessage) => new() + { + IsValid = false, + ErrorMessage = errorMessage + }; +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Entities/Checkout.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Entities/Checkout.cs new file mode 100644 index 00000000..22e4495e --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Entities/Checkout.cs @@ -0,0 +1,134 @@ +using System.ComponentModel.DataAnnotations.Schema; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CheckoutAgg.Enums; + +namespace GozareshgirProgramManager.Domain.CheckoutAgg.Entities; + +public class Checkout : EntityBase +{ + /// + /// ایجاد فیش + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public Checkout(DateTime checkoutStartDate, DateTime checkoutEndDate, int year, int month, string fullName, long userId, + int mandatoryHours, int totalHoursWorked, int totalDaysWorked, int remainingHours, double monthlySalaryDefined, double monthlySalaryPay, double deductionFromSalary) + { + CheckoutStartDate = checkoutStartDate; + CheckoutEndDate = checkoutEndDate; + Year = year; + Month = month; + FullName = fullName; + UserId = userId; + MandatoryHours = mandatoryHours; + TotalHoursWorked = totalHoursWorked; + TotalDaysWorked = totalDaysWorked; + RemainingHours = remainingHours; + MonthlySalaryDefined = monthlySalaryDefined; + MonthlySalaryPay = monthlySalaryPay; + DeductionFromSalary = deductionFromSalary; + + } + + /// + /// تاریخ شروع فیش حقوقی + /// + public DateTime CheckoutStartDate { get; private set; } + + /// + /// تاریخ پایان فیش حقوقی + /// + public DateTime CheckoutEndDate { get; private set; } + + /// + /// سال + /// + public int Year { get; private set; } + + /// + /// ماه + /// + public int Month { get; private set; } + + [NotMapped] + public string PersianMonthName=> Month.ToFarsiMonthByIntNumber(); + + /// + /// نام کامل کاربر + /// + public string FullName { get; private set; } + + /// + /// آی دی کاربر + /// + public long UserId { get; private set; } + + /// + /// ساعت موظفی + /// + public int MandatoryHours { get; private set; } + + /// + /// مجموع ساعات کارکرد پرسنل + /// + public int TotalHoursWorked { get; private set; } + + /// + /// مجمع روزهای کارکرد پرسنل + /// + public int TotalDaysWorked { get; private set; } + + /// + /// ساعات باقی مانده + /// کسر کار یا اضافه کار + /// + public int RemainingHours { get; private set; } + + /// + /// حقوق ماهانه + /// تعیین شده + /// + public double MonthlySalaryDefined { get; private set; } + + /// + /// حقوق نهایی که به پرسنل داده می شود + /// + public double MonthlySalaryPay { get; private set; } + + /// + /// کسر از حقوق + /// + public double DeductionFromSalary { get; private set; } + + /// + /// ویرایش فیش + /// + /// + /// + /// + /// + /// + /// + /// + public void Edit(int mandatoryHours, int totalHoursWorked, int totalDaysWorked, int remainingHours, double monthlySalaryDefined, double monthlySalaryPay, double deductionFromSalary) + { + MandatoryHours = mandatoryHours; + TotalHoursWorked = totalHoursWorked; + TotalDaysWorked = totalDaysWorked; + RemainingHours = remainingHours; + MonthlySalaryDefined = monthlySalaryDefined; + MonthlySalaryPay = monthlySalaryPay; + DeductionFromSalary = deductionFromSalary; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/CreateCheckoutStatus.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/CreateCheckoutStatus.cs new file mode 100644 index 00000000..53b669b5 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/CreateCheckoutStatus.cs @@ -0,0 +1,18 @@ +namespace GozareshgirProgramManager.Domain.CheckoutAgg.Enums; + +public enum CreateCheckoutStatus +{ + /// + /// آماده ایجاد + /// + ReadyToCreate = 1, + /// + /// قبلا ایجاد شده + /// + AlreadyCreated = 2, + /// + /// تنظیمات حقوق انجام نشده + /// + NotSetSalaryPaymentSettings = 3 + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/PersianMonthName.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/PersianMonthName.cs new file mode 100644 index 00000000..0890604b --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/PersianMonthName.cs @@ -0,0 +1,18 @@ +namespace GozareshgirProgramManager.Domain.CheckoutAgg.Enums; + +public enum PersianMonthName +{ + فروردین = 1, + اردیبهشت = 2, + خرداد = 3, + تیر = 4, + مرداد = 5, + شهریور = 6, + مهر = 7, + آبان = 8, + آذر = 9, + دی = 10, + بهمن = 11, + اسفند = 12, + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/TypeOfCheckoutHandler.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/TypeOfCheckoutHandler.cs new file mode 100644 index 00000000..095562e7 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Enums/TypeOfCheckoutHandler.cs @@ -0,0 +1,22 @@ +namespace GozareshgirProgramManager.Domain.CheckoutAgg.Enums; + +/// +/// انتخاب حالت ایجاد یا ویراش تکی / گروهی +/// +public enum TypeOfCheckoutHandler +{ + /// + /// ایجاد گروهی + /// + CreateInGroup = 1, + + /// + /// ویرایش گروهی + /// + GroupEditing = 2, + + /// + /// ویرایش تکی + /// + SingleEdit = 3, +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Repositories/ICheckoutRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Repositories/ICheckoutRepository.cs new file mode 100644 index 00000000..f33b9031 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CheckoutAgg/Repositories/ICheckoutRepository.cs @@ -0,0 +1,9 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CheckoutAgg.Entities; + +namespace GozareshgirProgramManager.Domain.CheckoutAgg.Repositories; + +public interface ICheckoutRepository : IRepository +{ + Task> GetCheckoutListByIds(List checkoutIds); +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Customer.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Customer.cs new file mode 100644 index 00000000..1126077b --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Customer.cs @@ -0,0 +1,34 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CustomerAgg.Events; + +namespace GozareshgirProgramManager.Domain.CustomerAgg; + +public class Customer : EntityBase, IAggregateRoot +{ + public string Name { get; private set; } + public string Email { get; private set; } + public DateTime CreatedAt { get; private set; } + + private Customer() { } // For EF Core + + private Customer(Guid id, string name, string email) + { + Id = id; + Name = name; + Email = email; + CreatedAt = DateTime.UtcNow; + } + + public static Customer Create(string name, string email) + { + var customer = new Customer(Guid.NewGuid(), name, email); + customer.AddDomainEvent(new CustomerRegistered(customer.Id, customer.Name, customer.Email)); + return customer; + } + + public void UpdateName(string name) + { + Name = name; + } +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Entities/Address.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Entities/Address.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Entities/Customer.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Entities/Customer.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegistered.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegistered.cs new file mode 100644 index 00000000..2362f3fc --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegistered.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.CustomerAgg.Events; + +public record CustomerRegistered( + Guid CustomerId, + string Name, + string Email) : IDomainEvent +{ + public DateTime OccurredOn { get; } = DateTime.UtcNow; +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegisteredEvent.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Events/CustomerRegisteredEvent.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/CustomerNotFoundException.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/CustomerNotFoundException.cs new file mode 100644 index 00000000..b50831ad --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/CustomerNotFoundException.cs @@ -0,0 +1,10 @@ +namespace GozareshgirProgramManager.Domain.CustomerAgg.Exceptions; + +public class CustomerNotFoundException : Exception +{ + public CustomerNotFoundException(Guid customerId) + : base($"Customer with ID '{customerId}' was not found.") + { + } +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/DuplicateEmailException.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Exceptions/DuplicateEmailException.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Repositories/ICustomerRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Repositories/ICustomerRepository.cs new file mode 100644 index 00000000..c0b0be7a --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/Repositories/ICustomerRepository.cs @@ -0,0 +1,10 @@ +namespace GozareshgirProgramManager.Domain.CustomerAgg.Repositories; + +public interface ICustomerRepository +{ + Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default); + Task AddAsync(Customer customer, CancellationToken cancellationToken = default); + void Update(Customer customer); + void Delete(Customer customer); +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/ValueObjects/Email.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/ValueObjects/Email.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/ValueObjects/PhoneNumber.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/CustomerAgg/ValueObjects/PhoneNumber.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj new file mode 100644 index 00000000..9ae2365c --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/GozareshgirProgramManager.Domain.csproj @@ -0,0 +1,14 @@ + + + + net10.0 + enable + enable + + + + + + + + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs new file mode 100644 index 00000000..fabc5c3a --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayAgg/Holiday.cs @@ -0,0 +1,25 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.HolidayItemAgg; + +namespace GozareshgirProgramManager.Domain.HolidayAgg; + +public class Holiday : EntityBase +{ + public Holiday(string year) + { + Year = year; + + } + + public string Year { get; private set; } + public List HolidayItems { get; set; } + + public Holiday() + { + HolidayItems = new List(); + } + public void Edit(string year) + { + Year = year; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs new file mode 100644 index 00000000..3a66bd58 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/HolidayItemAgg/HolidayItem.cs @@ -0,0 +1,28 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.HolidayAgg; + +namespace GozareshgirProgramManager.Domain.HolidayItemAgg; + +public class HolidayItem : EntityBase +{ + public HolidayItem(DateTime holidaydate, long holidayId, string holidayYear) + { + Holidaydate = holidaydate; + HolidayId = holidayId; + HolidayYear = holidayYear; + } + + public DateTime Holidaydate { get; private set; } + public long HolidayId { get; private set; } + public string HolidayYear { get; private set; } + + public Holiday Holidayss { get; set; } + + public void Edit(DateTime holidaydate, long holidayId, string holidayYear) + { + Holidaydate = holidaydate; + HolidayId = holidayId; + HolidayYear = holidayYear; + + } +} \ No newline at end of file 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/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs new file mode 100644 index 00000000..33bdfcdf --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/PhaseSection.cs @@ -0,0 +1,41 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// بخش فاز - برای ذخیره تخصیص کاربر و مهارت در سطح Phase +/// +public class PhaseSection : EntityBase +{ + private PhaseSection() { } + + public PhaseSection(Guid phaseId, long userId, Guid skillId) + { + PhaseId = phaseId; + UserId = userId; + SkillId = skillId; + } + + public Guid PhaseId { get; private set; } + public long UserId { get; private set; } + public Guid SkillId { get; private set; } + + // Navigation property + public ProjectPhase Phase { get; private set; } = null!; + + public void UpdateUser(long userId) + { + UserId = userId; + } + + public void UpdateSkill(Guid skillId) + { + SkillId = skillId; + } + public void Update(long userId, Guid skillId) + { + UserId = userId; + SkillId = skillId; + } +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/Project.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/Project.cs new file mode 100644 index 00000000..dc2bfa15 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/Project.cs @@ -0,0 +1,174 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// پروژه - بالاترین سطح در سلسله مراتب و Aggregate Root +/// +public class Project : ProjectHierarchyNode +{ + private readonly List _phases; + private readonly List _projectSections; + + private Project() + { + _phases = new List(); + _projectSections = new List(); + } + + public Project(string name, string? description = null) : base(name, description) + { + _phases = new List(); + _projectSections = new List(); + AddDomainEvent(new ProjectCreatedEvent(Id, name)); + } + + + public IReadOnlyList Phases => _phases.AsReadOnly(); + public IReadOnlyList ProjectSections => _projectSections.AsReadOnly(); + + // Project-specific properties + public DateTime? StartDate { get; private set; } + public DateTime? EndDate { get; private set; } + public DateTime? PlannedStartDate { get; private set; } + public DateTime? PlannedEndDate { get; private set; } + public ProjectStatus Status { get; private set; } = ProjectStatus.Planning; + + + #region Phase Management + + public ProjectPhase AddPhase(string name, string? description = null) + { + var phase = new ProjectPhase(name, Id, description); + _phases.Add(phase); + AddDomainEvent(new PhaseAddedEvent(phase.Id, Id, name)); + return phase; + } + + public void RemovePhase(Guid phaseId) + { + var phase = _phases.FirstOrDefault(p => p.Id == phaseId); + if (phase == null) + throw new InvalidOperationException("فاز مورد نظر یافت نشد"); + + if (phase.Tasks.Any()) + throw new InvalidOperationException("نمی‌توان فازی را که شامل تسک است حذف کرد"); + + _phases.Remove(phase); + AddDomainEvent(new PhaseRemovedEvent(phaseId, Id)); + } + + #endregion + + #region ProjectSection Management + + public void AddProjectSection(long userId, Guid skillId) + { + var existingSection = _projectSections.FirstOrDefault(s => s.UserId == userId && s.SkillId == skillId); + if (existingSection == null) + { + var section = new ProjectSection(Id, userId, skillId); + _projectSections.Add(section); + } + } + + public void ClearProjectSections() + { + _projectSections.Clear(); + } + + #endregion + + #region Date Management + + public void SetDates(DateTime? startDate = null, DateTime? endDate = null) + { + if (startDate.HasValue && endDate.HasValue && startDate > endDate) + throw new ArgumentException("تاریخ شروع نمی‌تواند بعد از تاریخ پایان باشد"); + + StartDate = startDate; + EndDate = endDate; + } + + public void SetPlannedDates(DateTime? plannedStartDate = null, DateTime? plannedEndDate = null) + { + if (plannedStartDate.HasValue && plannedEndDate.HasValue && plannedStartDate > plannedEndDate) + throw new ArgumentException("تاریخ شروع برنامه‌ریزی شده نمی‌تواند بعد از تاریخ پایان برنامه‌ریزی شده باشد"); + + PlannedStartDate = plannedStartDate; + PlannedEndDate = plannedEndDate; + } + + public void UpdateStatus(ProjectStatus status) + { + Status = status; + AddDomainEvent(new ProjectStatusUpdatedEvent(Id, status)); + } + + #endregion + + #region Assignment Management + + public void AssignToUser(long userId, bool cascadeToPhases = true, bool forceOverride = false) + { + HasAssignmentOverride = true; + + if (cascadeToPhases) + { + foreach (var phase in _phases) + { + if (phase.HasAssignmentOverride && !forceOverride) + continue; + + phase.AssignToUser(userId, cascadeToTasks: true, forceOverride, markAsOverride: false); + } + } + + AddDomainEvent(new ProjectAssignedEvent(Id, userId)); + } + + public void Unassign(bool cascadeToPhases = true, bool forceOverride = false) + { + HasAssignmentOverride = true; + + if (cascadeToPhases) + { + foreach (var phase in _phases) + { + if (phase.HasAssignmentOverride && !forceOverride) + continue; + + phase.Unassign(cascadeToTasks: true, forceOverride, markAsOverride: false); + } + } + + AddDomainEvent(new ProjectUnassignedEvent(Id)); + } + + #endregion + + #region Time Calculation + + public override TimeSpan GetTotalTimeSpent() + { + return TimeSpan.FromTicks(_phases.Sum(p => p.GetTotalTimeSpent().Ticks)); + } + + public override TimeSpan GetTotalEstimatedTime() + { + return TimeSpan.FromTicks(_phases.Sum(p => p.GetTotalEstimatedTime().Ticks)); + } + + #endregion + + public void UpdateProjectSectionUser(Guid skillId, long userId) + { + var section = _projectSections.FirstOrDefault(s => s.SkillId == skillId); + if (section != null) + { + section.UpdateUser(userId); + } + } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectHierarchyNode.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectHierarchyNode.cs new file mode 100644 index 00000000..51df2571 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectHierarchyNode.cs @@ -0,0 +1,78 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// کلاس پایه برای تمام نودهای سلسله مراتبی پروژه +/// +public abstract class ProjectHierarchyNode : EntityBase +{ + protected ProjectHierarchyNode() + { + } + + protected ProjectHierarchyNode(string name, string? description = null) + { + Name = name; + Description = description; + } + + public string Name { get; protected set; } = string.Empty; + public string? Description { get; protected set; } + + // Time allocation properties + public bool HasAssignmentOverride { get; protected set; } + + #region Update Methods + + public virtual void UpdateName(string name) + { + if (string.IsNullOrWhiteSpace(name)) + throw new ArgumentException("نام نمی‌تواند خالی باشد", nameof(name)); + + Name = name; + } + + public virtual void UpdateDescription(string? description) + { + Description = description; + } + + public void MarkAsOverridden() + { + HasAssignmentOverride = true; + } + + #endregion + + // #region Time Management + // + // public virtual void SetAllocatedTime(TimeSpan time, bool markAsOverride = true) + // { + // if (time < TimeSpan.Zero) + // throw new ArgumentException("زمان تخصیص‌یافته نمی‌تواند منفی باشد", nameof(time)); + // + // AllocatedTime = time; + // if (markAsOverride) + // { + // HasTimeOverride = true; + // } + // } + // + // public virtual void ClearTimeOverride() + // { + // HasTimeOverride = false; + // AllocatedTime = null; + // } + // + // #endregion + + #region Time Calculation (Abstract) + + public abstract TimeSpan GetTotalTimeSpent(); + public abstract TimeSpan GetTotalEstimatedTime(); + + #endregion +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs new file mode 100644 index 00000000..539ac278 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectPhase.cs @@ -0,0 +1,199 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// فاز پروژه - سطح میانی در سلسله مراتب +/// +public class ProjectPhase : ProjectHierarchyNode +{ + private readonly List _tasks; + private readonly List _phaseSections; + + private ProjectPhase() + { + _tasks = new List(); + _phaseSections = new List(); + } + + public ProjectPhase(string name, Guid projectId, string? description = null) : base(name, description) + { + ProjectId = projectId; + _tasks = new List(); + _phaseSections = new List(); + AddDomainEvent(new PhaseCreatedEvent(Id, projectId, name)); + } + + public Guid ProjectId { get; private set; } + public Project Project { get; private set; } = null!; + public IReadOnlyList Tasks => _tasks.AsReadOnly(); + public IReadOnlyList PhaseSections => _phaseSections.AsReadOnly(); + + // Phase-specific properties + public PhaseStatus Status { get; private set; } = PhaseStatus.Planning; + public DateTime? StartDate { get; private set; } + public DateTime? EndDate { get; private set; } + public int OrderIndex { get; private set; } + + #region Task Management + + public ProjectTask AddTask(string name, string? description = null) + { + var task = new ProjectTask(name, Id, description); + _tasks.Add(task); + AddDomainEvent(new TaskAddedEvent(task.Id, Id, name)); + return task; + } + + public void RemoveTask(Guid taskId) + { + var task = _tasks.FirstOrDefault(t => t.Id == taskId); + if (task == null) + throw new InvalidOperationException("تسک مورد نظر یافت نشد"); + + if (task.Sections.Any()) + throw new InvalidOperationException("نمی‌توان تسکی را که شامل بخش است حذف کرد"); + + _tasks.Remove(task); + AddDomainEvent(new TaskRemovedEvent(taskId, Id)); + } + + #endregion + + #region PhaseSection Management + + public void AddPhaseSection(long userId, Guid skillId) + { + var existingSection = _phaseSections.FirstOrDefault(s => s.UserId == userId && s.SkillId == skillId); + if (existingSection == null) + { + var section = new PhaseSection(Id, userId, skillId); + _phaseSections.Add(section); + } + + } + + public void RemovePhaseSection(long userId, Guid skillId) + { + var section = _phaseSections.FirstOrDefault(s => s.UserId == userId && s.SkillId == skillId); + if (section != null) + { + _phaseSections.Remove(section); + } + } + + public void ClearPhaseSections() + { + _phaseSections.Clear(); + } + + #endregion + + #region Status Management + + public void UpdateStatus(PhaseStatus status) + { + Status = status; + AddDomainEvent(new PhaseStatusUpdatedEvent(Id, status)); + } + + public void SetDates(DateTime? startDate = null, DateTime? endDate = null) + { + if (startDate.HasValue && endDate.HasValue && startDate > endDate) + throw new ArgumentException("تاریخ شروع نمی‌تواند بعد از تاریخ پایان باشد"); + + StartDate = startDate; + EndDate = endDate; + } + + public void SetOrderIndex(int orderIndex) + { + if (orderIndex < 0) + throw new ArgumentException("ترتیب نمی‌تواند منفی باشد", nameof(orderIndex)); + + OrderIndex = orderIndex; + } + + #endregion + + #region Assignment Management + + public void AssignToUser(long userId, bool cascadeToTasks = true, bool forceOverride = false, bool markAsOverride = true) + { + if (markAsOverride) + { + HasAssignmentOverride = true; + } + + if (cascadeToTasks) + { + foreach (var task in _tasks) + { + if (task.HasAssignmentOverride && !forceOverride) + continue; + + task.AssignToUser(userId, cascadeToSections: true, forceOverride, markAsOverride: false); + } + } + + AddDomainEvent(new PhaseAssignedEvent(Id, userId)); + } + + public void Unassign(bool cascadeToTasks = true, bool forceOverride = false, bool markAsOverride = true) + { + if (markAsOverride) + { + HasAssignmentOverride = true; + } + + if (cascadeToTasks) + { + foreach (var task in _tasks) + { + if (task.HasAssignmentOverride && !forceOverride) + continue; + + task.Unassign(cascadeToSections: true, forceOverride, markAsOverride: false); + } + } + + AddDomainEvent(new PhaseUnassignedEvent(Id)); + } + + #endregion + + #region Time Calculation + + public override TimeSpan GetTotalTimeSpent() + { + return TimeSpan.FromTicks(_tasks.Sum(t => t.GetTotalTimeSpent().Ticks)); + } + + public override TimeSpan GetTotalEstimatedTime() + { + return TimeSpan.FromTicks(_tasks.Sum(t => t.GetTotalEstimatedTime().Ticks)); + } + + #endregion + + #region Query Helpers + + public IEnumerable GetTasksWithTimeOverride() + { + return _tasks.Where(t => t.HasTimeOverride); + } + + public IEnumerable GetTasksWithAssignmentOverride() + { + return _tasks.Where(t => t.HasAssignmentOverride); + } + + public IEnumerable GetAllSections() + { + return _tasks.SelectMany(t => t.Sections); + } + + #endregion +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs new file mode 100644 index 00000000..67820d49 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectSection.cs @@ -0,0 +1,34 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// ProjectSection: shortcut container for UserId + SkillId at Project level +/// +public class ProjectSection : EntityBase +{ + private ProjectSection() { } + + public ProjectSection(Guid projectId, long userId, Guid skillId) + { + ProjectId = projectId; + UserId = userId; + SkillId = skillId; + } + + public Guid ProjectId { get; private set; } + public long UserId { get; private set; } + public Guid SkillId { get; private set; } + + public Project Project { get; private set; } = null!; + + public void UpdateUser(long userId) + { + UserId = userId; + } + + public void UpdateSkill(Guid skillId) + { + SkillId = skillId; + } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs new file mode 100644 index 00000000..863e332f --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/ProjectTask.cs @@ -0,0 +1,249 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// تسک - پایین‌ترین سطح در سلسله مراتب که شامل بخش‌ها می‌شود +/// +public class ProjectTask : ProjectHierarchyNode +{ + private readonly List _sections; + + private ProjectTask() + { + _sections = new List(); + } + + public ProjectTask(string name, Guid phaseId, string? description = null) : base(name, description) + { + PhaseId = phaseId; + _sections = new List(); + Priority = TaskPriority.Medium; + AddDomainEvent(new TaskCreatedEvent(Id, phaseId, name)); + } + + public Guid PhaseId { get; private set; } + public ProjectPhase Phase { get; private set; } = null!; + public IReadOnlyList Sections => _sections.AsReadOnly(); + + // Task-specific properties + public Enums.TaskStatus Status { get; private set; } = Enums.TaskStatus.NotStarted; + public TaskPriority Priority { get; private set; } + public DateTime? StartDate { get; private set; } + public DateTime? EndDate { get; private set; } + public DateTime? DueDate { get; private set; } + public int OrderIndex { get; private set; } + public TimeSpan? AllocatedTime { get; protected set; } + public bool HasTimeOverride { get; protected set; } + + #region Section Management + + public void AddSection(TaskSection section, bool cascadeToChildren = false) + { + var existingSection = _sections.FirstOrDefault(s => s.SkillId == section.SkillId); + if (existingSection != null) + { + // اگر userId متفاوت است، ویرایش شود + if (existingSection.CurrentAssignedUserId != section.CurrentAssignedUserId) + { + if (existingSection.CurrentAssignedUserId > 0) + { + existingSection.TransferToUser(existingSection.CurrentAssignedUserId, section.CurrentAssignedUserId); + } + else + { + existingSection.AssignToUser(section.CurrentAssignedUserId); + } + } + } + else + { + _sections.Add(section); + AddDomainEvent(new TaskSectionAddedEvent(Id, section.Id, section.SkillId)); + } + } + + public void AddSection(Guid skillId, long assignedUserId) + { + var existingSection = _sections.FirstOrDefault(s => s.SkillId == skillId); + if (existingSection != null) + { + if (existingSection.CurrentAssignedUserId != assignedUserId) + { + if (existingSection.CurrentAssignedUserId > 0) + { + existingSection.TransferToUser(existingSection.CurrentAssignedUserId, assignedUserId); + } + else + { + existingSection.AssignToUser(assignedUserId); + } + } + return; + } + + var section = new TaskSection(Id, skillId, assignedUserId); + _sections.Add(section); + AddDomainEvent(new TaskSectionAddedEvent(Id, section.Id, skillId)); + } + + public void RemoveSection(Guid sectionId) + { + var section = _sections.FirstOrDefault(s => s.Id == sectionId); + if (section == null) + throw new InvalidOperationException("بخش مورد نظر یافت نشد"); + + _sections.Remove(section); + AddDomainEvent(new TaskSectionRemovedEvent(Id, sectionId)); + } + + public void RemoveSectionBySkill(Guid skillId) + { + var section = _sections.FirstOrDefault(s => s.SkillId == skillId); + if (section != null) + { + _sections.Remove(section); + AddDomainEvent(new TaskSectionRemovedEvent(Id, section.Id)); + } + } + + #endregion + + #region Status Management + + public void UpdateStatus(Enums.TaskStatus status) + { + Status = status; + AddDomainEvent(new TaskStatusUpdatedEvent(Id, status)); + } + + public void SetPriority(TaskPriority priority) + { + Priority = priority; + AddDomainEvent(new TaskPriorityUpdatedEvent(Id, priority)); + } + + public void SetDates(DateTime? startDate = null, DateTime? endDate = null, DateTime? dueDate = null) + { + if (startDate.HasValue && endDate.HasValue && startDate > endDate) + throw new ArgumentException("تاریخ شروع نمی‌تواند بعد از تاریخ پایان باشد"); + + if (dueDate.HasValue && endDate.HasValue && dueDate < endDate) + throw new ArgumentException("تاریخ مهلت نمی‌تواند قبل از تاریخ پایان باشد"); + + StartDate = startDate; + EndDate = endDate; + DueDate = dueDate; + } + + public void SetOrderIndex(int orderIndex) + { + if (orderIndex < 0) + throw new ArgumentException("ترتیب نمی‌تواند منفی باشد", nameof(orderIndex)); + + OrderIndex = orderIndex; + } + + #endregion + + #region Assignment Management + + public void AssignToUser(long userId, bool cascadeToSections = true, bool forceOverride = false, bool markAsOverride = true) + { + if (markAsOverride) + { + HasAssignmentOverride = true; + } + + if (cascadeToSections) + { + foreach (var section in _sections) + { + section.AssignToUser(userId); + } + } + + AddDomainEvent(new TaskAssignedEvent(Id, userId)); + } + + public void Unassign(bool cascadeToSections = true, bool forceOverride = false, bool markAsOverride = true) + { + if (markAsOverride) + { + HasAssignmentOverride = true; + } + + if (cascadeToSections) + { + foreach (var section in _sections) + { + section.Unassign(); + } + } + + AddDomainEvent(new TaskUnassignedEvent(Id)); + } + + #endregion + + #region Time Calculation + + public override TimeSpan GetTotalTimeSpent() + { + return TimeSpan.FromTicks(_sections.Sum(s => s.GetTotalTimeSpent().Ticks)); + } + + public override TimeSpan GetTotalEstimatedTime() + { + return TimeSpan.FromTicks(_sections.Sum(s => s.EstimatedHours.Ticks)); + } + + #endregion + + #region Query Helpers + + public IEnumerable GetSectionsBySkill(Guid skillId) + { + return _sections.Where(s => s.SkillId == skillId); + } + + public TaskSection? GetSectionBySkill(Guid skillId) + { + return _sections.FirstOrDefault(s => s.SkillId == skillId); + } + + public bool HasSection(Guid skillId) + { + return _sections.Any(s => s.SkillId == skillId); + } + + public IEnumerable GetAssignedSections(long userId) + { + return _sections.Where(s => s.CurrentAssignedUserId == userId); + } + + #endregion + #region Time Management + + public void SetAllocatedTime(TimeSpan time, bool markAsOverride = true) + { + if (time < TimeSpan.Zero) + throw new ArgumentException("زمان تخصیص‌یافته نمی‌تواند منفی باشد", nameof(time)); + + AllocatedTime = time; + if (markAsOverride) + { + HasTimeOverride = true; + } + } + + public void ClearTimeOverride() + { + HasTimeOverride = false; + AllocatedTime = null; + } + + #endregion +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs new file mode 100644 index 00000000..e478478d --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs @@ -0,0 +1,223 @@ +using System.Linq; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain._Common.Exceptions; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Events; +using GozareshgirProgramManager.Domain.ProjectAgg.Models; +using GozareshgirProgramManager.Domain.SkillAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// بخش تسک - برای ذخیره کار واقعی که کاربر روی یک مهارت خاص انجام می‌دهد +/// +public class TaskSection : EntityBase +{ + private readonly List _activities; + private readonly List _additionalTimes; + + private TaskSection() + { + _activities = new List(); + _additionalTimes = new List(); + } + + public TaskSection(Guid taskId, Guid skillId, long currentAssignedUserId) + { + TaskId = taskId; + SkillId = skillId; + CurrentAssignedUserId = currentAssignedUserId; + OriginalAssignedUserId = currentAssignedUserId; + InitialEstimatedHours = TimeSpan.Zero; + _activities = new List(); + _additionalTimes = new List(); + Status = TaskSectionStatus.ReadyToStart; + AddDomainEvent(new TaskSectionAddedEvent(taskId, Id, skillId)); + } + + public Guid TaskId { get; private set; } + public Guid SkillId { get; private set; } + public TimeSpan InitialEstimatedHours { get; private set; } + public string? InitialDescription { get; set; } + public TaskSectionStatus Status { get; private set; } + + // شخصی که برای اولین بار این بخش به او اختصاص داده شده (مالک اصلی) + public long OriginalAssignedUserId { get; private set; } + + // شخصی که در حال حاضر این بخش به او اختصاص داده شده + public long CurrentAssignedUserId { get; private set; } + + // Navigation to ProjectTask (must be Task level) + public ProjectTask Task { get; private set; } = null!; + public Skill? Skill { get; set; } + + public IReadOnlyList Activities => _activities.AsReadOnly(); + public IReadOnlyList AdditionalTimes => _additionalTimes.AsReadOnly(); + + // محاسبه تایم نهایی (اولیه + تمام اضافه‌ها) + public TimeSpan FinalEstimatedHours => + TimeSpan.FromTicks(InitialEstimatedHours.Ticks + _additionalTimes.Sum(at => at.Hours.Ticks)); + + // برای backward compatibility + public TimeSpan EstimatedHours => FinalEstimatedHours; + + public void AddAdditionalTime(TimeSpan additionalHours, string? reason = null, long? addedByUserId = null) + { + if (additionalHours <= TimeSpan.Zero) + throw new BadRequestException("تایم اضافی باید بزرگتر از صفر باشد", nameof(additionalHours)); + + var additionalTime = new TaskSectionAdditionalTime(additionalHours, reason, addedByUserId); + _additionalTimes.Add(additionalTime); + } + + public void UpdateInitialEstimatedHours(TimeSpan newInitialEstimate, string initialDescription) + { + if (newInitialEstimate <= TimeSpan.Zero) + throw new BadRequestException("تایم تخمینی اولیه باید بزرگتر از صفر باشد", nameof(newInitialEstimate)); + + InitialEstimatedHours = newInitialEstimate; + InitialDescription = initialDescription; + } + + public void RemoveAdditionalTime(Guid additionalTimeId) + { + var additionalTime = _additionalTimes.FirstOrDefault(at => at.Id == additionalTimeId); + if (additionalTime == null) + throw new BadRequestException("تایم اضافی مورد نظر یافت نشد"); + + _additionalTimes.Remove(additionalTime); + } + + public TimeSpan GetTotalAdditionalTime() + { + return TimeSpan.FromTicks(_additionalTimes.Sum(at => at.Hours.Ticks)); + } + + public void UnassignUser() + { + if (_activities.Any(a => a.IsActive)) + { + throw new BadRequestException("نمی‌توان کاربری را که در حال کار است حذف کرد"); + } + + CurrentAssignedUserId = 0; + UpdateStatus(TaskSectionStatus.NotAssigned); + } + + public void StartWork(long userId, string? notes = null) + { + if (CurrentAssignedUserId != userId) + { + throw new BadRequestException("کاربر مجاز به شروع این بخش نیست"); + } + + // if (Status == TaskSectionStatus.Completed) + // { + // throw new BadRequestException("این بخش قبلاً تکمیل شده است"); + // } + + if (_activities.Any(a => a.IsActive)) + { + throw new BadRequestException("یک فعالیت در حال انجام وجود دارد"); + } + + var activity = new TaskSectionActivity(Id, userId, notes); + _activities.Add(activity); + + + UpdateStatus(TaskSectionStatus.InProgress); + } + + public void StopWork(long userId, TaskSectionStatus taskSectionStatus, string? endNotes = null) + { + var activeActivity = _activities.FirstOrDefault(a => a.IsActive); + if (activeActivity == null) + { + throw new BadRequestException("هیچ فعالیت فعالی یافت نشد"); + } + + if (activeActivity.UserId != userId) + { + throw new BadRequestException("کاربر مجاز به توقف این فعالیت نیست"); + } + + UpdateStatus(taskSectionStatus); + activeActivity.StopWork(endNotes); + } + + public void CompleteSection() + { + if (_activities.Any(a => a.IsActive)) + { + throw new BadRequestException("نمی‌توان بخشی را که فعالیت فعال دارد تکمیل کرد"); + } + + UpdateStatus(TaskSectionStatus.Completed); + } + + public void UpdateStatus(TaskSectionStatus status) + { + var oldStatus = Status; + Status = status; + AddDomainEvent(new TaskSectionStatusChangedEvent(Id, oldStatus, status)); + } + + public TimeSpan GetTotalTimeSpent() + { + return TimeSpan.FromTicks(_activities.Sum(a => a.GetTimeSpent().Ticks)); + } + + public bool IsCompleted() + { + return Status == TaskSectionStatus.Completed; + } + + public bool IsInProgress() + { + return _activities.Any(a => a.IsActive); + } + + public void AssignToUser(long userId) + { + if (OriginalAssignedUserId == 0) + { + OriginalAssignedUserId = userId; + } + + CurrentAssignedUserId = userId; + + if (Status == TaskSectionStatus.NotAssigned) + { + UpdateStatus(TaskSectionStatus.ReadyToStart); + } + + AddDomainEvent(new TaskSectionAssignedEvent(Id, userId)); + } + + public void TransferToUser(long fromUserId, long toUserId) + { + if (CurrentAssignedUserId != fromUserId) + { + throw new BadRequestException("کاربر فعلی با کاربر منبع مطابقت ندارد"); + } + + if (_activities.Any(a => a.IsActive)) + { + throw new BadRequestException("نمی‌توان بخشی را که در حال انجام است انتقال داد"); + } + + OriginalAssignedUserId = toUserId; + CurrentAssignedUserId = toUserId; + AddDomainEvent(new TaskSectionTransferredEvent(Id, fromUserId, toUserId)); + } + + public void Unassign() + { + UnassignUser(); + } + + public void ClearAdditionalTimes() + { + _additionalTimes.Clear(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionActivity.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionActivity.cs new file mode 100644 index 00000000..85e60d0d --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionActivity.cs @@ -0,0 +1,57 @@ +using System.Diagnostics.CodeAnalysis; +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// فعالیت کاری روی یک بخش +/// +public class TaskSectionActivity : EntityBase +{ + private TaskSectionActivity() { } + + public TaskSectionActivity(Guid sectionId, long userId, string? notes = null) + { + SectionId = sectionId; + UserId = userId; + StartDate = DateTime.Now; + Notes = notes; + IsActive = true; + } + + public Guid SectionId { get; private set; } + public long UserId { get; private set; } + public DateTime StartDate { get; private set; } + public DateTime? EndDate { get; private set; } + public string? Notes { get; private set; } + public string? EndNotes { get; private set; } + public bool IsActive { get; private set; } + + // Navigation property + public TaskSection Section { get; private set; } = null!; + + public void StopWork(string? endNotes = null) + { + if (!IsActive) + throw new InvalidOperationException("این فعالیت قبلاً متوقف شده است."); + + EndDate = DateTime.Now; + EndNotes = endNotes; + IsActive = false; + } + + public TimeSpan GetTimeSpent() + { + if (IsActive) + { + return DateTime.Now - StartDate; + } + + return (EndDate ?? DateTime.Now) - StartDate; + } + + public void UpdateNotes(string? notes) + { + Notes = notes; + } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionAdditionalTime.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionAdditionalTime.cs new file mode 100644 index 00000000..657f76cc --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSectionAdditionalTime.cs @@ -0,0 +1,29 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +/// +/// زمان اضافی اضافه شده بعد از تخمین اولیه +/// +public class TaskSectionAdditionalTime : EntityBase +{ + private TaskSectionAdditionalTime() { } + + public TaskSectionAdditionalTime(TimeSpan hours, string? reason = null, long? addedByUserId = null) + { + Hours = hours; + Reason = reason; + AddedByUserId = addedByUserId; + AddedAt = DateTime.UtcNow; + } + + public TimeSpan Hours { get; private set; } + public string? Reason { get; private set; } + public long? AddedByUserId { get; private set; } + public DateTime AddedAt { get; private set; } + + public void UpdateReason(string? reason) + { + Reason = reason; + } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/UserTimeReport.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/UserTimeReport.cs new file mode 100644 index 00000000..d3525513 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/UserTimeReport.cs @@ -0,0 +1,18 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +public class UserTimeReport +{ + public long UserId { get; set; } + public string UserName { get; set; } = string.Empty; + public TimeSpan TotalTimeSpent { get; set; } + public TimeSpan EstimatedTime { get; set; } + public int ActivityCount { get; set; } + public DateTime LastActivity { get; set; } + public DateTime? FirstActivity { get; set; } + public double EfficiencyRate => EstimatedTime.TotalHours > 0 ? + (EstimatedTime.TotalHours / TotalTimeSpent.TotalHours) * 100 : 0; + + public bool IsOvertime => TotalTimeSpent > EstimatedTime; + + public TimeSpan TimeDifference => TotalTimeSpent - EstimatedTime; +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/PhaseStatus.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/PhaseStatus.cs new file mode 100644 index 00000000..a2aa534c --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/PhaseStatus.cs @@ -0,0 +1,37 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +/// +/// وضعیت فاز پروژه +/// +public enum PhaseStatus +{ + /// + /// در حال برنامه‌ریزی + /// + Planning = 0, + + /// + /// آماده شروع + /// + Ready = 1, + + /// + /// در حال اجرا + /// + InProgress = 2, + + /// + /// متوقف شده + /// + OnHold = 3, + + /// + /// تکمیل شده + /// + Completed = 4, + + /// + /// لغو شده + /// + Cancelled = 5 +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectHierarchyLevel.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectHierarchyLevel.cs new file mode 100644 index 00000000..f5a2eb28 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectHierarchyLevel.cs @@ -0,0 +1,23 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +/// +/// سطوح مختلف در سلسله مراتب پروژه +/// +public enum ProjectHierarchyLevel +{ + /// + /// سطح پروژه (بالاترین سطح) + /// + Project = 0, + + /// + /// سطح فاز پروژه + /// + Phase = 1, + + /// + /// سطح تسک + /// + Task = 2, +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectStatus.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectStatus.cs new file mode 100644 index 00000000..fbd58771 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/ProjectStatus.cs @@ -0,0 +1,37 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +/// +/// وضعیت پروژه +/// +public enum ProjectStatus +{ + /// + /// در حال برنامه‌ریزی + /// + Planning = 0, + + /// + /// آماده شروع + /// + Ready = 1, + + /// + /// در حال اجرا + /// + InProgress = 2, + + /// + /// متوقف شده + /// + OnHold = 3, + + /// + /// تکمیل شده + /// + Completed = 4, + + /// + /// لغو شده + /// + Cancelled = 5 +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskPriority.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskPriority.cs new file mode 100644 index 00000000..13ccd784 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskPriority.cs @@ -0,0 +1,27 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +/// +/// اولویت تسک +/// +public enum TaskPriority +{ + /// + /// پایین + /// + Low = 0, + + /// + /// متوسط + /// + Medium = 1, + + /// + /// بالا + /// + High = 2, + + /// + /// بحرانی + /// + Critical = 3 +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskSectionStatus.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskSectionStatus.cs new file mode 100644 index 00000000..d5208bfb --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskSectionStatus.cs @@ -0,0 +1,10 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +public enum TaskSectionStatus +{ + NotAssigned = 0, // تخصیص داده نشده + ReadyToStart = 1, // آماده شروع + InProgress = 2, // درحال انجام + Incomplete = 3, // ناتمام شده + Completed = 4 // تکمیل شده +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskStatus.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskStatus.cs new file mode 100644 index 00000000..fc0d3c20 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Enums/TaskStatus.cs @@ -0,0 +1,9 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +public enum TaskStatus +{ + NotStarted = 1, + InProgress = 2, + Completed = 3, + OnHold = 4 +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs new file mode 100644 index 00000000..e823967e --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Events/ProjectEvents.cs @@ -0,0 +1,177 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using TaskStatus = GozareshgirProgramManager.Domain.ProjectAgg.Enums.TaskStatus; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Events; + +// Project Events +public record ProjectCreatedEvent(Guid ProjectId, string Name) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectStatusUpdatedEvent(Guid ProjectId, ProjectStatus Status) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectAssignedEvent(Guid ProjectId, long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectUnassignedEvent(Guid ProjectId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +// Phase Events +public record PhaseCreatedEvent(Guid PhaseId, Guid ProjectId, string Name) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record PhaseAddedEvent(Guid PhaseId, Guid ProjectId, string Name) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record PhaseRemovedEvent(Guid PhaseId, Guid ProjectId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record PhaseStatusUpdatedEvent(Guid PhaseId, PhaseStatus Status) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record PhaseAssignedEvent(Guid PhaseId, long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record PhaseUnassignedEvent(Guid PhaseId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +// Task Events +public record TaskCreatedEvent(Guid TaskId, Guid PhaseId, string Name) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskAddedEvent(Guid TaskId, Guid PhaseId, string Name) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskRemovedEvent(Guid TaskId, Guid PhaseId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskStatusUpdatedEvent(Guid TaskId, TaskStatus Status) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskPriorityUpdatedEvent(Guid TaskId, TaskPriority Priority) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskAssignedEvent(Guid TaskId, long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskUnassignedEvent(Guid TaskId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskSectionAddedEvent(Guid TaskId, Guid SectionId, Guid SkillId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskSectionRemovedEvent(Guid TaskId, Guid SectionId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +// TaskSection Events +public record TaskSectionStatusChangedEvent(Guid SectionId, TaskSectionStatus OldStatus, TaskSectionStatus NewStatus) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskSectionAssignedEvent(Guid SectionId, long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record TaskSectionTransferredEvent(Guid SectionId, long FromUserId, long ToUserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +// Section Events (Legacy - keeping for backward compatibility) +public record ProjectPhaseAddedEvent(Guid ProjectId, Guid PhaseId, string PhaseName) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectTaskStatusChangedEvent(Guid SectionId, TaskStatus OldStatus, TaskStatus NewStatus) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectSectionAddedEvent(Guid SectionId, Guid TaskId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + + +public record ProjectSectionAssignedEvent(Guid SectionId, long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectSectionTransferredEvent(Guid SectionId, long FromUserId, long ToUserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record WorkStartedEvent(Guid SectionId, long UserId, DateTime StartTime, string? Notes) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record WorkStoppedEvent(Guid SectionId, long UserId, DateTime StartTime, DateTime EndTime, TimeSpan Duration, string? Notes) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record ProjectSectionCompletedEvent(Guid ProjectId, long UserId, TimeSpan TotalTimeSpent, string? Notes) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record AdditionalTimeAddedEvent(Guid ProjectId, Guid AdditionalTimeId, TimeSpan Hours, string? Reason, long? AddedByUserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record AdditionalTimeRemovedEvent(Guid ProjectId, Guid AdditionalTimeId, TimeSpan RemovedHours) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record InitialEstimatedTimeUpdatedEvent(Guid ProjectId, TimeSpan OldEstimate, TimeSpan NewEstimate) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Models/UserTimeReport.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Models/UserTimeReport.cs new file mode 100644 index 00000000..c02c1a39 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Models/UserTimeReport.cs @@ -0,0 +1,12 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.Models; + +/// +/// گزارش زمان کاربر برای یک بخش پروژه +/// +public class UserTimeReport +{ + public long UserId { get; set; } + public TimeSpan TotalTimeSpent { get; set; } + public int ActivityCount { get; set; } + public DateTime LastActivity { get; set; } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IPhaseSectionRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IPhaseSectionRepository.cs new file mode 100644 index 00000000..db8fb7e1 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IPhaseSectionRepository.cs @@ -0,0 +1,6 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain._Common; +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +public interface IPhaseSectionRepository : IRepository +{ +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectPhaseRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectPhaseRepository.cs new file mode 100644 index 00000000..8a29e014 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectPhaseRepository.cs @@ -0,0 +1,33 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +/// +/// Repository interface for ProjectPhase entity +/// +public interface IProjectPhaseRepository : IRepository +{ + /// + /// Get phase with all its tasks + /// + Task GetWithTasksAsync(Guid phaseId); + + /// + /// Get phases by project ID + /// + Task> GetByProjectIdAsync(Guid projectId); + + + /// + /// Get phases with assignment overrides + /// + Task> GetPhasesWithAssignmentOverridesAsync(); + + /// + /// Get phases by status + /// + Task> GetByStatusAsync(ProjectAgg.Enums.PhaseStatus status); + + void Remove(ProjectPhase phase); +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectRepository.cs new file mode 100644 index 00000000..5514e492 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectRepository.cs @@ -0,0 +1,38 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +/// +/// Repository interface for Project aggregate root +/// +public interface IProjectRepository : IRepository +{ + /// + /// Get project with all its phases and tasks + /// + Task GetWithFullHierarchyAsync(Guid projectId); + + /// + /// Get project with phases only + /// + Task GetWithPhasesAsync(Guid projectId); + + /// + /// Get projects by status + /// + Task> GetByStatusAsync(ProjectAgg.Enums.ProjectStatus status); + + + /// + /// Get projects with assignment overrides + /// + Task> GetProjectsWithAssignmentOverridesAsync(); + + /// + /// Search projects by name + /// + Task> SearchByNameAsync(string searchTerm); + + void Remove(Project project); +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectSectionRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectSectionRepository.cs new file mode 100644 index 00000000..2838c8d6 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectSectionRepository.cs @@ -0,0 +1,9 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +public interface IProjectSectionRepository : IRepository +{ +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectTaskRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectTaskRepository.cs new file mode 100644 index 00000000..8b0ff688 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/IProjectTaskRepository.cs @@ -0,0 +1,47 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +/// +/// Repository interface for ProjectTask entity +/// +public interface IProjectTaskRepository : IRepository +{ + /// + /// Get task with all its sections + /// + Task GetWithSectionsAsync(Guid taskId); + + /// + /// Get tasks by phase ID + /// + Task> GetByPhaseIdAsync(Guid phaseId); + + /// + /// Get tasks with time overrides + /// + Task> GetTasksWithTimeOverridesAsync(); + + /// + /// Get tasks with assignment overrides + /// + Task> GetTasksWithAssignmentOverridesAsync(); + + /// + /// Get tasks by status + /// + Task> GetByStatusAsync(ProjectAgg.Enums.TaskStatus status); + + /// + /// Get tasks by priority + /// + Task> GetByPriorityAsync(ProjectAgg.Enums.TaskPriority priority); + + /// + /// Get tasks assigned to user + /// + Task> GetAssignedToUserAsync(long userId); + + void Remove(ProjectTask task); +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionActivityRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionActivityRepository.cs new file mode 100644 index 00000000..d20ef6e0 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionActivityRepository.cs @@ -0,0 +1,16 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +public interface ITaskSectionActivityRepository:IRepository +{ + Task GetByIdAsync(Guid id); + Task> GetBySectionIdAsync(Guid sectionId); + Task> GetByUserIdAsync(long userId); + Task> GetActiveByUserAsync(long userId); + Task> GetByDateRangeAsync(DateTime from, DateTime to); + Task> GetByDateRangeUserIdAsync(DateTime from, DateTime to,long userId); + Task GetTotalTimeSpentByUserInRangeAsync(long userId, DateTime from, DateTime to); + Task> GetTotalTimeSpentPerUserInRangeAsync(DateTime from, DateTime to); +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs new file mode 100644 index 00000000..bedf59bf --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +public interface ITaskSectionRepository: IRepository +{ + Task GetByIdWithActivitiesAsync(Guid id, CancellationToken cancellationToken = default); + + + Task GetByIdWithFullDataAsync(Guid id, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/TimeTracking.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/TimeTracking.cs new file mode 100644 index 00000000..1018b220 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/TimeTracking.cs @@ -0,0 +1,75 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.ProjectAgg.ValueObjects; + +public class TimeRange : ValueObject +{ + public DateTime Start { get; private set; } + public DateTime? End { get; private set; } + + public TimeRange(DateTime start) + { + Start = start; + } + + public TimeRange(DateTime start, DateTime end) + { + if (start >= end) + throw new ArgumentException("Start time must be before end time"); + + Start = start; + End = end; + } + + public TimeSpan Duration => End.HasValue ? End.Value - Start : DateTime.UtcNow - Start; + public bool IsActive => !End.HasValue; + + public void Complete(DateTime endTime) + { + if (End.HasValue) + throw new InvalidOperationException("Time range is already completed"); + + if (endTime <= Start) + throw new ArgumentException("End time must be after start time"); + + End = endTime; + } + + protected override IEnumerable GetEqualityComponents() + { + yield return Start; + yield return End ?? DateTime.MinValue; + } +} + +public class WorkSession : ValueObject +{ + public long UserId { get; private set; } + public TimeRange TimeRange { get; private set; } + public string? Notes { get; private set; } + public string? EndNotes { get; private set; } + + public WorkSession(long userId, DateTime startTime, string? notes = null) + { + UserId = userId; + TimeRange = new TimeRange(startTime); + Notes = notes; + } + + public void Complete(DateTime endTime, string? endNotes = null) + { + TimeRange.Complete(endTime); + EndNotes = endNotes; + } + + public TimeSpan Duration => TimeRange.Duration; + public bool IsActive => TimeRange.IsActive; + + protected override IEnumerable GetEqualityComponents() + { + yield return UserId; + yield return TimeRange; + yield return Notes ?? string.Empty; + yield return EndNotes ?? string.Empty; + } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/UserSkillAssignment.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/UserSkillAssignment.cs new file mode 100644 index 00000000..491e2000 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/ValueObjects/UserSkillAssignment.cs @@ -0,0 +1,31 @@ +namespace GozareshgirProgramManager.Domain.ProjectAgg.ValueObjects; + +/// +/// Value Object برای ذخیره تخصیص کاربر و مهارت در سطوح بالاتر (Project/Phase) +/// این اطلاعات می‌تواند به صورت shortcut در Task و Section استفاده شود +/// +public class UserSkillAssignment +{ + public UserSkillAssignment(long userId, Guid skillId) + { + UserId = userId; + SkillId = skillId; + } + + public long UserId { get; private set; } + public Guid SkillId { get; private set; } + + public override bool Equals(object? obj) + { + if (obj is not UserSkillAssignment other) + return false; + + return UserId == other.UserId && SkillId == other.SkillId; + } + + public override int GetHashCode() + { + return HashCode.Combine(UserId, SkillId); + } +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs new file mode 100644 index 00000000..81bb10ba --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs @@ -0,0 +1,48 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.PermissionAgg.Entities; +using System.Security.Principal; +using System.Xml.Linq; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.RoleAgg.Entities; + +public class Role : EntityBase +{ + /// + /// نام نقش + /// + public string RoleName { get; private set; } + + + /// + /// لیست پرمیشن کد ها + /// + public List Permissions { get; private set; } + + /// + /// ای دی نقش در گزارشگیر + /// + public long? GozareshgirRoleId { get; private set; } + + + protected Role() + { + } + + public Role(string roleName,long? gozareshgirRolId, List permissions) + { + RoleName = roleName; + Permissions = permissions; + GozareshgirRoleId = gozareshgirRolId; + + } + + + public void Edit(string roleName, List permissions) + { + RoleName = roleName; + Permissions = permissions; + } + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs new file mode 100644 index 00000000..6d30ae22 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.RoleAgg.Repositories; + +public interface IRoleRepository : IRepository +{ + Task GetByGozareshgirRoleIdAsync(long? gozareshgirRolId); + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs new file mode 100644 index 00000000..b8a05dc9 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs @@ -0,0 +1,19 @@ +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.RoleUserAgg; + +public class RoleUser +{ + public RoleUser(long roleId) + { + RoleId = roleId; + } + + public long Id { get; private set; } + public long RoleId { get; private set; } + + + public User User { get; set; } + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/DTOs/UserSalarySettingDto.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/DTOs/UserSalarySettingDto.cs new file mode 100644 index 00000000..12e5f50d --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/DTOs/UserSalarySettingDto.cs @@ -0,0 +1,43 @@ +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; + +namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; + +public record UserSalarySettingDto +{ + + /// + /// آی دی کاربر + /// + public long UserId { get; set; } + + /// + /// کار در تعطیلات رسمی + /// + public bool HolidayWorking { get; set; } + + /// + /// حقوق ماهانه + /// + public double MonthlySalary { get; set; } + + + public string FullName { get; set; } + + public List WorkingHoursListDto { get; set; } +} + + +public record WorkingHoursListDto +{ + /// + /// مدت زمان شیفت + /// + public TimeSpan ShiftDuration { get; set; } + /// + /// عدد روز از ماه + /// + public PersianDayOfWeek PersianDayOfWeek { get; set; } + + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs new file mode 100644 index 00000000..d98e3454 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs @@ -0,0 +1,94 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; + +/// +/// تنظیمات پرداخت حقوق +/// +public class SalaryPaymentSetting : EntityBase +{ + /// + /// ایجاد تنظیمات حقوق + /// برای اولین بار + /// + /// + /// + /// + /// + public SalaryPaymentSetting(bool holidayWorking, long userId, double monthlySalary, List workingHoursList) + { + HolidayWorking = holidayWorking; + UserId = userId; + MonthlySalary = monthlySalary; + WorkingHoursList = workingHoursList; + StartSettingDate = new DateTime(2025, 3, 21); + } + /// + /// افزودن تنظیمات جدید + /// + /// + /// + /// + /// + /// + public SalaryPaymentSetting(bool holidayWorking, long userId, List workingHoursList, DateTime startSettingDate) + { + HolidayWorking = holidayWorking; + UserId = userId; + + WorkingHoursList = workingHoursList; + StartSettingDate = startSettingDate; + } + + + protected SalaryPaymentSetting() + { + + } + + /// + /// کارکردن در تعطیلات رسمی + /// + public bool HolidayWorking { get; private set; } + + + /// + /// آی دی کاربر + /// + public long UserId { get; private set; } + + /// + /// دستمزد ماهانه + /// + public double MonthlySalary { get; private set; } + + /// + /// تاریخ شروع تنظیمات + /// + public DateTime? StartSettingDate { get; private set; } + + /// + /// تاریخ پایان تنظیمات + /// + public DateTime? EndSettingDate { get; private set; } + + + public List WorkingHoursList { get; set; } + + + /// + /// ویرایش تنظیمات حقوق + /// + /// + /// + public void Edit(bool holidayWorking, double monthlySalary, List workingHoursList) + { + HolidayWorking = holidayWorking; + WorkingHoursList = workingHoursList; + MonthlySalary = monthlySalary; + } + + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/WorkingHours.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/WorkingHours.cs new file mode 100644 index 00000000..0522364f --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/WorkingHours.cs @@ -0,0 +1,164 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; +using System.ComponentModel.DataAnnotations.Schema; + +namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; + +/// +/// تخصیص ساعت کاری به کاربر +/// +public class WorkingHours +{ + public WorkingHours(TimeSpan startShiftOne, TimeSpan endShiftOne, TimeSpan startShiftTwo, TimeSpan endShiftTwo, TimeSpan restTime, bool hasShiftOne, bool hasShiftTwo, bool hasRestTime, PersianDayOfWeek persianDayOfWeek, bool isActiveDay) + { + StartShiftOne = hasShiftOne? startShiftOne : TimeSpan.Zero; + EndShiftOne = hasShiftOne ? endShiftOne : TimeSpan.Zero; + StartShiftTwo = hasShiftTwo ? startShiftTwo : TimeSpan.Zero; + EndShiftTwo = hasShiftTwo ? endShiftTwo : TimeSpan.Zero; + RestTime = hasRestTime ? restTime : TimeSpan.Zero; + HasShiftOne = hasShiftOne; + HasShiftTow = hasShiftTwo; + HasRestTime = hasRestTime; + PersianDayOfWeek = persianDayOfWeek; + IsActiveDay = isActiveDay; + + ComputeShiftDuration(startShiftOne, endShiftOne, startShiftTwo, endShiftTwo, restTime, hasShiftOne, hasShiftTwo,hasRestTime); + } + + + private WorkingHours(bool isActiveDay) + { + IsActiveDay = isActiveDay; + } + + public long Id { get; private set; } + + /// + /// ساعت شروع شیفت کاری + /// + public TimeSpan StartShiftOne { get; private set; } + + /// + /// ساعت پایان شیفت کاری + /// + public TimeSpan EndShiftOne { get; private set; } + + + /// + /// ساعت شروع شیفت دوم کاری + /// + public TimeSpan StartShiftTwo { get; private set; } + + /// + /// ساعت پایان شیفت دوم کاری + /// + public TimeSpan EndShiftTwo { get; private set; } + + /// + /// مدت استراحت + /// + public TimeSpan RestTime { get; private set; } + + + /// + /// آیا مقطع مار اول دارد + /// + public bool HasShiftOne { get; private set; } + + /// + /// آیا مقطع کار دوم دارد + /// + public bool HasShiftTow { get; private set; } + + /// + /// آیا ساعت استراحت دارد + /// + public bool HasRestTime { get; private set; } + + /// + /// بازه زمانی شیفت + /// + public int ShiftDurationInMinutes { get; private set; } + + [NotMapped] + public TimeSpan ShiftDuration + { + get => TimeSpan.FromMinutes(ShiftDurationInMinutes); + private set => ShiftDurationInMinutes = (int)value.TotalMinutes; + } + + /// + /// عدد روز از ماه + /// + public PersianDayOfWeek PersianDayOfWeek { get; private set; } + + + + + /// + /// آیا این روز هفته + /// فعال است + /// + public bool IsActiveDay { get; private set; } + + public SalaryPaymentSetting SalaryPaymentSetting { get; set; } + + /// + /// بدست آوردن بازه زمانی شیفت + /// + /// + /// + /// + private void ComputeShiftDuration(TimeSpan startShift, TimeSpan endShift, TimeSpan startShiftTwo, TimeSpan endShiftTwo, TimeSpan restTime, bool hasShiftOne, bool hasShiftTwo, bool hasRestTime) + { + var now = DateTime.Now.Date; + + if (hasShiftOne && !hasShiftTwo) + { + DateTime startOne = new DateTime(now.Year, now.Month, now.Day, startShift.Hours, startShift.Minutes,0); + DateTime endOne = new DateTime(now.Year, now.Month, now.Day, endShift.Hours, endShift.Minutes, 0); + + + if (endOne <= startOne) + endOne = endOne.AddDays(1); + var shiftDuration = (endOne - startOne); + + ShiftDuration = hasRestTime ? (shiftDuration - restTime) : shiftDuration; + } + else if (!hasShiftOne && hasShiftTwo) + { + DateTime startTow = new DateTime(now.Year, now.Month, now.Day, startShiftTwo.Hours, startShiftTwo.Minutes, 0); + DateTime endTow = new DateTime(now.Year, now.Month, now.Day, endShiftTwo.Hours, endShiftTwo.Minutes, 0); + + if (endTow <= startTow) + endTow = endTow.AddDays(1); + + + ShiftDuration = (endTow - startTow); + } + else if (hasShiftOne && hasShiftTwo) + { + DateTime startOne = new DateTime(now.Year, now.Month, now.Day, startShift.Hours, startShift.Minutes, 0); + DateTime endOne = new DateTime(now.Year, now.Month, now.Day, endShift.Hours, endShift.Minutes, 0); + if (endOne <= startOne){} + endOne = endOne.AddDays(1); + + var shiftOneDuration = (endOne - startOne); + + DateTime startTow = new DateTime(endOne.Year, endOne.Month, endOne.Day, startShiftTwo.Hours, startShiftTwo.Minutes, 0); + DateTime endTow = new DateTime(endOne.Year, endOne.Month, endOne.Day, endShiftTwo.Hours, endShiftTwo.Minutes, 0); + + if (endTow <= startTow) + endTow = endTow.AddDays(1); + + var shiftDurationTow = (endTow - startTow); + ShiftDuration = shiftOneDuration.Add(shiftDurationTow); + } + else + { + ShiftDurationInMinutes = 0; + } + + } + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/HasSalarySettings.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/HasSalarySettings.cs new file mode 100644 index 00000000..589c71d1 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/HasSalarySettings.cs @@ -0,0 +1,20 @@ +namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; + +public enum HasSalarySettings +{ + /// + /// پیش فرض هر دو حالت + /// + Default = 0, + + /// + /// تنظیمات حقوق و ساعت دارد + /// + HasSettings = 1, + /// + /// تنظیمات حقوق و ساعت ندارد + /// + DoesNotHaveSettings = 2 + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/PersianDayOfWeek.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/PersianDayOfWeek.cs new file mode 100644 index 00000000..ad78b55a --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Enums/PersianDayOfWeek.cs @@ -0,0 +1,29 @@ +namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; + +public enum PersianDayOfWeek +{ + /// شنبه + Shanbeh = 1, + + /// یکشنبه + YekShanbeh = 2, + + /// دوشنبه + DoShanbeh = 3, + + /// سه شنبه + SeShanbeh = 4, + + /// چهارشنبه + CheharShanbeh = 5, + + /// پنجشنبه + PanjShanbeh = 6, + + /// جمعه + Jomeh = 7, + + + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Repositories/ISalaryPaymentSettingRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Repositories/ISalaryPaymentSettingRepository.cs new file mode 100644 index 00000000..4bc45f73 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Repositories/ISalaryPaymentSettingRepository.cs @@ -0,0 +1,26 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; + +namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; + +public interface ISalaryPaymentSettingRepository : IRepository +{ + /// + /// دریافت لیست تنظیمات حقوق + /// + /// + /// + Task GetSalarySettingByUserId(long userId); + + + Task> GetAllSettings(List userIdList); + + /// + /// حذف گروهی تنظیمات حقوق + /// + /// + /// + void RemoveRangeSalarySettings(List removedItems); +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Entities/Skill.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Entities/Skill.cs new file mode 100644 index 00000000..662f9544 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Entities/Skill.cs @@ -0,0 +1,16 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; + +namespace GozareshgirProgramManager.Domain.SkillAgg.Entities; + +public class Skill:EntityBase, IAggregateRoot +{ + public Skill(string name) + { + Name = name; + Sections = []; + } + + public string Name { get; set; } + public List Sections { get; set; } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Repositories/ISkillRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Repositories/ISkillRepository.cs new file mode 100644 index 00000000..e6152c60 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SkillAgg/Repositories/ISkillRepository.cs @@ -0,0 +1,9 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.SkillAgg.Entities; + +namespace GozareshgirProgramManager.Domain.SkillAgg.Repositories; + +public interface ISkillRepository: IRepository +{ + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs new file mode 100644 index 00000000..d112136d --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs @@ -0,0 +1,169 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.PermissionAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.RoleUserAgg; + +namespace GozareshgirProgramManager.Domain.UserAgg.Entities; + +/// +/// کاربر +/// +public class User : EntityBase +{ + /// + /// ایجاد + /// + /// + /// + /// + /// + /// + /// + /// + public User(string fullName, string userName, string password, string mobile, string? email, long? accountId, List roles) + { + FullName = fullName; + UserName = userName; + Password = password; + Mobile = mobile; + Email = email; + IsActive = true; + AccountId = accountId; + RoleUser = roles; + } + + protected User() + { + + } + /// + /// نام و نام خانوادگی + /// + public string FullName { get; private set; } + + /// + /// نام کاربری + /// + public string UserName { get; private set; } + + /// + /// گذرواژه + /// + public string Password { get; private set; } + + /// + /// مسیر عکس پروفایل + /// + public string ProfilePhotoPath { get; private set; } + + /// + /// شماره موبایل + /// + public string Mobile { get; set; } + + /// + /// ایمیل + /// + public string? Email { get; private set; } + + /// + /// فعال/غیر فعال بودن یوزر + /// + public bool IsActive { get; private set; } + + + /// + /// کد یکبارمصرف ورود + /// + public string? VerifyCode { get; private set; } + + /// + /// آی دی کاربر در گزارشگیر + /// + public long? AccountId { get; private set; } + + + /// + /// لیست پرمیشن کد ها + /// + public List RoleUser { get; private set; } + + /// + /// لیست توکن‌های تازه‌سازی + /// + private List _refreshTokens = new(); + public IReadOnlyCollection RefreshTokens => _refreshTokens.AsReadOnly(); + + /// + /// آپدیت کاربر + /// + /// + /// + /// + /// + /// + public void Edit(string fullName, string userName, string mobile, List roles, bool isActive) + { + FullName = fullName; + UserName = userName; + Mobile = mobile; + RoleUser = roles; + IsActive = isActive; + } + + /// + /// غیرفعال سازی + /// + public void DeActive() + { + IsActive = false; + } + + /// + /// فعال سازی + /// + public void ReActive() + { + IsActive = true; + } + + /// + /// افزودن توکن تازه‌سازی + /// + public void AddRefreshToken(string token, DateTime expiresAt, string? ipAddress = null, string? userAgent = null) + { + var refreshToken = new UserRefreshToken(Id, token, expiresAt, ipAddress, userAgent); + _refreshTokens.Add(refreshToken); + } + + /// + /// لغو توکن تازه‌سازی + /// + public void RevokeRefreshToken(string token) + { + var refreshToken = _refreshTokens.FirstOrDefault(x => x.Token == token); + if (refreshToken == null) + throw new InvalidOperationException("توکن یافت نشد"); + + refreshToken.Revoke(); + } + + /// + /// لغو تمام توکن‌های فعال + /// + public void RevokeAllRefreshTokens() + { + foreach (var token in _refreshTokens.Where(x => x.IsActive)) + { + token.Revoke(); + } + } + + /// + /// پاکسازی توکن‌های منقضی شده + /// + public void RemoveExpiredRefreshTokens() + { + _refreshTokens.RemoveAll(x => !x.IsActive); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs new file mode 100644 index 00000000..b04b3615 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs @@ -0,0 +1,90 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.UserAgg.Entities; + +/// +/// توکن تازه‌سازی برای احراز هویت +/// +public class UserRefreshToken : EntityBase +{ + /// + /// سازنده محافظت شده برای EF Core + /// + protected UserRefreshToken() + { + } + + /// + /// ایجاد توکن تازه‌سازی + /// + public UserRefreshToken(long userId, string token, DateTime expiresAt, string? ipAddress = null, string? userAgent = null) + { + UserId = userId; + Token = token; + ExpiresAt = expiresAt; + IpAddress = ipAddress; + UserAgent = userAgent; + } + + /// + /// شناسه کاربر + /// + public long UserId { get; private set; } + + /// + /// توکن تازه‌سازی + /// + public string Token { get; private set; } + + /// + /// تاریخ انقضا + /// + public DateTime ExpiresAt { get; private set; } + + /// + /// تاریخ لغو + /// + public DateTime? RevokedAt { get; private set; } + + /// + /// آی‌پی کاربر + /// + public string? IpAddress { get; private set; } + + /// + /// User Agent مرورگر + /// + public string? UserAgent { get; private set; } + + /// + /// آیا منقضی شده؟ + /// + public bool IsExpired => DateTime.Now >= ExpiresAt; + + /// + /// آیا لغو شده؟ + /// + public bool IsRevoked => RevokedAt.HasValue; + + /// + /// آیا فعال است؟ + /// + public bool IsActive => !IsRevoked && !IsExpired; + + /// + /// لغو توکن + /// + public void Revoke() + { + if (IsRevoked) + throw new InvalidOperationException("توکن قبلاً لغو شده است"); + + RevokedAt = DateTime.Now; + } + + /// + /// کاربر صاحب توکن + /// + public User User { get; private set; } +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs new file mode 100644 index 00000000..e02abfc9 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs @@ -0,0 +1 @@ + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs new file mode 100644 index 00000000..83b95f05 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs @@ -0,0 +1,47 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + + +namespace GozareshgirProgramManager.Domain.UserAgg.Events; + +public record UserCreatedEvent(long UserId, string FirstName, string LastName, string Email) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserPersonalInfoUpdatedEvent(long UserId, string OldFirstName, string OldLastName, string NewFirstName, string NewLastName) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserEmailUpdatedEvent(long UserId, string OldEmail, string NewEmail) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserWorkInfoUpdatedEvent(long UserId, string? Department, string? Position) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + + + + + + + + +public record UserDeactivatedEvent(long UserId, string? Reason) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserActivatedEvent(long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserLoggedInEvent(long UserId, DateTime LoginTime) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs new file mode 100644 index 00000000..62146e68 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs @@ -0,0 +1,9 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.UserAgg.Repositories; + +public interface IUserRefreshTokenRepository : IRepository +{ + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs new file mode 100644 index 00000000..5ce68190 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs @@ -0,0 +1,32 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.UserAgg.Repositories; + +public interface IUserRepository: IRepository +{ + Task GetByIdAsync(long id); + + /// + /// یافتن کاربر با آی دی اکانت گزارشگیر او + /// + /// + /// + Task GetByGozareshgirAccountId(long accountId); + Task GetByEmailAsync(string email); + Task GetByMobileAsync(string mobile); + Task> GetAllAsync(); + Task> GetActiveUsersAsync(); + + Task AddAsync(User user); + void Update(User user); + void Delete(User user); + Task ExistsAsync(long id); + Task UsernameExistsAsync(string username); + Task EmailExistsAsync(string email); + Task MobileExistsAsync(string mobile); + Task GetUserWithRolesByIdAsync(long userId, CancellationToken cancellationToken); +} + + + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/EntityBase.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/EntityBase.cs new file mode 100644 index 00000000..1710c77b --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/EntityBase.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace GozareshgirProgramManager.Domain._Common; + +public abstract class EntityBase +{ + public EntityBase() + { + if (typeof(TId) == typeof(Guid)) + { + Id = (TId)(object)Guid.NewGuid(); + } + CreationDate = DateTime.Now; + } + public TId Id { get; protected set; } + public DateTime CreationDate { get; protected set; } + + private readonly List _domainEvents = new(); + [NotMapped] + public IReadOnlyCollection DomainEvents => _domainEvents.AsReadOnly(); + protected void AddDomainEvent(IDomainEvent domainEvent) => _domainEvents.Add(domainEvent); + public void ClearDomainEvents() => _domainEvents.Clear(); + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/BadRequestException.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/BadRequestException.cs new file mode 100644 index 00000000..c33adfa0 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/BadRequestException.cs @@ -0,0 +1,24 @@ +namespace GozareshgirProgramManager.Domain._Common.Exceptions; + +public class BadRequestException:Exception +{ + public BadRequestException(string message):base(message) + { + + } + + public BadRequestException(string message, string details) : base(message) + { + Details = details; + } + + public BadRequestException(string message, Dictionary extra) : + base(message) + { + Extra = extra; + } + + public string Details { get; } + public Dictionary Extra { get; set; } + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/NotFoundException.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/NotFoundException.cs new file mode 100644 index 00000000..3b0f1796 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/NotFoundException.cs @@ -0,0 +1,13 @@ +namespace GozareshgirProgramManager.Domain._Common.Exceptions; + +public class NotFoundException:Exception +{ + public NotFoundException(string message) : base(message) + { + } + + public NotFoundException(string name, object key) : base($"Entity \"{name}\" ({key}) was not found.") + { + } + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/UnAuthorizedException.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/UnAuthorizedException.cs new file mode 100644 index 00000000..67f0befb --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Exceptions/UnAuthorizedException.cs @@ -0,0 +1,8 @@ +namespace GozareshgirProgramManager.Domain._Common.Exceptions; + +public class UnAuthorizedException:Exception +{ + public UnAuthorizedException(string message) : base(message) + { + } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IAggregateRoot.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IAggregateRoot.cs new file mode 100644 index 00000000..b11ee26d --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IAggregateRoot.cs @@ -0,0 +1,8 @@ +namespace GozareshgirProgramManager.Domain._Common; + +/// +/// Marker interface for Aggregate Roots +/// +public interface IAggregateRoot +{ +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IDomainEvent.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IDomainEvent.cs new file mode 100644 index 00000000..6ab51876 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IDomainEvent.cs @@ -0,0 +1,6 @@ +namespace GozareshgirProgramManager.Domain._Common; + +public interface IDomainEvent +{ + DateTime OccurredOn { get; } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IRepository.cs new file mode 100644 index 00000000..cd8a9dcc --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IRepository.cs @@ -0,0 +1,17 @@ +using System.Linq.Expressions; + +namespace GozareshgirProgramManager.Domain._Common; + +public interface IRepository where T:class +{ + T Get(TKey id); + Task GetByIdAsync(TKey id); + List Get(); + IQueryable GetQueryable(); + void Create(T entity); + Task CreateAsync(T entity); + bool ExistsIgnoreQueryFilter(Expression> expression); + bool Exists(Expression> expression); + //void SaveChanges(); + //Task SaveChangesAsync(); +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IUnitOfWork.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IUnitOfWork.cs new file mode 100644 index 00000000..1ecce3ef --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/IUnitOfWork.cs @@ -0,0 +1,9 @@ + namespace GozareshgirProgramManager.Domain._Common; + +/// +/// Unit of Work pattern interface +/// +public interface IUnitOfWork +{ + Task SaveChangesAsync(CancellationToken cancellationToken = default); +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs new file mode 100644 index 00000000..0f1ed2da --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/Tools.cs @@ -0,0 +1,2089 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using PersianTools.Core; + + +namespace GozareshgirProgramManager.Domain._Common; + +public static class Tools +{ + + public static string[] MonthNames = + {"فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند"}; + + public static string[] DayNames = { "شنبه", "یکشنبه", "دو شنبه", "سه شنبه", "چهار شنبه", "پنج شنبه", "جمعه" }; + public static string[] DayNamesG = { "یکشنبه", "دو شنبه", "سه شنبه", "چهار شنبه", "پنج شنبه", "جمعه", "شنبه" }; + + + public static bool IsMobileValid(this string mobileNo) + { + if (mobileNo.Length < 11) + return false; + return Regex.IsMatch(mobileNo, "^((09))(\\d{9})$"); + } + + /// + /// تاریخ شروع و تعداد ماه را میگیرد و تاریخ پایان قراردا را بر میگرداند + /// + /// + /// + /// + public static (DateTime endDateGr, string endDateFa) FindEndOfContract(string startDate, string monthPlus) + { + + int startYear = Convert.ToInt32(startDate.Substring(0, 4)); + int startMonth = Convert.ToInt32(startDate.Substring(5, 2)); + int startDay = Convert.ToInt32(startDate.Substring(8, 2)); + var start = new PersianDateTime(startYear, startMonth, startDay); + var end = (start.AddMonths(Convert.ToInt32(monthPlus))).AddDays(-1); + return ($"{end}".ToGeorgianDateTime(), $"{end}"); + + } + + /// + /// دریافت روزهای کارکرد پرسنل در لیست بیمه ماه مشخص شده + /// با کمک شروع بکار و ترک کار + /// + /// + /// + /// + /// + /// + /// + public static (int countWorkingDays, DateTime startWork, DateTime endWork, bool hasStartWorkInMonth, bool hasLeftWorkInMonth) GetEmployeeInsuranceWorkingDays(DateTime startWork, DateTime? leftWork, DateTime startDate, + DateTime endDate, long employeeId) + { + DateTime start = startDate; + DateTime end = endDate; + bool startWorkInMonth = false; + bool endWorkInMonth = false; + + //اگر شروع بکار پرسنل در ماه مشخص شده لیست بیمه بود + if (startWork >= startDate) + { + start = startWork; + startWorkInMonth = true; + } + + if (leftWork == null) + leftWork = DateTime.MinValue; + //اگر ترک کار پرسنل در ماه مشخص شده لیست بیمه بود + if (leftWork != DateTime.MinValue && leftWork.Value < endDate) + { + end = leftWork.Value; + endWorkInMonth = true; + } + + int countDays = (int)(end - start).TotalDays + 1; + + + //روزهای کارکرد پرسنل با آی دی های زیر دستی تعریف شد + switch (employeeId) + { + + //case 3812://ثابت- کسری حاجی پور + // countWorkingDays = 15; + // break; + case 40463://ثابت + countDays = 10; + break; + case 40469://ثابت + countDays = 7; + break; + //case 9950://ثابت + // countDays = 15; + //break; + case 9640://ثابت + countDays = 15; + break; + case 40998://ثابت + countDays = 15; + break; + case 6219://ثابت + countDays = 15; + break; + //case 7897://ثابت + // countWorkingDays = 15; + } + + + return (countDays, start, end, startWorkInMonth, endWorkInMonth); + } + /// + /// محاسبه سن + /// + /// + /// + /// + public static (int yearCount, int monthCount, int dayCount) GetAge(DateTime startDate, DateTime endDate) + { + + var startFa = startDate.ToFarsi(); + int startYear = Convert.ToInt32(startFa.Substring(0, 4)); + int startMonth = Convert.ToInt32(startFa.Substring(5, 2)); + int startDay = Convert.ToInt32(startFa.Substring(8, 2)); + var start = new PersianDateTime(startYear, startMonth, startDay); + + + var endFa = endDate.ToFarsi(); + int endYear = Convert.ToInt32(endFa.Substring(0, 4)); + int endMonth = Convert.ToInt32(endFa.Substring(5, 2)); + int endDay = Convert.ToInt32(endFa.Substring(8, 2)); + var end = new PersianDateTime(endYear, endMonth, endDay); + int months = 0; + int days = 0; + int years = 0; + + var firstYearCounter = start.AddYears(1); + //اگر سنش هنوز به یک سال نرسیده بود + if (firstYearCounter > end) + { + start = start.AddYears(-1); + + var endMonthCounter = new PersianDateTime(end.Year, end.Month, start.Day); + + for (var monthCounter = start; monthCounter <= end; monthCounter = monthCounter.AddMonths(1)) + { + if (monthCounter <= end) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("month : " + monthCounter); + months++; + } + + if (monthCounter.Month == end.Month) + { + var firstDayCounter = monthCounter.AddDays(1); + for (var dayCounter = firstDayCounter; dayCounter <= end; dayCounter = dayCounter.AddDays(1)) + { + if (dayCounter <= end) + { + days++; + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("day : " + dayCounter); + + } + + } + months = months > 0 ? months - 1 : 0; + break; + } + + + + } + + + } + else + { + for (var yearCouner = firstYearCounter; yearCouner <= end; yearCouner = yearCouner.AddYears(1)) + { + + if (yearCouner.Year <= end.Year) + { + years++; + Console.ForegroundColor = ConsoleColor.DarkMagenta; + Console.WriteLine("year : " + yearCouner); + } + + + if (yearCouner.Year == end.Year) + { + + var endMonthCounter = new PersianDateTime(end.Year, end.Month, (yearCouner.Day > end.Day ? end.Day : yearCouner.Day)); + + if (yearCouner.Day <= end.Day) + { + endMonthCounter = end; + + } + for (var monthCounter = yearCouner; monthCounter <= endMonthCounter; monthCounter = monthCounter.AddMonths(1)) + { + if (monthCounter < end) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("month : " + monthCounter); + months++; + } + + if (monthCounter.Month == end.Month) + { + var firstDayCounter = monthCounter.AddDays(1); + if (yearCouner.Day > end.Day) + { + + firstDayCounter = firstDayCounter.AddMonths(-1); + } + for (var dayCounter = firstDayCounter; dayCounter <= end; dayCounter = dayCounter.AddDays(1)) + { + if (dayCounter <= end) + { + days++; + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("day : " + dayCounter); + + } + + } + + months = months > 0 ? months - 1 : 0; + break; + } + + + } + + } + + } + } + + + Console.ResetColor(); + Console.WriteLine($"old: [{years} year] ، [{months} month] ، [{days} day]"); + return (years, months, days); + } + + public static string ToFarsi(this DateTime? date) + { + try + { + if (date != null) return date.Value.ToFarsi(); + } + catch (Exception) + { + return ""; + } + + return ""; + } + + public static string ToFarsi(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + return $"{pc.GetYear(date)}/{pc.GetMonth(date):00}/{pc.GetDayOfMonth(date):00}"; + } + public static string ToFarsiMonth(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + return $"{pc.GetMonth(date)}"; + } + + /// + /// دریافت عدد ماه شمسی + /// از تاریخ میلادی + /// + /// + /// + public static string GetShamsiMonthNumber(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + return $"{pc.GetMonth(date):00}"; + } + /// + /// دریافت ساتل شمسی + /// از تاریخ میلادی + /// + /// + /// + public static string GetShamsiYearNumber(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + return $"{pc.GetYear(date)}"; + } + /// + /// این متد تاریخ میلادی را گرفته و ماه 31 یا 30 روزه را تشخیص میدهد، ماه اسفند 30 روزه برمگیردد + /// + /// + /// + public static int CountMonthDays(this DateTime date) + { + if (date == new DateTime()) return 0; + var pc = new PersianCalendar(); + + return pc.GetMonth(date) switch + { + 1 => 31, + 2 => 31, + 3 => 31, + 4 => 31, + 5 => 31, + 6 => 31, + + 7 => 30, + 8 => 30, + 9 => 30, + 10 => 30, + 11 => 30, + 12 => 30, + _ => 0, + + }; + } + + public static string ToFarsiYear2(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + var year = pc.GetYear(date).ToString(); + string y1 = string.Empty; + string y2 = string.Empty; + string sum = string.Empty; + for (int i = 0; i < year.Length; i++) + { + + if (year[i] == 2) + { + y1 += year[i]; + } + + if (year[i] == 3) + { + y2 += year[i]; + } + + } + + sum = y1 + y2; + return sum; + } + public static string ToFarsiYear(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + + return $"{pc.GetYear(date)}"; + } + public static string ToDiscountFormat(this DateTime date) + { + if (date == new DateTime()) return ""; + return $"{date.Year}/{date.Month}/{date.Day}"; + } + + public static string GetTime(this DateTime date) + { + return $"_{date.Hour:00}_{date.Minute:00}_{date.Second:00}"; + } + + public static string ToFarsiFull(this DateTime date) + { + var pc = new PersianCalendar(); + return + $"{pc.GetYear(date)}/{pc.GetMonth(date):00}/{pc.GetDayOfMonth(date):00} {date.Hour:00}:{date.Minute:00}:{date.Second:00}"; + } + + private static readonly string[] Pn = { "۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹" }; + private static readonly string[] En = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + public static string ToEnglishNumber(this string strNum) + { + var cash = strNum; + for (var i = 0; i < 10; i++) + cash = cash.Replace(Pn[i], En[i]); + return cash; + } + + public static string ToPersianNumber(this int intNum) + { + var chash = intNum.ToString(); + for (var i = 0; i < 10; i++) + chash = chash.Replace(En[i], Pn[i]); + return chash; + } + + public static DateTime? FromFarsiDate(this string InDate) + { + if (string.IsNullOrEmpty(InDate)) + return null; + + var spited = InDate.Split('/'); + if (spited.Length < 3) + return null; + + if (!int.TryParse(spited[0].ToEnglishNumber(), out var year)) + return null; + + if (!int.TryParse(spited[1].ToEnglishNumber(), out var month)) + return null; + + if (!int.TryParse(spited[2].ToEnglishNumber(), out var day)) + return null; + var c = new PersianCalendar(); + return c.ToDateTime(year, month, day, 0, 0, 0, 0); + } + + + public static DateTime ToGeorgianDateTime(this string persianDate) + { + try + { + persianDate = persianDate.ToEnglishNumber(); + var year = Convert.ToInt32(persianDate.Substring(0, 4)); + var month = Convert.ToInt32(persianDate.Substring(5, 2)); + var day = Convert.ToInt32(persianDate.Substring(8, 2)); + + return new DateTime(year, month, day, new PersianCalendar()); + + + } + catch (Exception e) + { + return new DateTime(3000, 12, 20, new PersianCalendar()); + } + + } + + public static DateTime ToGeorgian(this string persianDate) + { + persianDate = persianDate.ToEnglishNumber(); + var year = Convert.ToInt32(persianDate.Substring(0, 4)); + var month = 01; + var day = 01; + return new DateTime(year, month, day, new PersianCalendar()); + } + public static string ToMoney(this double myMoney) + { + + return myMoney.ToString("N0", CultureInfo.CreateSpecificCulture("fa-ir")); + } + public static string ToMoneyNullable(this double? myMoney) + { + + return myMoney?.ToString("N0", CultureInfo.CreateSpecificCulture("fa-ir")); + } + public static string ToDoubleMoney(this string myMoney) + { + string bb = string.Empty; + + for (int x = 0; x < myMoney.Length; x++) + { + if (char.IsDigit(myMoney[x])) + bb += myMoney[x]; + } + + if (bb.Length > 0) + { + return bb; + } + else + { + return "0"; + } + + + + } + public static double MoneyToDouble(this string myMoney) + { + string bb = string.Empty; + bool isNegative = false; + + try + { + if (!string.IsNullOrWhiteSpace(myMoney)) + { + for (int x = 0; x < myMoney.Length; x++) + { + if (char.IsDigit(myMoney[x])) + { + bb += myMoney[x]; + } + else if (myMoney[x] == '-' && bb.Length == 0) + { + // اگر علامت منفی قبل از اولین عدد آمد، در نظر بگیر + isNegative = true; + } + } + + if (bb.Length > 0) + { + double res = double.Parse(bb); + return isNegative ? -res : res; + } + else + { + return 0; + } + } + else + { + return 0; + } + + } + catch (Exception) + { + + return 0; + } + } + public static string ToFileName(this DateTime date) + { + return $"{date.Year:0000}-{date.Month:00}-{date.Day:00}-{date.Hour:00}-{date.Minute:00}-{date.Second:00}"; + } + + public static string FindeEndOfMonth(this string date) + { + string y2 = string.Empty; + var year = Convert.ToInt32(date.Substring(0, 4)); + var month = Convert.ToInt32(date.Substring(5, 2)); + var YearD = date.Substring(0, 4); + var MonthD = date.Substring(5, 2); + if (month <= 6) + { + y2 = $"{YearD}/{MonthD}/31"; + } + else if (month > 6 && month < 12) + { + y2 = $"{YearD}/{MonthD}/30"; + } + else if (month == 12) + { + switch (year) + { + case 1346: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1350: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1354: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1358: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1362: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1366: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1370: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1375: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1379: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1383: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1387: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1391: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1395: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1399: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1403: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1408: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1412: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1416: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1420: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1424: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1428: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1432: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1436: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1441: + y2 = $"{YearD}/{MonthD}/30"; + break; + case 1445: + y2 = $"{YearD}/{MonthD}/30"; + break; + + default: + y2 = $"{YearD}/{MonthD}/29"; + break; + + } + } + + return y2; + } + + + /// + /// تعداد روزهای سال را برمیگرداند + /// اگر کبیسهد بود سال 366 روزه برمیگرداند + /// اگر کبیسهد نبود سال 365 روزه برمیگرداند + /// + /// + /// + public static int YearTotalDays(this string date) + { + int y2 = 366; + var year = Convert.ToInt32(date.Substring(0, 4)); + + + switch (year) + { + case 1346: + y2 = 367; + break; + case 1350: + y2 = 367; + break; + case 1354: + y2 = 367; + break; + case 1358: + y2 = 367; + break; + case 1362: + y2 = 367; + break; + case 1366: + y2 = 367; + break; + case 1370: + y2 = 367; + break; + case 1375: + y2 = 367; + break; + case 1379: + y2 = 367; + break; + case 1383: + y2 = 367; + break; + case 1387: + y2 = 367; + break; + case 1391: + y2 = 367; + break; + case 1395: + y2 = 367; + break; + case 1399: + y2 = 367; + break; + case 1403: + y2 = 367; + break; + case 1408: + y2 = 367; + break; + case 1412: + y2 = 367; + break; + case 1416: + y2 = 367; + break; + case 1420: + y2 = 367; + break; + case 1424: + y2 = 367; + break; + case 1428: + y2 = 367; + break; + case 1432: + y2 = 367; + break; + case 1436: + y2 = 367; + break; + case 1441: + y2 = 367; + break; + case 1445: + y2 = 367; + break; + + default: + y2 = 366; + break; + + } + + + return y2; + } + + public static int BetweenDateGeorgianToDay(DateTime dateStart, DateTime? dateEnd) + { + DateTime end = DateTime.Now; + if (dateEnd != null) + { + end = (DateTime)dateEnd; + } + return (int)(end - dateStart).TotalDays; + } + + public static string GetMonthByNumber(this string value) + { + + if (value == "01") + { + return "فروردین"; + } + else if (value == "02") + { + return "اردیبهشت"; + } + else if (value == "03") + { + return "خرداد"; + } + else if (value == "04") + { + return "تیر"; + } + else if (value == "05") + { + return "مرداد"; + } + else if (value == "06") + { + return "شهریور"; + } + else if (value == "07") + { + return "مهر"; + } + else if (value == "08") + { + return "آبان"; + } + else if (value == "09") + { + return "آذر"; + } + else if (value == "10") + { + return "دی"; + } + else if (value == "11") + { + return "بهمن"; + } + else + return "اسفند"; + + } + + public static string RestTimeSplit(this string restTime) + { + string result = string.Empty; + + if (restTime?.Length >= 2) + { + result = restTime.Substring(0, 2); + if (result == "00") + result = "0"; + } + else + { + result = "0"; + } + + + return result; + } + + public static string NationalCodeValid(this string nationalCode) + { + try + { + char[] chArray = nationalCode.ToCharArray(); + int[] numArray = new int[chArray.Length]; + var cunt = chArray.Length; + for (int i = 0; i < chArray.Length; i++) + { + numArray[i] = (int)char.GetNumericValue(chArray[i]); + } + + int num2 = numArray[9]; + switch (nationalCode) + { + case "0000000000": + case "1111111111": + case "2222222222": + case "3333333333": + case "4444444444": + case "5555555555": + case "6666666666": + case "7777777777": + case "8888888888": + case "9999999999": + + return "incorrect"; + } + + int num3 = + ((((((((numArray[0] * 10) + (numArray[1] * 9)) + (numArray[2] * 8)) + (numArray[3] * 7)) + + (numArray[4] * 6)) + (numArray[5] * 5)) + (numArray[6] * 4)) + (numArray[7] * 3)) + + (numArray[8] * 2); + int num4 = num3 - ((num3 / 11) * 11); + if ((((num4 == 0) && (num2 == num4)) || ((num4 == 1) && (num2 == 1))) || + ((num4 > 1) && (num2 == Math.Abs((int)(num4 - 11)))) && cunt <= 10) + { + return "valid"; + } + else + { + return "invalid"; + } + } + catch (Exception) + { + return "lessThan10"; + + } + + } + public static string RestTimeMinSplit(this string restTime) + { + string result = string.Empty; + + if (restTime?.Length > 2) + { + result = restTime.Substring(3, 2); + if (result == "00") + result = "0"; + + } + else + { + result = "0"; + } + + + return result; + } + + public static List ExtractNumbers(this string input) + { + List numbers = new List(); + string pattern = @"\d+"; // Matches one or more digits + + MatchCollection matches = Regex.Matches(input, pattern); + + foreach (Match match in matches) + { + if (long.TryParse(match.Value, out long number)) + { + numbers.Add(number); + } + } + + return numbers; + } + public static int ExtractIntNumbers(this string input) + { + int numbers = 0; + string num = ""; + string pattern = @"\d+"; // Matches one or more digits + + MatchCollection matches = Regex.Matches(input, pattern); + + foreach (Match match in matches) + { + if (int.TryParse(match.Value, out int number)) + { + num += $"{number}"; + } + } + + try + { + numbers = Convert.ToInt32(num); + } + catch (Exception e) + { + return 0; + } + + return numbers; + } + public static string ToFarsiMonthByNumber(this string value) + { + if (value == "") return ""; + string result = ""; + switch (value) + { + case "1": + case "01": + result = "فروردین"; + break; + case "2": + case "02": + result = "اردیبهشت"; + break; + case "3": + case "03": + result = "خرداد"; + break; + case "4": + case "04": + result = "تیر"; + break; + case "5": + case "05": + result = "مرداد"; + break; + case "6": + case "06": + result = "شهریور"; + break; + case "7": + case "07": + result = "مهر"; + break; + case "8": + case "08": + result = "آبان"; + break; + case "9": + case "09": + result = "آذر"; + break; + case "10": + result = "دی"; + break; + case "11": + result = "بهمن"; + break; + case "12": + result = "اسفند"; + break; + default: + result = ""; + break; + } + + return result; + } + public static string ToFarsiMonthByIntNumber(this int value) + { + if (value == 0) return ""; + string result = ""; + switch (value) + { + case 1: + result = "فروردین"; + break; + case 2: + result = "اردیبهشت"; + break; + case 3: + result = "خرداد"; + break; + case 4: + result = "تیر"; + break; + case 5: + result = "مرداد"; + break; + case 6: + result = "شهریور"; + break; + case 7: + result = "مهر"; + break; + case 8: + result = "آبان"; + break; + case 9: + result = "آذر"; + break; + case 10: + result = "دی"; + break; + case 11: + result = "بهمن"; + break; + case 12: + result = "اسفند"; + break; + default: + result = ""; + break; + } + + return result; + } + + #region Vafa + public static string ToFarsiWithoutYear(this DateTime date) + { + if (date == new DateTime()) return ""; + var pc = new PersianCalendar(); + return $"{pc.GetMonth(date):00}/{pc.GetDayOfMonth(date):00}"; + } + public static int ToMonthByStringValue(this string value) + { + if (value == "") return 0; + int result = 0; + switch (value) + { + case "فروردین": + result = 1; + break; + case "اردیبهشت": + result = 2; + break; + case "خرداد": + result = 3; + break; + case "تیر": + result = 4; + break; + case "مرداد": + result = 5; + break; + case "شهریور": + result = 6; + break; + case "مهر": + result = 7; + break; + case "آبان": + result = 8; + break; + case "آذر": + result = 9; + break; + case "دی": + result = 10; + break; + case "بهمن": + result = 11; + break; + case "اسفند": + result = 12; + break; + default: + result = 0; + break; + } + + return result; + } + + public static string ColorPercent(this int value) + { + string color = ""; + + var redDark = "#B91C1C"; + var redLight = "#EF4444"; + + var orangeDark = "#F59E0B"; + var orangeLight = "#FBBF24"; + + var limeDark = "#81CB0F"; + var limeLight = "#A3E635"; + + switch (value) + { + case <= 16: + color = redDark; + break; + case <= 33: + color = redLight; + break; + case <= 49: + color = orangeDark; + break; + case <= 66: + color = orangeLight; + break; + case <= 83: + color = limeLight; + break; + case <= 100: + color = limeDark; + break; + default: + color = ""; + break; + } + return color; + } + + public static double RoundMoney(this double value) + { + var valueLength = (((int)value).ToString()).Length; + var checkZero = (((int)value).ToString()).Substring(1, 1); + int digitValue = 0; + int digitLentgh = 0; + int d = 0; + if ((int)value == 10499677) + { + Console.WriteLine(90); + } + switch (valueLength) + { + case 6: + digitValue = 5000; + digitLentgh = 100000; + d = 1000; + break; + case 7: + digitValue = 50000; + digitLentgh = 1000000; + d = 10000; + break; + case 8: + digitValue = checkZero == "0" ? 50000 : 500000; + digitLentgh = checkZero == "0" ? 100000 : 10000000; + d = 100000; + break; + + } + + int result = 0; + int rightDigits = (int)(value % digitLentgh); + + + //if (rightDigits < digitValue) + //{ + // result = (int)(value / d) * d; + //} + //else + //{ + // result = (int)(value / d + 1) * d; + //} + result = (int)(value / d + 1) * d; + return result; + } + + public static string ToMoneyToman(this double myMoney) + { + myMoney = myMoney / 10; + return myMoney.ToString("N0", CultureInfo.CreateSpecificCulture("fa-ir")); + } + + public static PersianDateTime ToPersianDateTime(this DateTime date) + { + var persianDate = date.ToFarsi(); + var year = Convert.ToInt32(persianDate.Substring(0, 4)); + var month = Convert.ToInt32(persianDate.Substring(5, 2)); + var day = Convert.ToInt32(persianDate.Substring(8, 2)); + return new PersianDateTime(year, month, day); + } + + //public static string ResizeImage(string imagePath, int width, int height) + //{ + // using (var srcImage = Image.FromFile(imagePath)) + // { + // var newImage = new Bitmap(width, height); + // using (var graphics = Graphics.FromImage(newImage)) + // { + // graphics.CompositingQuality = CompositingQuality.HighSpeed; + // graphics.InterpolationMode = InterpolationMode.Bicubic; + // graphics.SmoothingMode = SmoothingMode.HighSpeed; + // graphics.DrawImage(srcImage, 0, 0, width, height); + // } + + // using (var memoryStream = new MemoryStream()) + // { + // newImage.Save(memoryStream, ImageFormat.Jpeg); + // return Convert.ToBase64String(memoryStream.ToArray()); + // } + // } + //} + + public static PersianDateTime ToFirstDayOfNextMonth(this DateTime date) + { + var pc = new PersianCalendar(); + var year = pc.GetYear(date); + var month = pc.GetMonth(date); + + if (month == 12) + { + year += 1; + month = 1; + } + else + { + month += 1; + } + + return new PersianDateTime(year, month, 1); + + } + #endregion + + #region Safa + + public static string GetContentTypeImage(string extension) + { + if (!extension.StartsWith(".")) + { + extension = "." + extension; + } + + return extension.ToLower() switch + { + ".jpg" => "image/jpeg", + ".jpeg" => "image/jpeg", + ".png" => "image/png", + ".gif" => "image/gif", + ".bmp" => "image/bmp", + ".svg" => "image/svg+xml", + ".ico" => "image/x-icon", + _ => "", + }; + } + + public static string GetContentType(string extension) + { + + // Ensure the extension starts with a dot + if (!extension.StartsWith(".")) + { + extension = "." + extension; + } + + // Use switch expression to return the appropriate content type + return extension.ToLower() switch + { + ".txt" => "text/plain", + ".htm" => "text/html", + ".html" => "text/html", + ".css" => "text/css", + ".js" => "application/javascript", + ".json" => "application/json", + ".xml" => "application/xml", + ".pdf" => "application/pdf", + ".zip" => "application/zip", + ".rar" => "application/x-rar-compressed", + ".tar" => "application/x-tar", + ".mp3" => "audio/mpeg", + ".wav" => "audio/wav", + ".mp4" => "video/mp4", + ".avi" => "video/x-msvideo", + ".doc" => "application/msword", + ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ".xls" => "application/vnd.ms-excel", + ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ".ppt" => "application/vnd.ms-powerpoint", + ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", + _ => "application/octet-stream", + }; + } + + #endregion + public static string ConvertToEnglish(this string value) + { + if (string.IsNullOrEmpty(value)) + return value; + + string EnglishNumbers = ""; + for (int i = 0; i < value.Length; i++) + { + if (Char.IsDigit(value[i])) + { + EnglishNumbers += char.GetNumericValue(value, i); + } + else + { + EnglishNumbers += value[i].ToString(); + } + } + return EnglishNumbers; + } + + public static DateTime ExtractTimeFromDbbackup(this string value) + { + DateTime dateTime = new DateTime(); + var parts = value.Split('-'); + if (parts.Length >= 4 && parts[1].Length == 4 && parts[2].Length == 2 && parts[3].Length == 2 && parts[4].Length == 2 && parts[5].Length >= 2) + { + var part5 = parts[5].Substring(0, 2); + + + try + { + PersianCalendar pc = new PersianCalendar(); + dateTime = pc.ToDateTime(int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]), int.Parse(parts[4]), int.Parse(part5), 0, 0, 0); + + } + catch (Exception e) + { + + + } + + } + //var year = value.Substring(10, 4); + //var month = value.Substring(15, 2); + //var day = value.Substring(18, 2); + //var persianDate = year + "/" + month + "/" + day; + //var georgianDate = persianDate.ToGeorgianDateTime(); + //var hourString = value.Substring(21, 2); + //int hour = hourString.ExtractIntNumbers(); + + //var result = new DateTime(georgianDate.Year, georgianDate.Month, georgianDate.Day, hour, 1, 1); + return dateTime; + } + + public static DateTime ExtractTimeFromInsurancebackup(this string value) + { + var year = value.Substring(14, 4); + var month = value.Substring(19, 2); + var day = value.Substring(22, 2); + var persianDate = year + "/" + month + "/" + day; + var georgianDate = persianDate.ToGeorgianDateTime(); + var hourString = value.Substring(25, 2); + int hour = hourString.ExtractIntNumbers(); + + var result = new DateTime(georgianDate.Year, georgianDate.Month, georgianDate.Day, hour, 1, 1); + return result; + } + + public static string FindeEndOfYear(this string date) + { + var year = Convert.ToInt32(date.Substring(0, 4)); + var month = Convert.ToInt32(date.Substring(5, 2)); + var day = Convert.ToInt32(date.Substring(8, 2)); + + var start = new PersianDateTime(year, month, day); + var startAddYear = start.AddMonths(11); + var monthStr = $"{startAddYear.Month}"; + if (monthStr.Length < 2) + monthStr = $"0{monthStr}"; + var lastMonth = $"{startAddYear.Year}/{monthStr}/01"; + var end = lastMonth.FindeEndOfMonth(); + return end; + + } + + public static string CalculateLeaveHoursAndDays(string paidLeaveType, string leaveHourses) + { + string leaveHoursResult = ""; + if (paidLeaveType == "ساعتی") + { + var leaveH = TimeSpan.Parse(leaveHourses); + var hours = (int)leaveH.TotalHours; + var minutes = (int)leaveH.TotalMinutes % 60; + if (hours > 0 && minutes > 0) + { + leaveHoursResult = hours + " ساعت و " + minutes + " دقیقه"; + } + else if (hours > 0 && minutes == 0) + { + leaveHoursResult = hours + " ساعت"; + } + else if (hours == 0 && minutes > 0) + { + leaveHoursResult = minutes + " دقیقه"; + } + } + else + { + leaveHoursResult = leaveHourses + " روز"; + } + + return leaveHoursResult; + } + + public static string ComputationOfHoursAndMinutes(double data) + { + int hours = (int)Math.Floor(data); + double remaining = data - hours; + int minutes = (int)(remaining * 60); + + string result; + if (minutes == 0) + { + result = hours + " س"; + } + else + { + result = hours + " س " + minutes + " د"; + } + + return result; + } + + public static bool CheckValidHm(string input) + { + if (string.IsNullOrWhiteSpace(input)) + return true; + string pattern = @"^([2][0-3]|[1][0-9]|[0-9]|[0][0-9])([:][0-5][0-9])$"; + + var match = Regex.Match(input, pattern); + if (!match.Success) + return false; + return true; + } + + /// + /// چک میکند که در دو شیفت استاتیک تداخل زمانی وجود دارد یا خیر + /// چک میکند که آیا ساعات وارد شده ولید هستند یا خیر + /// + /// + /// + /// + /// + /// + public static bool InterferenceTime(string start1, string end1, string start2, string end2) + { + if (!CheckValidHm(start1)) + return true; + + if (!CheckValidHm(end1)) + return true; + + if (!CheckValidHm(start2)) + return true; + + if (!CheckValidHm(end2)) + return true; + + //اگه دو شیفت نبود + if (string.IsNullOrWhiteSpace(start1) || string.IsNullOrWhiteSpace(start2)) + return false; + + + try + { + var start1Gr = Convert.ToDateTime(start1); + var end1Gr = Convert.ToDateTime(end1); + + if (end1Gr < start1Gr) + end1Gr = end1Gr.AddDays(1); + + var start2Gr = Convert.ToDateTime(start2); + var end2Gr = Convert.ToDateTime(end2); + + + start2Gr = new DateTime(end1Gr.Year, end1Gr.Month, end1Gr.Day, start2Gr.Hour, start2Gr.Minute, + start2Gr.Second); + + + end2Gr = new DateTime(end1Gr.Year, end1Gr.Month, end1Gr.Day, end2Gr.Hour, end2Gr.Minute, + end2Gr.Second); + if (end2Gr < start2Gr) + end2Gr = end2Gr.AddDays(1); + + var diff = (end1Gr - start1Gr).Add((end2Gr - start2Gr)); + if (diff > new TimeSpan(24,0,0)) + return true; + + if (start2Gr <= end1Gr) + return true; + + return false; + } + catch (Exception) + { + + return true; + } + + + } + public static DateTime FindFirstDayOfMonthGr(this DateTime date) + { + var pc = new PersianCalendar(); + return ($"{pc.GetYear(date)}/{pc.GetMonth(date):00}/01").ToGeorgianDateTime(); + } + #region Mahan + + + public static bool IsvalidIban(this string iban) + { + return Regex.IsMatch(iban, @"^IR[0-9]{24}$"); + } + public static bool IsValidCardNumber(this string cardNumber) + { + return Regex.IsMatch(cardNumber, @"^[0-9]{16}$"); + } + /// + /// این متد حروف عربی را به فارسی در میاورد. مثال: علي را به علی تبدیل میکند + /// + /// + /// + public static string ToPersian(this string text) + { + var res = ""; + foreach (var @char in text) + { + + if (@char == char.Parse("ي")) + res += "ی"; + else if (@char == char.Parse("ك")) + res += "ک"; + else + res += @char; + } + return res; + } + + /// + /// این متد سعی میکند رشته را به تاریخ برگرداند و یک بول و دیت تایم برمیگرداند + /// + /// تاریخ شمسی + /// تاریخ + /// + public static bool TryToGeorgianDateTime(this string persianDate, out DateTime georgianDateTime) + { + if (string.IsNullOrWhiteSpace(persianDate)) + { + georgianDateTime = new DateTime(3000, 12, 20, new PersianCalendar()); + return false; + } + persianDate = persianDate.ToEnglishNumber(); + try + { + var year = Convert.ToInt32(persianDate.Substring(0, 4)); + var month = Convert.ToInt32(persianDate.Substring(5, 2)); + var day = Convert.ToInt32(persianDate.Substring(8, 2)); + + georgianDateTime = new DateTime(year, month, day, new PersianCalendar()); + return true; + } + catch + { + georgianDateTime = new DateTime(3000, 12, 20, new PersianCalendar()); + return false; + } + } + + public static string FindFirstDayOfMonth(this DateTime date) + { + var pc = new PersianCalendar(); + return $"{pc.GetYear(date)}/{pc.GetMonth(date):00}/01"; + } + public static string ToFarsiDuration(this string date) + { + var today = DateTime.Now.ToFarsi(); + var year = Convert.ToInt32(today.Substring(0, 4)); + var month = Convert.ToInt32(today.Substring(5, 2)); + var day = Convert.ToInt32(today.Substring(8, 2)); + var todayPersianDate = new PersianDateTime(year, month, day); + + var planYear = Convert.ToInt32(date.Substring(0, 4)); + var planMonth = Convert.ToInt32(date.Substring(5, 2)); + var planDay = Convert.ToInt32(date.Substring(8, 2)); + var planPersianDate = new PersianDateTime(planYear, planMonth, planDay); + + if (planPersianDate > todayPersianDate) + { + var countDay = 0; + var counMonth = 0; + var nextMonth = new PersianDateTime(todayPersianDate).AddMonths(1); + for (var start = todayPersianDate; start <= planPersianDate; start = start.AddDays(1)) + { + countDay++; + if (start == nextMonth) + { + counMonth++; + nextMonth = new PersianDateTime(start).AddMonths(1); + countDay = 0; + } + } + + if (counMonth > 0) + { + if (countDay == 0) + { + return $"{counMonth} ماه"; + } + return $"{counMonth}ماه و {countDay} روز"; + } + else + { + return $"{countDay}روز"; + } + } + else + { + return ""; + } + } + + public static string ToFarsiDuration2(this string date) + { + var persianCalendar = new System.Globalization.PersianCalendar(); + var today = DateTime.Now; + + // Convert today's Gregorian date to Persian date + var todayYear = persianCalendar.GetYear(today); + var todayMonth = persianCalendar.GetMonth(today); + var todayDay = persianCalendar.GetDayOfMonth(today); + + var todayPersianDate = new DateTime(todayYear, todayMonth, todayDay, persianCalendar); + + // Parse the target Persian date from the input string + var planYear = int.Parse(date.Substring(0, 4)); + var planMonth = int.Parse(date.Substring(5, 2)); + var planDay = int.Parse(date.Substring(8, 2)); + + var planPersianDate = new DateTime(planYear, planMonth, planDay, persianCalendar); + + if (planPersianDate > todayPersianDate) + { + // Calculate the exact difference in years, months, and days + int yearDifference = planYear - todayYear; + int monthDifference = planMonth - todayMonth; + int dayDifference = planDay - todayDay; + + if (dayDifference < 0) + { + monthDifference--; + dayDifference += persianCalendar.GetDaysInMonth(todayYear, todayMonth); + } + + if (monthDifference < 0) + { + yearDifference--; + monthDifference += 12; + } + + // Construct the duration string + var duration = ""; + if (yearDifference > 0) + { + duration += $"{yearDifference} سال "; + } + + if (monthDifference > 0) + { + duration += $"{monthDifference} ماه "; + } + + if (dayDifference > 0) + { + duration += $"{dayDifference} روز"; + } + + return duration.Trim(); + } + else + { + return ""; + } + } + //public static string SerializeToBson(object obj) + //{ + // using var memoryStream = new MemoryStream(); + // using (BsonDataWriter bsonWriter = new BsonDataWriter(memoryStream)) + // { + // JsonSerializer serializer = new JsonSerializer(); + // serializer.Serialize(bsonWriter, obj); + // } + // byte[] bsonData = memoryStream.ToArray(); + // return Convert.ToBase64String(bsonData); + //} + ////بیسان هایی که بصورت لیست بودند استخراج میشود + //public static List DeserializeFromBsonList(string base64Data) + //{ + // byte[] data = Convert.FromBase64String(base64Data); + + // using MemoryStream memoryStream = new MemoryStream(data); + // using BsonDataReader reader = new BsonDataReader(memoryStream); + // reader.ReadRootValueAsArray = true; + // JsonSerializer serializer = new JsonSerializer(); + // return serializer.Deserialize>(reader); + //} + ////بیسان هایی که بصورت تکی بودند استخراج میشود + //public static T DeserializeFromBson(string base64Data) + //{ + // byte[] bsonData = Convert.FromBase64String(base64Data); + // using MemoryStream memoryStream = new MemoryStream(bsonData); + // using BsonDataReader bsonReader = new BsonDataReader(memoryStream); + // JsonSerializer serializer = new JsonSerializer(); + // return serializer.Deserialize(bsonReader); + //} + + //public static TimeOnly CalculateOffset(ICollection shiftDetailsRegularShifts) + //{ + // if (!shiftDetailsRegularShifts.Any()) + // { + // return TimeOnly.MinValue; + // } + // var date = new DateOnly(); + // var firstStartShift = new DateTime(date, shiftDetailsRegularShifts.MinBy(x => x.Placement).StartTime); + // var lastEndShift = new DateTime(date, shiftDetailsRegularShifts.MaxBy(x => x.Placement).EndTime); + // if (lastEndShift > firstStartShift) + // firstStartShift = firstStartShift.AddDays(1); + // var offSet = (firstStartShift - lastEndShift).Divide(2); + // return TimeOnly.FromDateTime(lastEndShift.Add(offSet)); + //} + public static DateTime GetNextDayOfWeek(this DateTime date, DayOfWeek dayOfWeek) + { + int numberOfNextDayOfWeek = ((int)dayOfWeek - (int)date.DayOfWeek + 7) % 7; + return date.AddDays(numberOfNextDayOfWeek == 0 ? 7 : numberOfNextDayOfWeek); + } + + + //این متد آخر همان روز را به صورت دیت تایم برمیگرداند + public static DateTime ToEndDayOfGeorgianDateTime(this string persianDate) + { + persianDate = persianDate.ToEnglishNumber(); + try + { + var year = Convert.ToInt32(persianDate.Substring(0, 4)); + var month = Convert.ToInt32(persianDate.Substring(5, 2)); + var day = Convert.ToInt32(persianDate.Substring(8, 2)); + + var res = new DateTime(year, month, day, new PersianCalendar()); + res = res.AddHours(23); + res = res.AddMinutes(59); + res = res.AddSeconds(59); + + return res; + + } + catch (Exception e) + { + return new DateTime(3000, 12, 20, new PersianCalendar()); + } + + } + //تبدیل به تاریخ با ساعت + public static DateTime ToGeorgianDateWithTime(this string persianDate, string persianTime) + { + persianDate = persianDate.ToEnglishNumber(); + try + { + var year = Convert.ToInt32(persianDate.Substring(0, 4)); + var month = Convert.ToInt32(persianDate.Substring(5, 2)); + var day = Convert.ToInt32(persianDate.Substring(8, 2)); + + + + var hour = int.Parse(persianTime.Substring(0, 2)); + var minute = int.Parse(persianTime.Substring(3, 2)); + + var res = new DateTime(year, month, day, new PersianCalendar()); + res = res.AddHours(hour); + res = res.AddMinutes(minute); + return res; + + } + catch (Exception e) + { + return new DateTime(3000, 12, 20, new PersianCalendar()); + } + + } + + public static string DayOfWeeKToPersian(this DayOfWeek dayOfWeek) + { + return dayOfWeek switch + { + DayOfWeek.Friday => "جمعه", + DayOfWeek.Monday => "دوشنبه", + DayOfWeek.Saturday => "شنبه", + DayOfWeek.Sunday => "یکشنبه", + DayOfWeek.Thursday => "پنجشنبه", + DayOfWeek.Tuesday => "سه شنبه", + DayOfWeek.Wednesday => "چهارشنبه", + _ => "" + }; + } + + public static bool IsInvalidDateTime(this DateTime date) + { + return date == new DateTime(3000, 12, 20, new PersianCalendar()); + + } + + + + + + #endregion + + #region Pooya + /// + /// محاسبه روز های هر ماه شمسی + /// + /// تاریخ روزی از ماه + public static int CountPersianMonthDays(this DateTime date) + { + DateTime currentMonthDate, nextMonthDate; + currentMonthDate = date.FindFirstDayOfMonth().ToGeorgianDateTime(); + FindFirstDayOfNextMonth(date, out nextMonthDate); + + return ((int)(nextMonthDate.Date - currentMonthDate.Date).TotalDays); + } + + public static string FindFirstDayOfNextMonth(this DateTime date, out DateTime nextMonthDate) + { + var dateFa = date.ToFarsi(); + int year = Convert.ToInt32(dateFa.Substring(0, 4)); + int month = Convert.ToInt32(dateFa.Substring(5, 2)); + int nextMonth; + int nextMonthYear; + if (month == 12) + { + nextMonthYear = year + 1; + nextMonth = 1; + } + else + { + nextMonthYear = year; + nextMonth = month + 1; + } + nextMonthDate = new DateTime(nextMonthYear, nextMonth, 1, new PersianCalendar()); + return $"{nextMonthYear:0000}/{nextMonth:00}/01"; + } + + + /// + /// اضافه یا کم کردن ماه، توجه داشته باشید خروجی متد همیشه یکم ماه می باشد + /// + public static string AddMonthsFa(this DateTime date, int count, out DateTime result) + { + var dateFa = date.ToFarsi(); + int year = Convert.ToInt32(dateFa.Substring(0, 4)); + int month = Convert.ToInt32(dateFa.Substring(5, 2)); + + int newMonth; + int newYear; + + //add operation + if (count >= 0) + { + newYear = year; + while (month + count > 12) + { + newYear += 1; + count -= 12; + } + newMonth = month + count; + + } + + //subtract operation + else + { + newYear = year; + while (month + count < 1) + { + newYear -= 1; + count += 12; + } + newMonth = month + count; + } + result = new DateTime(newYear, newMonth, 1, new PersianCalendar()); + return $"{newYear:0000}/{newMonth:00}/01"; + + } + + + public static DateTime GetUndefinedDateTime() + { + return new DateTime(2121, 03, 21); + } + + public static bool IsDateUndefined(this DateTime date) + { + return date == new DateTime(2121, 03, 21); + } + public static string ToFarsiHoursAndMinutes(int hours, int minutes, string emptyValue = "") + { + + string message = emptyValue; + if (hours > 0 && minutes > 0) + { + + message = hours + " " + "ساعت و" + " " + minutes + " " + "دقیقه"; + } + else if (hours > 0 && minutes == 0) + { + + message = hours + " " + "ساعت "; + } + else if (hours == 0 && minutes > 0) + { + + message = minutes + " " + "دقیقه"; + } + + return message; + } + /// + /// تبدیل بازه زمانی اینتیجر به متن ساعت و دقسقه + /// + /// + /// + /// + public static string ConvertIntDurationToHoursAndMinutes(this int duration, string emptyValue = "") + { + var minutes = duration % 60; + var hours = duration / 60; + + string message = emptyValue; + if (hours > 0 && minutes > 0) + { + + message = hours + " " + "ساعت و" + " " + minutes + " " + "دقیقه"; + } + else if (hours > 0 && minutes == 0) + { + + message = hours + " " + "ساعت "; + } + else if (hours == 0 && minutes > 0) + { + + message = minutes + " " + "دقیقه"; + } + + return message; + } + + public static string ToFarsiHoursAndMinutes(this TimeSpan timeSpan, string emptyValue = "") + { + var hours = (int)timeSpan.TotalHours; + var minutes = timeSpan.Minutes; + string message = emptyValue; + if (hours > 0 && minutes > 0) + { + + message = hours + " " + "ساعت و" + " " + minutes + " " + "دقیقه"; + } + else if (hours > 0 && minutes == 0) + { + + message = hours + " " + "ساعت "; + } + else if (hours == 0 && minutes > 0) + { + + message = minutes + " " + "دقیقه"; + } + + return message; + } + public static string ToFarsiDaysAndHoursAndMinutes(this TimeSpan timeSpan, string emptyValue = "") + { + var hours = (int)timeSpan.TotalHours; + var minutes = timeSpan.Minutes; + var days = hours / 24; + hours = hours % 24; + string message = ""; + + if (days > 0) + message += days + " " + "روز"; + if (hours > 0) + if (message == "") + message += hours + " " + "ساعت"; + else + message += " و " + hours + " " + "ساعت"; + if (minutes > 0) + if (message == "") + message += minutes + " " + "دقیقه"; + else + message += " و " + minutes + " " + "دقیقه"; + + if (message == "") + message = emptyValue; + return message; + } + + public static bool ArePropertiesEqual(this T obj1, T obj2) + { + // If either object is null, they can't be equal + if (obj1 == null || obj2 == null) + return false; + + // Get the type of the objects + var type = typeof(T); + + // Iterate through each property + foreach (var property in type.GetProperties()) + { + // Get the values of the current property for both objects + var value1 = property.GetValue(obj1); + var value2 = property.GetValue(obj2); + + // If both values are null, they are considered equal + if (value1 == null && value2 == null) + continue; + + // If one value is null, but the other isn't, they are not equal + if (value1 == null || value2 == null) + return false; + + // If values are not equal, return false + if (!value1.Equals(value2)) + return false; + } + + // If all properties are equal, return true + return true; + } + + #endregion + + #region Davoodi + + //public static List GetDaysBetweenDateGeorgian(DateTime startDate, DateTime? endDate) + //{ + // var days = new List(); + + // if (endDate == null) + // endDate = DateTime.Now; + + // var persianStartDate = new MD.PersianDateTime.Standard.PersianDateTime(startDate); + // var persianEndDate = new MD.PersianDateTime.Standard.PersianDateTime(endDate); + + + // while (persianEndDate - persianStartDate >= TimeSpan.FromDays(0)) + // { + // days.Add(persianStartDate.ToShortDateString()); + // persianStartDate = persianStartDate.AddDays(1); + // } + + // return days; + //} + + public static int GetWorkingDaysDifference(DateTime? fromDate, DateTime? toDate) + { + //var workingDays = PersianDateExtensions.GetWorkingDays(new PersianDateTime(fromDate.ToFarsi()), new PersianDateTime(toDate.ToFarsi()), true); + var workingDays = PersianDateExtensions.GetWorkingDays((DateTime)fromDate, (DateTime)toDate, true); + + + if (fromDate > toDate) + workingDays *= -1; + + + return workingDays; + } + + + + #endregion +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/ValueObject.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/ValueObject.cs new file mode 100644 index 00000000..9a486daa --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/_Common/ValueObject.cs @@ -0,0 +1,38 @@ +namespace GozareshgirProgramManager.Domain._Common; + +public abstract class ValueObject +{ + protected abstract IEnumerable GetEqualityComponents(); + + public override bool Equals(object? obj) + { + if (obj == null || obj.GetType() != GetType()) + return false; + + var other = (ValueObject)obj; + return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); + } + + public override int GetHashCode() + { + return GetEqualityComponents() + .Select(x => x?.GetHashCode() ?? 0) + .Aggregate((x, y) => x ^ y); + } + + public static bool operator ==(ValueObject? left, ValueObject? right) + { + if (left is null && right is null) + return true; + + if (left is null || right is null) + return false; + + return left.Equals(right); + } + + public static bool operator !=(ValueObject? left, ValueObject? right) + { + return !(left == right); + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs new file mode 100644 index 00000000..a17403b0 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -0,0 +1,105 @@ + + + +using GozareshgirProgramManager.Application._Common.Behaviors; +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; + +namespace GozareshgirProgramManager.Infrastructure; + +public static class DependencyInjection +{ + public static IServiceCollection AddProgramManagerInfrastructure( + this IServiceCollection services, + IConfiguration configuration) + { + // DbContext + services.AddDbContext(options => + options.UseSqlServer( + configuration.GetConnectionString("ProgramManagerDb"), + b => b.MigrationsAssembly(typeof(ProgramManagerDbContext).Assembly.FullName))); + + // Register IAppDbContext + services.AddScoped(provider => + provider.GetRequiredService()); + + + + #region GozareshgirDbContext + + services.AddDbContext(x => x.UseSqlServer(configuration.GetConnectionString("GozareshgirDb"))); + + services.AddScoped(provider => + provider.GetRequiredService()); + #endregion + + // Unit of Work + services.AddScoped(); + + //Users + services.AddScoped(); + + //Roles + services.AddScoped(); + + //WorkingHours + services.AddScoped(); + + //Checkout + services.AddScoped(); + + // Repositories + services.AddScoped(); + + // Legacy Project repositories + services.AddScoped(); + + // New Hierarchy repositories + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + services.AddScoped(); + + services.AddScoped(); + + // JWT Settings + services.Configure(configuration.GetSection("JwtSettings")); + + // Authentication Services + services.AddScoped(); + services.AddScoped(); + + + + + // MediatR Validation Behavior + services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); + + + return services; + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj new file mode 100644 index 00000000..57ba7bdb --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj @@ -0,0 +1,22 @@ + + + + net10.0 + enable + enable + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.Designer.cs new file mode 100644 index 00000000..45ff290c --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.Designer.cs @@ -0,0 +1,393 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251119114157_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.AdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("TaskSectionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("AssignedUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.HasIndex("Level", "AssignedUserId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("ProjectTaskId") + .HasColumnType("uniqueidentifier"); + + b.Property("SectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskNodeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ProjectTaskId"); + + b.HasIndex("TaskNodeId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.AdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("TaskSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "ProjectPhase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectPhase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", null) + .WithMany("Sections") + .HasForeignKey("ProjectTaskId"); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "TaskNode") + .WithMany("Sections") + .HasForeignKey("TaskNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskNode"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.cs new file mode 100644 index 00000000..546082b6 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119114157_Initial.cs @@ -0,0 +1,262 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Customers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + CreatedAt = table.Column(type: "datetime2", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Customers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ProjectNodes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Level = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + ParentId = table.Column(type: "uniqueidentifier", nullable: true), + AllocatedTime = table.Column(type: "time", nullable: true), + AssignedUserId = table.Column(type: "bigint", nullable: true), + HasTimeOverride = table.Column(type: "bit", nullable: false, defaultValue: false), + HasAssignmentOverride = table.Column(type: "bit", nullable: false, defaultValue: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectNodes", x => x.Id); + table.ForeignKey( + name: "FK_ProjectNodes_ProjectNodes_ParentId", + column: x => x.ParentId, + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "Projects", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Projects", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ProjectPhases", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + ProjectId = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectPhases", x => x.Id); + table.ForeignKey( + name: "FK_ProjectPhases_Projects_ProjectId", + column: x => x.ProjectId, + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectTasks", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + PhaseId = table.Column(type: "uniqueidentifier", nullable: false), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectTasks", x => x.Id); + table.ForeignKey( + name: "FK_ProjectTasks_ProjectPhases_PhaseId", + column: x => x.PhaseId, + principalTable: "ProjectPhases", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "TaskSections", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TaskNodeId = table.Column(type: "uniqueidentifier", nullable: false), + SectionType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + InitialEstimatedHours = table.Column(type: "time", nullable: false), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + CurrentAssignedUserId = table.Column(type: "bigint", nullable: true), + AllocatedTime = table.Column(type: "time", nullable: true), + ProjectTaskId = table.Column(type: "uniqueidentifier", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TaskSections", x => x.Id); + table.ForeignKey( + name: "FK_TaskSections_ProjectNodes_TaskNodeId", + column: x => x.TaskNodeId, + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_TaskSections_ProjectTasks_ProjectTaskId", + column: x => x.ProjectTaskId, + principalTable: "ProjectTasks", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AdditionalTimes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Hours = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + Reason = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + AddedByUserId = table.Column(type: "bigint", nullable: true), + AddedAt = table.Column(type: "datetime2", nullable: false), + TaskSectionId = table.Column(type: "uniqueidentifier", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AdditionalTimes", x => x.Id); + table.ForeignKey( + name: "FK_AdditionalTimes_TaskSections_TaskSectionId", + column: x => x.TaskSectionId, + principalTable: "TaskSections", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "TaskSectionActivities", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SectionId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + StartDate = table.Column(type: "datetime2", nullable: false), + EndDate = table.Column(type: "datetime2", nullable: true), + Notes = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + EndNotes = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TaskSectionActivities", x => x.Id); + table.ForeignKey( + name: "FK_TaskSectionActivities_TaskSections_SectionId", + column: x => x.SectionId, + principalTable: "TaskSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AdditionalTimes_TaskSectionId", + table: "AdditionalTimes", + column: "TaskSectionId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectNodes_Level", + table: "ProjectNodes", + column: "Level"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectNodes_Level_AssignedUserId", + table: "ProjectNodes", + columns: new[] { "Level", "AssignedUserId" }); + + migrationBuilder.CreateIndex( + name: "IX_ProjectNodes_ParentId", + table: "ProjectNodes", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectPhases_ProjectId", + table: "ProjectPhases", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectTasks_PhaseId", + table: "ProjectTasks", + column: "PhaseId"); + + migrationBuilder.CreateIndex( + name: "IX_TaskSectionActivities_SectionId", + table: "TaskSectionActivities", + column: "SectionId"); + + migrationBuilder.CreateIndex( + name: "IX_TaskSections_ProjectTaskId", + table: "TaskSections", + column: "ProjectTaskId"); + + migrationBuilder.CreateIndex( + name: "IX_TaskSections_TaskNodeId", + table: "TaskSections", + column: "TaskNodeId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AdditionalTimes"); + + migrationBuilder.DropTable( + name: "Customers"); + + migrationBuilder.DropTable( + name: "TaskSectionActivities"); + + migrationBuilder.DropTable( + name: "TaskSections"); + + migrationBuilder.DropTable( + name: "ProjectNodes"); + + migrationBuilder.DropTable( + name: "ProjectTasks"); + + migrationBuilder.DropTable( + name: "ProjectPhases"); + + migrationBuilder.DropTable( + name: "Projects"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.Designer.cs new file mode 100644 index 00000000..e78e8c7c --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.Designer.cs @@ -0,0 +1,320 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251119152314_ChangeUsertable")] + partial class ChangeUsertable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("AssignedUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.HasIndex("Level", "AssignedUserId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("SectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskNodeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskNodeId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "TaskNode") + .WithMany("Sections") + .HasForeignKey("TaskNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskNode"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.cs new file mode 100644 index 00000000..334e7d78 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251119152314_ChangeUsertable.cs @@ -0,0 +1,192 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class ChangeUsertable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AdditionalTimes_TaskSections_TaskSectionId", + table: "AdditionalTimes"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskSections_ProjectTasks_ProjectTaskId", + table: "TaskSections"); + + migrationBuilder.DropTable( + name: "ProjectTasks"); + + migrationBuilder.DropTable( + name: "ProjectPhases"); + + migrationBuilder.DropTable( + name: "Projects"); + + migrationBuilder.DropIndex( + name: "IX_TaskSections_ProjectTaskId", + table: "TaskSections"); + + migrationBuilder.DropColumn( + name: "ProjectTaskId", + table: "TaskSections"); + + migrationBuilder.RenameColumn( + name: "TaskSectionId", + table: "AdditionalTimes", + newName: "ProjectSectionId"); + + migrationBuilder.RenameIndex( + name: "IX_AdditionalTimes_TaskSectionId", + table: "AdditionalTimes", + newName: "IX_AdditionalTimes_ProjectSectionId"); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + FullName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + UserName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + Password = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: false), + ProfilePhotoPath = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + Mobile = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), + Email = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true), + IsActive = table.Column(type: "bit", nullable: false), + VerifyCode = table.Column(type: "nvarchar(10)", maxLength: 10, nullable: true), + AccountId = table.Column(type: "bigint", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.AddForeignKey( + name: "FK_AdditionalTimes_TaskSections_ProjectSectionId", + table: "AdditionalTimes", + column: "ProjectSectionId", + principalTable: "TaskSections", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AdditionalTimes_TaskSections_ProjectSectionId", + table: "AdditionalTimes"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.RenameColumn( + name: "ProjectSectionId", + table: "AdditionalTimes", + newName: "TaskSectionId"); + + migrationBuilder.RenameIndex( + name: "IX_AdditionalTimes_ProjectSectionId", + table: "AdditionalTimes", + newName: "IX_AdditionalTimes_TaskSectionId"); + + migrationBuilder.AddColumn( + name: "ProjectTaskId", + table: "TaskSections", + type: "uniqueidentifier", + nullable: true); + + migrationBuilder.CreateTable( + name: "Projects", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Projects", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ProjectPhases", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ProjectId = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectPhases", x => x.Id); + table.ForeignKey( + name: "FK_ProjectPhases_Projects_ProjectId", + column: x => x.ProjectId, + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectTasks", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + PhaseId = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectTasks", x => x.Id); + table.ForeignKey( + name: "FK_ProjectTasks_ProjectPhases_PhaseId", + column: x => x.PhaseId, + principalTable: "ProjectPhases", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_TaskSections_ProjectTaskId", + table: "TaskSections", + column: "ProjectTaskId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectPhases_ProjectId", + table: "ProjectPhases", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectTasks_PhaseId", + table: "ProjectTasks", + column: "PhaseId"); + + migrationBuilder.AddForeignKey( + name: "FK_AdditionalTimes_TaskSections_TaskSectionId", + table: "AdditionalTimes", + column: "TaskSectionId", + principalTable: "TaskSections", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSections_ProjectTasks_ProjectTaskId", + table: "TaskSections", + column: "ProjectTaskId", + principalTable: "ProjectTasks", + principalColumn: "Id"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.Designer.cs new file mode 100644 index 00000000..2ac5aede --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.Designer.cs @@ -0,0 +1,372 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251123123226_RoleInit")] + partial class RoleInit + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("AssignedUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.HasIndex("Level", "AssignedUserId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("SectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskNodeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskNodeId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "TaskNode") + .WithMany("Sections") + .HasForeignKey("TaskNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskNode"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.cs new file mode 100644 index 00000000..bea52da9 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123123226_RoleInit.cs @@ -0,0 +1,64 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class RoleInit : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Roles", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RolePermissions", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Code = table.Column(type: "int", nullable: false), + RoleId = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RolePermissions", x => x.Id); + table.ForeignKey( + name: "FK_RolePermissions_Roles_RoleId", + column: x => x.RoleId, + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_RolePermissions_RoleId", + table: "RolePermissions", + column: "RoleId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RolePermissions"); + + migrationBuilder.DropTable( + name: "Roles"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.Designer.cs new file mode 100644 index 00000000..f8e22836 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.Designer.cs @@ -0,0 +1,375 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251123135308_RoleUpdate")] + partial class RoleUpdate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("AssignedUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.HasIndex("Level", "AssignedUserId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("SectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskNodeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskNodeId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "TaskNode") + .WithMany("Sections") + .HasForeignKey("TaskNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskNode"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.cs new file mode 100644 index 00000000..16b9be9c --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251123135308_RoleUpdate.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class RoleUpdate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GozareshgirRoleId", + table: "Roles", + type: "bigint", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "GozareshgirRoleId", + table: "Roles"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.Designer.cs new file mode 100644 index 00000000..827e389f --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.Designer.cs @@ -0,0 +1,346 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251125111142_add skills to entity")] + partial class addskillstoentity + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskNodeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskNodeId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "TaskNode") + .WithMany("Sections") + .HasForeignKey("TaskNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("TaskNode"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.cs new file mode 100644 index 00000000..944ad923 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125111142_add skills to entity.cs @@ -0,0 +1,222 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class addskillstoentity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AdditionalTimes_TaskSections_ProjectSectionId", + table: "AdditionalTimes"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskSectionActivities_TaskSections_SectionId", + table: "TaskSectionActivities"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskSections_ProjectNodes_TaskNodeId", + table: "TaskSections"); + + migrationBuilder.DropIndex( + name: "IX_ProjectNodes_Level_AssignedUserId", + table: "ProjectNodes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_TaskSections", + table: "TaskSections"); + + migrationBuilder.DropColumn( + name: "AssignedUserId", + table: "ProjectNodes"); + + migrationBuilder.DropColumn( + name: "SectionType", + table: "TaskSections"); + + migrationBuilder.RenameTable( + name: "TaskSections", + newName: "ProjectSections"); + + migrationBuilder.RenameIndex( + name: "IX_TaskSections_TaskNodeId", + table: "ProjectSections", + newName: "IX_ProjectSections_TaskNodeId"); + + migrationBuilder.AlterColumn( + name: "CurrentAssignedUserId", + table: "ProjectSections", + type: "bigint", + nullable: false, + defaultValue: 0L, + oldClrType: typeof(long), + oldType: "bigint", + oldNullable: true); + + migrationBuilder.AddColumn( + name: "SkillId", + table: "ProjectSections", + type: "uniqueidentifier", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProjectSections", + table: "ProjectSections", + column: "Id"); + + migrationBuilder.CreateTable( + name: "Skills", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Skills", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSections_SkillId", + table: "ProjectSections", + column: "SkillId"); + + migrationBuilder.AddForeignKey( + name: "FK_AdditionalTimes_ProjectSections_ProjectSectionId", + table: "AdditionalTimes", + column: "ProjectSectionId", + principalTable: "ProjectSections", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_ProjectNodes_TaskNodeId", + table: "ProjectSections", + column: "TaskNodeId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_Skills_SkillId", + table: "ProjectSections", + column: "SkillId", + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSectionActivities_ProjectSections_SectionId", + table: "TaskSectionActivities", + column: "SectionId", + principalTable: "ProjectSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AdditionalTimes_ProjectSections_ProjectSectionId", + table: "AdditionalTimes"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_ProjectNodes_TaskNodeId", + table: "ProjectSections"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_Skills_SkillId", + table: "ProjectSections"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskSectionActivities_ProjectSections_SectionId", + table: "TaskSectionActivities"); + + migrationBuilder.DropTable( + name: "Skills"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProjectSections", + table: "ProjectSections"); + + migrationBuilder.DropIndex( + name: "IX_ProjectSections_SkillId", + table: "ProjectSections"); + + migrationBuilder.DropColumn( + name: "SkillId", + table: "ProjectSections"); + + migrationBuilder.RenameTable( + name: "ProjectSections", + newName: "TaskSections"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_TaskNodeId", + table: "TaskSections", + newName: "IX_TaskSections_TaskNodeId"); + + migrationBuilder.AddColumn( + name: "AssignedUserId", + table: "ProjectNodes", + type: "bigint", + nullable: true); + + migrationBuilder.AlterColumn( + name: "CurrentAssignedUserId", + table: "TaskSections", + type: "bigint", + nullable: true, + oldClrType: typeof(long), + oldType: "bigint"); + + migrationBuilder.AddColumn( + name: "SectionType", + table: "TaskSections", + type: "nvarchar(50)", + maxLength: 50, + nullable: false, + defaultValue: ""); + + migrationBuilder.AddPrimaryKey( + name: "PK_TaskSections", + table: "TaskSections", + column: "Id"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectNodes_Level_AssignedUserId", + table: "ProjectNodes", + columns: new[] { "Level", "AssignedUserId" }); + + migrationBuilder.AddForeignKey( + name: "FK_AdditionalTimes_TaskSections_ProjectSectionId", + table: "AdditionalTimes", + column: "ProjectSectionId", + principalTable: "TaskSections", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSectionActivities_TaskSections_SectionId", + table: "TaskSectionActivities", + column: "SectionId", + principalTable: "TaskSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSections_ProjectNodes_TaskNodeId", + table: "TaskSections", + column: "TaskNodeId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.Designer.cs new file mode 100644 index 00000000..9f6ea58c --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.Designer.cs @@ -0,0 +1,346 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251125112542_change section key name")] + partial class changesectionkeyname + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("ProjectNodeId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectNodeId"); + + b.HasIndex("SkillId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "ProjectNode") + .WithMany("Sections") + .HasForeignKey("ProjectNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectNode"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.cs new file mode 100644 index 00000000..8fd3deda --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125112542_change section key name.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class changesectionkeyname : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_ProjectNodes_TaskNodeId", + table: "ProjectSections"); + + migrationBuilder.RenameColumn( + name: "TaskNodeId", + table: "ProjectSections", + newName: "ProjectNodeId"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_TaskNodeId", + table: "ProjectSections", + newName: "IX_ProjectSections_ProjectNodeId"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_ProjectNodes_ProjectNodeId", + table: "ProjectSections", + column: "ProjectNodeId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_ProjectNodes_ProjectNodeId", + table: "ProjectSections"); + + migrationBuilder.RenameColumn( + name: "ProjectNodeId", + table: "ProjectSections", + newName: "TaskNodeId"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_ProjectNodeId", + table: "ProjectSections", + newName: "IX_ProjectSections_TaskNodeId"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_ProjectNodes_TaskNodeId", + table: "ProjectSections", + column: "TaskNodeId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.Designer.cs new file mode 100644 index 00000000..c8e06582 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.Designer.cs @@ -0,0 +1,346 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251125145830_change project node on delete to cascade")] + partial class changeprojectnodeondeletetocascade + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("ProjectNodeId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectNodeId"); + + b.HasIndex("SkillId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "ProjectNode") + .WithMany("Sections") + .HasForeignKey("ProjectNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectNode"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.cs new file mode 100644 index 00000000..c2d73e3d --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125145830_change project node on delete to cascade.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class changeprojectnodeondeletetocascade : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.Designer.cs new file mode 100644 index 00000000..c35702a7 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.Designer.cs @@ -0,0 +1,349 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251125164239_change section and additionalTime description")] + partial class changesectionandadditionalTimedescription + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectNodeId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectNodeId"); + + b.HasIndex("SkillId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("ProjectSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "ProjectNode") + .WithMany("Sections") + .HasForeignKey("ProjectNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectNode"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.cs new file mode 100644 index 00000000..6c2696bc --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251125164239_change section and additionalTime description.cs @@ -0,0 +1,142 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class changesectionandadditionalTimedescription : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ProjectNodes_ProjectNodes_ParentId", + table: "ProjectNodes"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskSectionActivities_ProjectSections_SectionId", + table: "TaskSectionActivities"); + + migrationBuilder.DropPrimaryKey( + name: "PK_TaskSectionActivities", + table: "TaskSectionActivities"); + + migrationBuilder.DropColumn( + name: "AllocatedTime", + table: "ProjectSections"); + + migrationBuilder.RenameTable( + name: "TaskSectionActivities", + newName: "ProjectSectionActivities"); + + migrationBuilder.RenameIndex( + name: "IX_TaskSectionActivities_SectionId", + table: "ProjectSectionActivities", + newName: "IX_ProjectSectionActivities_SectionId"); + + migrationBuilder.AlterColumn( + name: "InitialEstimatedHours", + table: "ProjectSections", + type: "nvarchar(30)", + maxLength: 30, + nullable: false, + oldClrType: typeof(TimeSpan), + oldType: "time"); + + migrationBuilder.AddColumn( + name: "InitialDescription", + table: "ProjectSections", + type: "nvarchar(500)", + maxLength: 500, + nullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProjectSectionActivities", + table: "ProjectSectionActivities", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectNodes_ProjectNodes_ParentId", + table: "ProjectNodes", + column: "ParentId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSectionActivities_ProjectSections_SectionId", + table: "ProjectSectionActivities", + column: "SectionId", + principalTable: "ProjectSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ProjectNodes_ProjectNodes_ParentId", + table: "ProjectNodes"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSectionActivities_ProjectSections_SectionId", + table: "ProjectSectionActivities"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProjectSectionActivities", + table: "ProjectSectionActivities"); + + migrationBuilder.DropColumn( + name: "InitialDescription", + table: "ProjectSections"); + + migrationBuilder.RenameTable( + name: "ProjectSectionActivities", + newName: "TaskSectionActivities"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSectionActivities_SectionId", + table: "TaskSectionActivities", + newName: "IX_TaskSectionActivities_SectionId"); + + migrationBuilder.AlterColumn( + name: "InitialEstimatedHours", + table: "ProjectSections", + type: "time", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(30)", + oldMaxLength: 30); + + migrationBuilder.AddColumn( + name: "AllocatedTime", + table: "ProjectSections", + type: "time", + nullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_TaskSectionActivities", + table: "TaskSectionActivities", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectNodes_ProjectNodes_ParentId", + table: "ProjectNodes", + column: "ParentId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSectionActivities_ProjectSections_SectionId", + table: "TaskSectionActivities", + column: "SectionId", + principalTable: "ProjectSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.Designer.cs new file mode 100644 index 00000000..1132e866 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.Designer.cs @@ -0,0 +1,406 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251126122836_AddUserRoleTable")] + partial class AddUserRoleTable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("AssignedUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.HasIndex("Level", "AssignedUserId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialEstimatedHours") + .HasColumnType("time"); + + b.Property("SectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskNodeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskNodeId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "TaskNode") + .WithMany("Sections") + .HasForeignKey("TaskNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskNode"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.cs new file mode 100644 index 00000000..23d03281 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251126122836_AddUserRoleTable.cs @@ -0,0 +1,46 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class AddUserRoleTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "RoleUsers", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "bigint", nullable: false), + UserId = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RoleUsers", x => x.Id); + table.ForeignKey( + name: "FK_RoleUsers_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_RoleUsers_UserId", + table: "RoleUsers", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RoleUsers"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.Designer.cs new file mode 100644 index 00000000..a865122a --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.Designer.cs @@ -0,0 +1,556 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251201120420_change projects from nodes to three seprated pieces")] + partial class changeprojectsfromnodestothreesepratedpieces + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("ProjectSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("ProjectSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.cs new file mode 100644 index 00000000..b6e789f8 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201120420_change projects from nodes to three seprated pieces.cs @@ -0,0 +1,287 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class changeprojectsfromnodestothreesepratedpieces : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AdditionalTimes_ProjectSections_ProjectSectionId", + table: "AdditionalTimes"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_ProjectNodes_ProjectNodeId", + table: "ProjectSections"); + + migrationBuilder.DropTable( + name: "ProjectNodes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_AdditionalTimes", + table: "AdditionalTimes"); + + migrationBuilder.RenameTable( + name: "AdditionalTimes", + newName: "ProjectSectionAdditionalTimes"); + + migrationBuilder.RenameColumn( + name: "ProjectNodeId", + table: "ProjectSections", + newName: "TaskId"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_ProjectNodeId", + table: "ProjectSections", + newName: "IX_ProjectSections_TaskId"); + + migrationBuilder.RenameIndex( + name: "IX_AdditionalTimes_ProjectSectionId", + table: "ProjectSectionAdditionalTimes", + newName: "IX_ProjectSectionAdditionalTimes_ProjectSectionId"); + + migrationBuilder.AddColumn( + name: "IsActive", + table: "ProjectSectionActivities", + type: "bit", + nullable: false, + defaultValue: false); + + migrationBuilder.AlterColumn( + name: "Reason", + table: "ProjectSectionAdditionalTimes", + type: "nvarchar(500)", + maxLength: 500, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(1000)", + oldMaxLength: 1000, + oldNullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProjectSectionAdditionalTimes", + table: "ProjectSectionAdditionalTimes", + column: "Id"); + + migrationBuilder.CreateTable( + name: "Projects", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + StartDate = table.Column(type: "datetime2", nullable: true), + EndDate = table.Column(type: "datetime2", nullable: true), + PlannedStartDate = table.Column(type: "datetime2", nullable: true), + PlannedEndDate = table.Column(type: "datetime2", nullable: true), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + HasAssignmentOverride = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Projects", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ProjectPhases", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ProjectId = table.Column(type: "uniqueidentifier", nullable: false), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + StartDate = table.Column(type: "datetime2", nullable: true), + EndDate = table.Column(type: "datetime2", nullable: true), + OrderIndex = table.Column(type: "int", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + HasAssignmentOverride = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectPhases", x => x.Id); + table.ForeignKey( + name: "FK_ProjectPhases_Projects_ProjectId", + column: x => x.ProjectId, + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectTasks", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + PhaseId = table.Column(type: "uniqueidentifier", nullable: false), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + Priority = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + StartDate = table.Column(type: "datetime2", nullable: true), + EndDate = table.Column(type: "datetime2", nullable: true), + DueDate = table.Column(type: "datetime2", nullable: true), + OrderIndex = table.Column(type: "int", nullable: false), + AllocatedTime = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: true), + HasTimeOverride = table.Column(type: "bit", nullable: false), + HasAssignmentOverride = table.Column(type: "bit", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectTasks", x => x.Id); + table.ForeignKey( + name: "FK_ProjectTasks_ProjectPhases_PhaseId", + column: x => x.PhaseId, + principalTable: "ProjectPhases", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ProjectPhases_ProjectId", + table: "ProjectPhases", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectTasks_PhaseId", + table: "ProjectTasks", + column: "PhaseId"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSectionAdditionalTimes_ProjectSections_ProjectSectionId", + table: "ProjectSectionAdditionalTimes", + column: "ProjectSectionId", + principalTable: "ProjectSections", + principalColumn: "Id"); + + // migrationBuilder.AddForeignKey( + // name: "FK_ProjectSections_ProjectTasks_TaskId", + // table: "ProjectSections", + // column: "TaskId", + // principalTable: "ProjectTasks", + // principalColumn: "Id", + // onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ProjectSectionAdditionalTimes_ProjectSections_ProjectSectionId", + table: "ProjectSectionAdditionalTimes"); + + // migrationBuilder.DropForeignKey( + // name: "FK_ProjectSections_ProjectTasks_TaskId", + // table: "ProjectSections"); + + migrationBuilder.DropTable( + name: "ProjectTasks"); + + migrationBuilder.DropTable( + name: "ProjectPhases"); + + migrationBuilder.DropTable( + name: "Projects"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProjectSectionAdditionalTimes", + table: "ProjectSectionAdditionalTimes"); + + migrationBuilder.DropColumn( + name: "IsActive", + table: "ProjectSectionActivities"); + + migrationBuilder.RenameTable( + name: "ProjectSectionAdditionalTimes", + newName: "AdditionalTimes"); + + migrationBuilder.RenameColumn( + name: "TaskId", + table: "ProjectSections", + newName: "ProjectNodeId"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_TaskId", + table: "ProjectSections", + newName: "IX_ProjectSections_ProjectNodeId"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSectionAdditionalTimes_ProjectSectionId", + table: "AdditionalTimes", + newName: "IX_AdditionalTimes_ProjectSectionId"); + + migrationBuilder.AlterColumn( + name: "Reason", + table: "AdditionalTimes", + type: "nvarchar(1000)", + maxLength: 1000, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(500)", + oldMaxLength: 500, + oldNullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_AdditionalTimes", + table: "AdditionalTimes", + column: "Id"); + + migrationBuilder.CreateTable( + name: "ProjectNodes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ParentId = table.Column(type: "uniqueidentifier", nullable: true), + AllocatedTime = table.Column(type: "time", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + HasAssignmentOverride = table.Column(type: "bit", nullable: false, defaultValue: false), + HasTimeOverride = table.Column(type: "bit", nullable: false, defaultValue: false), + Level = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectNodes", x => x.Id); + table.ForeignKey( + name: "FK_ProjectNodes_ProjectNodes_ParentId", + column: x => x.ParentId, + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_ProjectNodes_Level", + table: "ProjectNodes", + column: "Level"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectNodes_ParentId", + table: "ProjectNodes", + column: "ParentId"); + + migrationBuilder.AddForeignKey( + name: "FK_AdditionalTimes_ProjectSections_ProjectSectionId", + table: "AdditionalTimes", + column: "ProjectSectionId", + principalTable: "ProjectSections", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_ProjectNodes_ProjectNodeId", + table: "ProjectSections", + column: "ProjectNodeId", + principalTable: "ProjectNodes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.Designer.cs new file mode 100644 index 00000000..df7b277f --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.Designer.cs @@ -0,0 +1,524 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251201150949_SalaryPaymentSettingInit")] + partial class SalaryPaymentSettingInit + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.22") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasColumnType("time"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HasAssignmentOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("HasTimeOverride") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("Level") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Level"); + + b.HasIndex("ParentId"); + + b.ToTable("ProjectNodes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectNodeId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectNodeId"); + + b.HasIndex("SkillId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("ProjectSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("AdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", "ProjectNode") + .WithMany("Sections") + .HasForeignKey("ProjectNodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProjectNode"); + + b.Navigation("Skill"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectNode", b => + { + b.Navigation("Children"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.cs new file mode 100644 index 00000000..8ae61fbb --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251201150949_SalaryPaymentSettingInit.cs @@ -0,0 +1,87 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class SalaryPaymentSettingInit : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "SalaryPaymentSetting", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + HolidayWorking = table.Column(type: "bit", nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + MonthlySalary = table.Column(type: "float", nullable: false), + StartSettingDate = table.Column(type: "datetime2", nullable: true), + EndSettingDate = table.Column(type: "datetime2", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SalaryPaymentSetting", x => x.Id); + }); + + + + migrationBuilder.CreateTable( + name: "WorkingHours", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + StartShiftOne = table.Column(type: "time(0)", nullable: false), + EndShiftOne = table.Column(type: "time(0)", nullable: false), + StartShiftTwo = table.Column(type: "time(0)", nullable: false), + EndShiftTwo = table.Column(type: "time(0)", nullable: false), + RestTime = table.Column(type: "time(0)", nullable: false), + HasShiftOne = table.Column(type: "bit", nullable: false), + HasShiftTow = table.Column(type: "bit", nullable: false), + HasRestTime = table.Column(type: "bit", nullable: false), + ShiftDurationInMinutes = table.Column(type: "int", nullable: false), + PersianDayOfWeek = table.Column(type: "int", nullable: false), + SalaryPaymentSettingId = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_WorkingHours", x => x.Id); + table.ForeignKey( + name: "FK_WorkingHours_SalaryPaymentSetting_SalaryPaymentSettingId", + column: x => x.SalaryPaymentSettingId, + principalTable: "SalaryPaymentSetting", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + + + migrationBuilder.CreateIndex( + name: "IX_WorkingHours_SalaryPaymentSettingId", + table: "WorkingHours", + column: "SalaryPaymentSettingId"); + + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + + migrationBuilder.DropTable( + name: "WorkingHours"); + + migrationBuilder.DropTable( + name: "SalaryPaymentSetting"); + + + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.Designer.cs new file mode 100644 index 00000000..f6ad2cf2 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.Designer.cs @@ -0,0 +1,648 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251202113519_IsActiveDayToWorkingHours")] + partial class IsActiveDayToWorkingHours + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("ProjectSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("ProjectSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.cs new file mode 100644 index 00000000..8e4cf65f --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202113519_IsActiveDayToWorkingHours.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class IsActiveDayToWorkingHours : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsActiveDay", + table: "WorkingHours", + type: "bit", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsActiveDay", + table: "WorkingHours"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.Designer.cs new file mode 100644 index 00000000..a529f983 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.Designer.cs @@ -0,0 +1,706 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251202145954_CheckoutInit")] + partial class CheckoutInit + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CheckoutAgg.Entities.Checkout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CheckoutEndDate") + .HasColumnType("datetime2"); + + b.Property("CheckoutStartDate") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeductionFromSalary") + .HasColumnType("float"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MandatoryHours") + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("MonthlySalaryDefined") + .HasColumnType("float"); + + b.Property("MonthlySalaryPay") + .HasColumnType("float"); + + b.Property("RemainingHours") + .HasColumnType("int"); + + b.Property("TotalDaysWorked") + .HasColumnType("int"); + + b.Property("TotalHoursWorked") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Checkouts", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("ProjectSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("ProjectSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.cs new file mode 100644 index 00000000..8aa33809 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251202145954_CheckoutInit.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class CheckoutInit : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + + migrationBuilder.CreateTable( + name: "Checkouts", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + CheckoutStartDate = table.Column(type: "datetime2", nullable: false), + CheckoutEndDate = table.Column(type: "datetime2", nullable: false), + Year = table.Column(type: "int", nullable: false), + Month = table.Column(type: "int", nullable: false), + FullName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + MandatoryHours = table.Column(type: "int", nullable: false), + TotalHoursWorked = table.Column(type: "int", nullable: false), + TotalDaysWorked = table.Column(type: "int", nullable: false), + RemainingHours = table.Column(type: "int", nullable: false), + MonthlySalaryDefined = table.Column(type: "float", nullable: false), + MonthlySalaryPay = table.Column(type: "float", nullable: false), + DeductionFromSalary = table.Column(type: "float", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Checkouts", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Checkouts"); + + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.Designer.cs new file mode 100644 index 00000000..3d7eedab --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.Designer.cs @@ -0,0 +1,707 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251203071011_add user refresh token")] + partial class adduserrefreshtoken + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("ProjectSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("ProjectSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ProjectSectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectSectionId"); + + b.ToTable("ProjectSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RevokedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAt"); + + b.HasIndex("Token") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserRefreshTokens", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("ProjectSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.cs new file mode 100644 index 00000000..c4e6c962 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203071011_add user refresh token.cs @@ -0,0 +1,62 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class adduserrefreshtoken : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "UserRefreshTokens", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + Token = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), + ExpiresAt = table.Column(type: "datetime2", nullable: false), + RevokedAt = table.Column(type: "datetime2", nullable: true), + IpAddress = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + UserAgent = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRefreshTokens", x => x.Id); + table.ForeignKey( + name: "FK_UserRefreshTokens_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserRefreshTokens_ExpiresAt", + table: "UserRefreshTokens", + column: "ExpiresAt"); + + migrationBuilder.CreateIndex( + name: "IX_UserRefreshTokens_Token", + table: "UserRefreshTokens", + column: "Token", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_UserRefreshTokens_UserId", + table: "UserRefreshTokens", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserRefreshTokens"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.Designer.cs new file mode 100644 index 00000000..902c1fb7 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.Designer.cs @@ -0,0 +1,786 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251203174140_add sections")] + partial class addsections + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("PhaseSection"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectSection"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TaskSectionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskSectionId"); + + b.ToTable("TaskSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RevokedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAt"); + + b.HasIndex("Token") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserRefreshTokens", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("PhaseSections") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("ProjectSections") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("TaskSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + + b.Navigation("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("PhaseSections"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.cs new file mode 100644 index 00000000..fb691678 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251203174140_add sections.cs @@ -0,0 +1,288 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class addsections : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_Skills_SkillId", + table: "ProjectSections"); + + migrationBuilder.DropTable( + name: "ProjectSectionActivities"); + + migrationBuilder.DropTable( + name: "ProjectSectionAdditionalTimes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProjectSections", + table: "ProjectSections"); + + migrationBuilder.RenameTable( + name: "ProjectSections", + newName: "TaskSections"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_TaskId", + table: "TaskSections", + newName: "IX_TaskSections_TaskId"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_SkillId", + table: "TaskSections", + newName: "IX_TaskSections_SkillId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_TaskSections", + table: "TaskSections", + column: "Id"); + + migrationBuilder.CreateTable( + name: "PhaseSection", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + PhaseId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + SkillId = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PhaseSection", x => x.Id); + table.ForeignKey( + name: "FK_PhaseSection_ProjectPhases_PhaseId", + column: x => x.PhaseId, + principalTable: "ProjectPhases", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectSection", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ProjectId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + SkillId = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectSection", x => x.Id); + table.ForeignKey( + name: "FK_ProjectSection_Projects_ProjectId", + column: x => x.ProjectId, + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "TaskSectionActivities", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SectionId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "bigint", nullable: false), + StartDate = table.Column(type: "datetime2", nullable: false), + EndDate = table.Column(type: "datetime2", nullable: true), + Notes = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + EndNotes = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + IsActive = table.Column(type: "bit", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TaskSectionActivities", x => x.Id); + table.ForeignKey( + name: "FK_TaskSectionActivities_TaskSections_SectionId", + column: x => x.SectionId, + principalTable: "TaskSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "TaskSectionAdditionalTimes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Hours = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + Reason = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + AddedByUserId = table.Column(type: "bigint", nullable: true), + AddedAt = table.Column(type: "datetime2", nullable: false), + TaskSectionId = table.Column(type: "uniqueidentifier", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TaskSectionAdditionalTimes", x => x.Id); + table.ForeignKey( + name: "FK_TaskSectionAdditionalTimes_TaskSections_TaskSectionId", + column: x => x.TaskSectionId, + principalTable: "TaskSections", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_PhaseSection_PhaseId", + table: "PhaseSection", + column: "PhaseId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSection_ProjectId", + table: "ProjectSection", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_TaskSectionActivities_SectionId", + table: "TaskSectionActivities", + column: "SectionId"); + + migrationBuilder.CreateIndex( + name: "IX_TaskSectionAdditionalTimes_TaskSectionId", + table: "TaskSectionAdditionalTimes", + column: "TaskSectionId"); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSections_ProjectTasks_TaskId", + table: "TaskSections", + column: "TaskId", + principalTable: "ProjectTasks", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_TaskSections_Skills_SkillId", + table: "TaskSections", + column: "SkillId", + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_TaskSections_ProjectTasks_TaskId", + table: "TaskSections"); + + migrationBuilder.DropForeignKey( + name: "FK_TaskSections_Skills_SkillId", + table: "TaskSections"); + + migrationBuilder.DropTable( + name: "PhaseSection"); + + migrationBuilder.DropTable( + name: "ProjectSection"); + + migrationBuilder.DropTable( + name: "TaskSectionActivities"); + + migrationBuilder.DropTable( + name: "TaskSectionAdditionalTimes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_TaskSections", + table: "TaskSections"); + + migrationBuilder.RenameTable( + name: "TaskSections", + newName: "ProjectSections"); + + migrationBuilder.RenameIndex( + name: "IX_TaskSections_TaskId", + table: "ProjectSections", + newName: "IX_ProjectSections_TaskId"); + + migrationBuilder.RenameIndex( + name: "IX_TaskSections_SkillId", + table: "ProjectSections", + newName: "IX_ProjectSections_SkillId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProjectSections", + table: "ProjectSections", + column: "Id"); + + migrationBuilder.CreateTable( + name: "ProjectSectionActivities", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SectionId = table.Column(type: "uniqueidentifier", nullable: false), + CreationDate = table.Column(type: "datetime2", nullable: false), + EndDate = table.Column(type: "datetime2", nullable: true), + EndNotes = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + IsActive = table.Column(type: "bit", nullable: false), + Notes = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + StartDate = table.Column(type: "datetime2", nullable: false), + UserId = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectSectionActivities", x => x.Id); + table.ForeignKey( + name: "FK_ProjectSectionActivities_ProjectSections_SectionId", + column: x => x.SectionId, + principalTable: "ProjectSections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectSectionAdditionalTimes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + AddedAt = table.Column(type: "datetime2", nullable: false), + AddedByUserId = table.Column(type: "bigint", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: false), + Hours = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + ProjectSectionId = table.Column(type: "uniqueidentifier", nullable: true), + Reason = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectSectionAdditionalTimes", x => x.Id); + table.ForeignKey( + name: "FK_ProjectSectionAdditionalTimes_ProjectSections_ProjectSectionId", + column: x => x.ProjectSectionId, + principalTable: "ProjectSections", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSectionActivities_SectionId", + table: "ProjectSectionActivities", + column: "SectionId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSectionAdditionalTimes_ProjectSectionId", + table: "ProjectSectionAdditionalTimes", + column: "ProjectSectionId"); + + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_Skills_SkillId", + table: "ProjectSections", + column: "SkillId", + principalTable: "Skills", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.Designer.cs new file mode 100644 index 00000000..4de07c56 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.Designer.cs @@ -0,0 +1,839 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251206064818_add phase section and task section")] + partial class addphasesectionandtasksection + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CheckoutAgg.Entities.Checkout", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CheckoutEndDate") + .HasColumnType("datetime2"); + + b.Property("CheckoutStartDate") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeductionFromSalary") + .HasColumnType("float"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MandatoryHours") + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("MonthlySalaryDefined") + .HasColumnType("float"); + + b.Property("MonthlySalaryPay") + .HasColumnType("float"); + + b.Property("RemainingHours") + .HasColumnType("int"); + + b.Property("TotalDaysWorked") + .HasColumnType("int"); + + b.Property("TotalHoursWorked") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Checkouts", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("PhaseSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TaskSectionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskSectionId"); + + b.ToTable("TaskSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RevokedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAt"); + + b.HasIndex("Token") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserRefreshTokens", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("PhaseSections") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("ProjectSections") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("TaskSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + + b.Navigation("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("PhaseSections"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.cs new file mode 100644 index 00000000..889ac9de --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251206064818_add phase section and task section.cs @@ -0,0 +1,138 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class addphasesectionandtasksection : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PhaseSection_ProjectPhases_PhaseId", + table: "PhaseSection"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSection_Projects_ProjectId", + table: "ProjectSection"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProjectSection", + table: "ProjectSection"); + + migrationBuilder.DropPrimaryKey( + name: "PK_PhaseSection", + table: "PhaseSection"); + + migrationBuilder.RenameTable( + name: "ProjectSection", + newName: "ProjectSections"); + + migrationBuilder.RenameTable( + name: "PhaseSection", + newName: "PhaseSections"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSection_ProjectId", + table: "ProjectSections", + newName: "IX_ProjectSections_ProjectId"); + + migrationBuilder.RenameIndex( + name: "IX_PhaseSection_PhaseId", + table: "PhaseSections", + newName: "IX_PhaseSections_PhaseId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProjectSections", + table: "ProjectSections", + column: "Id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_PhaseSections", + table: "PhaseSections", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_PhaseSections_ProjectPhases_PhaseId", + table: "PhaseSections", + column: "PhaseId", + principalTable: "ProjectPhases", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSections_Projects_ProjectId", + table: "ProjectSections", + column: "ProjectId", + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_PhaseSections_ProjectPhases_PhaseId", + table: "PhaseSections"); + + migrationBuilder.DropForeignKey( + name: "FK_ProjectSections_Projects_ProjectId", + table: "ProjectSections"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProjectSections", + table: "ProjectSections"); + + migrationBuilder.DropPrimaryKey( + name: "PK_PhaseSections", + table: "PhaseSections"); + + migrationBuilder.RenameTable( + name: "ProjectSections", + newName: "ProjectSection"); + + migrationBuilder.RenameTable( + name: "PhaseSections", + newName: "PhaseSection"); + + migrationBuilder.RenameIndex( + name: "IX_ProjectSections_ProjectId", + table: "ProjectSection", + newName: "IX_ProjectSection_ProjectId"); + + migrationBuilder.RenameIndex( + name: "IX_PhaseSections_PhaseId", + table: "PhaseSection", + newName: "IX_PhaseSection_PhaseId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProjectSection", + table: "ProjectSection", + column: "Id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_PhaseSection", + table: "PhaseSection", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_PhaseSection_ProjectPhases_PhaseId", + table: "PhaseSection", + column: "PhaseId", + principalTable: "ProjectPhases", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_ProjectSection_Projects_ProjectId", + table: "ProjectSection", + column: "ProjectId", + principalTable: "Projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.Designer.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.Designer.cs new file mode 100644 index 00000000..c7e4fc0a --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.Designer.cs @@ -0,0 +1,905 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + [Migration("20251207080830_RoleAndRolePermissionTablerenamed")] + partial class RoleAndRolePermissionTablerenamed + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CheckoutAgg.Entities.Checkout", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CheckoutEndDate") + .HasColumnType("datetime2"); + + b.Property("CheckoutStartDate") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeductionFromSalary") + .HasColumnType("float"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MandatoryHours") + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("MonthlySalaryDefined") + .HasColumnType("float"); + + b.Property("MonthlySalaryPay") + .HasColumnType("float"); + + b.Property("RemainingHours") + .HasColumnType("int"); + + b.Property("TotalDaysWorked") + .HasColumnType("int"); + + b.Property("TotalHoursWorked") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Checkouts", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Year") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("nvarchar(4)"); + + b.HasKey("Id"); + + b.ToTable("Holidays", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayItemAgg.HolidayItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("HolidayId") + .HasColumnType("bigint"); + + b.Property("HolidayYear") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("nvarchar(4)"); + + b.Property("Holidaydate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("HolidayId"); + + b.ToTable("Holidayitems", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("PhaseSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TaskSectionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskSectionId"); + + b.ToTable("TaskSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("PmRoles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RevokedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAt"); + + b.HasIndex("Token") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserRefreshTokens", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayItemAgg.HolidayItem", b => + { + b.HasOne("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", "Holidayss") + .WithMany("HolidayItems") + .HasForeignKey("HolidayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Holidayss"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("PhaseSections") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("ProjectSections") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("TaskSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("PmRolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", b => + { + b.Navigation("HolidayItems"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + + b.Navigation("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("PhaseSections"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.cs new file mode 100644 index 00000000..4b02748e --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/20251207080830_RoleAndRolePermissionTablerenamed.cs @@ -0,0 +1,109 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + /// + public partial class RoleAndRolePermissionTablerenamed : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RolePermissions"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Roles", + table: "Roles"); + + migrationBuilder.RenameTable( + name: "Roles", + newName: "PmRoles"); + + migrationBuilder.AddPrimaryKey( + name: "PK_PmRoles", + table: "PmRoles", + column: "Id"); + + + + migrationBuilder.CreateTable( + name: "PmRolePermissions", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Code = table.Column(type: "int", nullable: false), + RoleId = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PmRolePermissions", x => x.Id); + table.ForeignKey( + name: "FK_PmRolePermissions_PmRoles_RoleId", + column: x => x.RoleId, + principalTable: "PmRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + + + migrationBuilder.CreateIndex( + name: "IX_PmRolePermissions_RoleId", + table: "PmRolePermissions", + column: "RoleId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + + migrationBuilder.DropTable( + name: "PmRolePermissions"); + + + + migrationBuilder.DropPrimaryKey( + name: "PK_PmRoles", + table: "PmRoles"); + + migrationBuilder.RenameTable( + name: "PmRoles", + newName: "Roles"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Roles", + table: "Roles", + column: "Id"); + + migrationBuilder.CreateTable( + name: "RolePermissions", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "bigint", nullable: false), + Code = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RolePermissions", x => x.Id); + table.ForeignKey( + name: "FK_RolePermissions_Roles_RoleId", + column: x => x.RoleId, + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_RolePermissions_RoleId", + table: "RolePermissions", + column: "RoleId"); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs new file mode 100644 index 00000000..8e4c3871 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Migrations/AppDbContextModelSnapshot.cs @@ -0,0 +1,902 @@ +// +using System; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace GozareshgirProgramManager.Infrastructure.Migrations +{ + [DbContext(typeof(ProgramManagerDbContext))] + partial class AppDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CheckoutAgg.Entities.Checkout", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CheckoutEndDate") + .HasColumnType("datetime2"); + + b.Property("CheckoutStartDate") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeductionFromSalary") + .HasColumnType("float"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MandatoryHours") + .HasColumnType("int"); + + b.Property("Month") + .HasColumnType("int"); + + b.Property("MonthlySalaryDefined") + .HasColumnType("float"); + + b.Property("MonthlySalaryPay") + .HasColumnType("float"); + + b.Property("RemainingHours") + .HasColumnType("int"); + + b.Property("TotalDaysWorked") + .HasColumnType("int"); + + b.Property("TotalHoursWorked") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Checkouts", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Customers", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Year") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("nvarchar(4)"); + + b.HasKey("Id"); + + b.ToTable("Holidays", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayItemAgg.HolidayItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("HolidayId") + .HasColumnType("bigint"); + + b.Property("HolidayYear") + .IsRequired() + .HasMaxLength(4) + .HasColumnType("nvarchar(4)"); + + b.Property("Holidaydate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("HolidayId"); + + b.ToTable("Holidayitems", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("PhaseSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PlannedEndDate") + .HasColumnType("datetime2"); + + b.Property("PlannedStartDate") + .HasColumnType("datetime2"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Projects", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectPhases", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllocatedTime") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DueDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("HasAssignmentOverride") + .HasColumnType("bit"); + + b.Property("HasTimeOverride") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OrderIndex") + .HasColumnType("int"); + + b.Property("PhaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("PhaseId"); + + b.ToTable("ProjectTasks", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("CurrentAssignedUserId") + .HasColumnType("bigint"); + + b.Property("InitialDescription") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InitialEstimatedHours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OriginalAssignedUserId") + .HasColumnType("bigint"); + + b.Property("SkillId") + .HasColumnType("uniqueidentifier"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TaskId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SkillId"); + + b.HasIndex("TaskId"); + + b.ToTable("TaskSections", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("EndNotes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("TaskSectionActivities", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddedAt") + .HasColumnType("datetime2"); + + b.Property("AddedByUserId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Hours") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Reason") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TaskSectionId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TaskSectionId"); + + b.ToTable("TaskSectionAdditionalTimes", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("PmRoles", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("EndSettingDate") + .HasColumnType("datetime2"); + + b.Property("HolidayWorking") + .HasColumnType("bit"); + + b.Property("MonthlySalary") + .HasColumnType("float"); + + b.Property("StartSettingDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("SalaryPaymentSetting", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Skills", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RevokedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAt"); + + b.HasIndex("Token") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("UserRefreshTokens", (string)null); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayItemAgg.HolidayItem", b => + { + b.HasOne("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", "Holidayss") + .WithMany("HolidayItems") + .HasForeignKey("HolidayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Holidayss"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("PhaseSections") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("Phases") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project") + .WithMany("ProjectSections") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase") + .WithMany("Tasks") + .HasForeignKey("PhaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Phase"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill") + .WithMany("Sections") + .HasForeignKey("SkillId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task") + .WithMany("Sections") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Skill"); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section") + .WithMany("Activities") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b => + { + b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null) + .WithMany("AdditionalTimes") + .HasForeignKey("TaskSectionId"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("PmRolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("EndShiftOne") + .HasColumnType("time(0)"); + + b1.Property("EndShiftTwo") + .HasColumnType("time(0)"); + + b1.Property("HasRestTime") + .HasColumnType("bit"); + + b1.Property("HasShiftOne") + .HasColumnType("bit"); + + b1.Property("HasShiftTow") + .HasColumnType("bit"); + + b1.Property("IsActiveDay") + .HasColumnType("bit"); + + b1.Property("PersianDayOfWeek") + .HasColumnType("int"); + + b1.Property("RestTime") + .HasColumnType("time(0)"); + + b1.Property("SalaryPaymentSettingId") + .HasColumnType("bigint"); + + b1.Property("ShiftDurationInMinutes") + .HasColumnType("int"); + + b1.Property("StartShiftOne") + .HasColumnType("time(0)"); + + b1.Property("StartShiftTwo") + .HasColumnType("time(0)"); + + b1.HasKey("Id"); + + b1.HasIndex("SalaryPaymentSettingId"); + + b1.ToTable("WorkingHours", (string)null); + + b1.WithOwner("SalaryPaymentSetting") + .HasForeignKey("SalaryPaymentSettingId"); + + b1.Navigation("SalaryPaymentSetting"); + }); + + b.Navigation("WorkingHoursList"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("UserId"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("UserId"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b => + { + b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.HolidayAgg.Holiday", b => + { + b.Navigation("HolidayItems"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b => + { + b.Navigation("Phases"); + + b.Navigation("ProjectSections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b => + { + b.Navigation("PhaseSections"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b => + { + b.Navigation("Activities"); + + b.Navigation("AdditionalTimes"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b => + { + b.Navigation("Sections"); + }); + + modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs new file mode 100644 index 00000000..181e1779 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs @@ -0,0 +1,22 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Domain.HolidayAgg; +using GozareshgirProgramManager.Domain.HolidayItemAgg; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Context; + +public class GozareshgirDbContext : DbContext, IGozareshgirDbContext +{ + public GozareshgirDbContext(DbContextOptions options) : base(options) + { + } + + public DbSet HolidayItems { get; set; } = null!; + public DbSet Holidays { get; set; } = null!; + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfigurationsFromAssembly(typeof(GozareshgirDbContext).Assembly); + base.OnModelCreating(modelBuilder); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs new file mode 100644 index 00000000..2fc4854c --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs @@ -0,0 +1,61 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; + using GozareshgirProgramManager.Domain.CheckoutAgg.Entities; + using GozareshgirProgramManager.Domain.CustomerAgg; +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; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Context; + +public class ProgramManagerDbContext : DbContext, IProgramManagerDbContext +{ + public ProgramManagerDbContext(DbContextOptions options) : base(options) + { + } + + public DbSet Customers { get; set; } = null!; + public DbSet TaskSections { get; set; } = null!; + public DbSet ProjectSections { get; set; } = null!; + public DbSet PhaseSections { get; set; } = null!; + + // New Hierarchy entities + public DbSet Projects { get; set; } = null!; + public DbSet ProjectPhases { get; set; } = null!; + public DbSet ProjectTasks { get; set; } = null!; + + public DbSet TaskSectionActivities { get; set; } = null!; + public DbSet TaskSectionAdditionalTimes { get; set; } = null!; + + public DbSet Users { get; set; } = null!; + public DbSet RefreshTokens { get; set; } = null!; + + public DbSet Checkouts { get; set; } = null!; + public DbSet SalaryPaymentSettings { get; set; } = null!; + public DbSet Roles { get; set; } = null!; + + public DbSet Skills { get; set; } = null!; + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfigurationsFromAssembly(typeof(ProgramManagerDbContext).Assembly); + base.OnModelCreating(modelBuilder); + } + + public async Task SeedSkillsIfEmptyAsync() + { + if (!Skills.Any()) + { + Skills.AddRange( + new Skill("UI/UX Design"), + new Skill("Frontend"), + new Skill("Backend") + ); + await SaveChangesAsync(); + } + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/AdditionalTimeMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/AdditionalTimeMapping.cs new file mode 100644 index 00000000..6c73bc87 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/AdditionalTimeMapping.cs @@ -0,0 +1,23 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class AdditionalTimeMapping:IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("AdditionalTimes"); + + builder.HasKey(ts => ts.Id); + + builder.Property(ts => ts.Id) + .ValueGeneratedNever(); + + builder.Property(x => x.Reason).HasMaxLength(1000); + + builder.Property(x => x.Hours).HasTimeSpanConversion(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CheckoutMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CheckoutMapping.cs new file mode 100644 index 00000000..3c8d83f8 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CheckoutMapping.cs @@ -0,0 +1,19 @@ +using GozareshgirProgramManager.Domain.CheckoutAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class CheckoutMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Checkouts"); + builder.HasKey(s => s.Id); + + builder.Property(s => s.Id) + .ValueGeneratedNever(); + + builder.Property(x => x.FullName).HasMaxLength(100); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CustomerMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CustomerMapping.cs new file mode 100644 index 00000000..e40e9b14 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/CustomerMapping.cs @@ -0,0 +1,29 @@ +using GozareshgirProgramManager.Domain.CustomerAgg; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class CustomerMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Customers"); + + builder.HasKey(c => c.Id); + + builder.Property(c => c.Id) + .ValueGeneratedNever(); + + builder.Property(c => c.Name) + .IsRequired() + .HasMaxLength(200); + + builder.Property(c => c.Email) + .IsRequired() + .HasMaxLength(256); + + builder.Property(c => c.CreatedAt) + .IsRequired(); + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs new file mode 100644 index 00000000..42eff124 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayItemMapping.cs @@ -0,0 +1,20 @@ +using GozareshgirProgramManager.Domain.HolidayItemAgg; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class HolidayItemMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Holidayitems"); + builder.HasKey(x => x.Id); + + builder.Property(x => x.HolidayYear).HasMaxLength(4); + + builder.HasOne(x => x.Holidayss) + .WithMany(x => x.HolidayItems) + .HasForeignKey(x => x.HolidayId); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs new file mode 100644 index 00000000..3038d89a --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/HolidayMapping.cs @@ -0,0 +1,20 @@ +using GozareshgirProgramManager.Domain.HolidayAgg; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class HolidayMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Holidays"); + builder.HasKey(x => x.Id); + + builder.Property(x => x.Year).HasMaxLength(4); + + builder.HasMany(x => x.HolidayItems) + .WithOne(x => x.Holidayss) + .HasForeignKey(x => x.HolidayId); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs new file mode 100644 index 00000000..c1db7d49 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/PhaseSectionMapping.cs @@ -0,0 +1,21 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class PhaseSectionMapping:IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(ps => ps.Id); + + builder.Property(ps => ps.Id) + .ValueGeneratedOnAdd(); + + builder.HasOne(ps => ps.Phase) + .WithMany(p => p.PhaseSections) + .HasForeignKey(ps => ps.PhaseId) + .OnDelete(DeleteBehavior.Cascade); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectMapping.cs new file mode 100644 index 00000000..69a79750 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectMapping.cs @@ -0,0 +1,58 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class ProjectMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Projects"); + + builder.HasKey(p => p.Id); + + builder.Property(p => p.Id) + .ValueGeneratedNever(); + + builder.Property(p => p.Name) + .HasMaxLength(200) + .IsRequired(); + + builder.Property(p => p.Description) + .HasMaxLength(1000) + .IsRequired(false); + + builder.Property(p => p.CreationDate) + .IsRequired(); + + builder.Property(p => p.StartDate) + .IsRequired(false); + + builder.Property(p => p.EndDate) + .IsRequired(false); + + builder.Property(p => p.PlannedStartDate) + .IsRequired(false); + + builder.Property(p => p.PlannedEndDate) + .IsRequired(false); + + builder.Property(p => p.Status) + .HasConversion() + .HasMaxLength(50) + .IsRequired(); + + builder.Property(p => p.HasAssignmentOverride) + .IsRequired(); + + // One-to-many relationship with ProjectPhases + builder.HasMany(p => p.Phases) + .WithOne(ph => ph.Project) + .HasForeignKey(ph => ph.ProjectId) + .OnDelete(DeleteBehavior.Cascade); + + + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectPhaseMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectPhaseMapping.cs new file mode 100644 index 00000000..838b7f0e --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectPhaseMapping.cs @@ -0,0 +1,64 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class ProjectPhaseMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("ProjectPhases"); + + builder.HasKey(ph => ph.Id); + + builder.Property(ph => ph.Id) + .ValueGeneratedNever(); + + builder.Property(ph => ph.Name) + .HasMaxLength(200) + .IsRequired(); + + builder.Property(ph => ph.Description) + .HasMaxLength(1000) + .IsRequired(false); + + builder.Property(ph => ph.CreationDate) + .IsRequired(); + + builder.Property(ph => ph.ProjectId) + .IsRequired(); + + builder.Property(ph => ph.Status) + .HasConversion() + .HasMaxLength(50) + .IsRequired(); + + builder.Property(ph => ph.StartDate) + .IsRequired(false); + + builder.Property(ph => ph.EndDate) + .IsRequired(false); + + builder.Property(ph => ph.OrderIndex) + .IsRequired(); + + + builder.Property(ph => ph.HasAssignmentOverride) + .IsRequired(); + + // Relationship with Project + builder.HasOne(ph => ph.Project) + .WithMany(p => p.Phases) + .HasForeignKey(ph => ph.ProjectId) + .OnDelete(DeleteBehavior.Cascade); + + // One-to-many relationship with ProjectTasks + builder.HasMany(ph => ph.Tasks) + .WithOne(t => t.Phase) + .HasForeignKey(t => t.PhaseId) + .OnDelete(DeleteBehavior.Cascade); + + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs new file mode 100644 index 00000000..ebc8df44 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectSectionMapping.cs @@ -0,0 +1,20 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class ProjectSectionMapping:IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .ValueGeneratedNever(); + + builder.HasOne(x => x.Project) + .WithMany(x => x.ProjectSections) + .HasForeignKey(x => x.ProjectId) + .OnDelete(DeleteBehavior.Cascade); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectTaskMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectTaskMapping.cs new file mode 100644 index 00000000..705af3d6 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/ProjectTaskMapping.cs @@ -0,0 +1,79 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class ProjectTaskMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("ProjectTasks"); + + builder.HasKey(t => t.Id); + + builder.Property(t => t.Id) + .ValueGeneratedNever(); + + builder.Property(t => t.Name) + .HasMaxLength(200) + .IsRequired(); + + builder.Property(t => t.Description) + .HasMaxLength(1000) + .IsRequired(false); + + builder.Property(t => t.CreationDate) + .IsRequired(); + + builder.Property(t => t.PhaseId) + .IsRequired(); + + builder.Property(t => t.Status) + .HasConversion() + .HasMaxLength(50) + .IsRequired(); + + builder.Property(t => t.Priority) + .HasConversion() + .HasMaxLength(50) + .IsRequired(); + + builder.Property(t => t.StartDate) + .IsRequired(false); + + builder.Property(t => t.EndDate) + .IsRequired(false); + + builder.Property(t => t.DueDate) + .IsRequired(false); + + builder.Property(t => t.OrderIndex) + .IsRequired(); + + builder.Property(t => t.AllocatedTime) + .HasTimeSpanConversion() + .IsRequired(false); + + builder.Property(t => t.HasTimeOverride) + .IsRequired(); + + builder.Property(t => t.HasAssignmentOverride) + .IsRequired(); + + // Relationship with ProjectPhase + builder.HasOne(t => t.Phase) + .WithMany(ph => ph.Tasks) + .HasForeignKey(t => t.PhaseId) + .OnDelete(DeleteBehavior.Cascade); + + // One-to-many relationship with ProjectSections + builder.HasMany(t => t.Sections) + .WithOne(s => s.Task) + .HasForeignKey(s => s.TaskId) + .OnDelete(DeleteBehavior.Cascade); + + } +} 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/SalaryPaymentSettingMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/SalaryPaymentSettingMapping.cs new file mode 100644 index 00000000..f6d69733 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/SalaryPaymentSettingMapping.cs @@ -0,0 +1,50 @@ +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class SalaryPaymentSettingMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("SalaryPaymentSetting"); + builder.HasKey(x => x.Id); + + builder.Property(x => x.StartSettingDate).IsRequired(false); + builder.Property(x => x.EndSettingDate).IsRequired(false); + + builder.OwnsMany(x => x.WorkingHoursList, navigationBuilder => + { + navigationBuilder.HasKey(x => x.Id); + navigationBuilder.ToTable("WorkingHours"); + navigationBuilder.WithOwner(x => x.SalaryPaymentSetting); + + navigationBuilder.Property(x => x.StartShiftOne) + .HasColumnType("time(0)") + .IsRequired(true); + + navigationBuilder.Property(x => x.EndShiftOne) + .HasColumnType("time(0)") + .IsRequired(true); + + navigationBuilder.Property(x => x.StartShiftTwo) + .HasColumnType("time(0)") + .IsRequired(true); + + navigationBuilder.Property(x => x.EndShiftTwo) + .HasColumnType("time(0)") + .IsRequired(true); + + navigationBuilder.Property(x => x.RestTime) + .HasColumnType("time(0)") + .IsRequired(true); + + navigationBuilder + .Property(x => x.PersianDayOfWeek) + .HasConversion(); + + }); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/SkillMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/SkillMapping.cs new file mode 100644 index 00000000..b142abe8 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/SkillMapping.cs @@ -0,0 +1,27 @@ +using GozareshgirProgramManager.Domain.SkillAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class SkillMapping:IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Skills"); + + builder.HasKey(s => s.Id); + + builder.Property(s => s.Id) + .ValueGeneratedNever(); + + builder.Property(s => s.Name) + .IsRequired() + .HasMaxLength(200); + + builder.HasMany(x=>x.Sections) + .WithOne(x => x.Skill) + .HasForeignKey(f=>f.SkillId) + .OnDelete(DeleteBehavior.Cascade); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionActivityMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionActivityMapping.cs new file mode 100644 index 00000000..84f4227e --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionActivityMapping.cs @@ -0,0 +1,53 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class TaskSectionActivityMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("TaskSectionActivities"); + + builder.HasKey(a => a.Id); + + builder.Property(a => a.Id) + .ValueGeneratedNever(); + + builder.Property(a => a.SectionId) + .IsRequired(); + + builder.Property(a => a.UserId) + .IsRequired(); + + builder.Property(a => a.StartDate) + .IsRequired(); + + builder.Property(a => a.EndDate) + .IsRequired(false); + + builder.Property(a => a.Notes) + .HasMaxLength(1000) + .IsRequired(false); + + builder.Property(a => a.EndNotes) + .HasMaxLength(1000) + .IsRequired(false); + + builder.Property(a => a.IsActive) + .IsRequired(); + + builder.Property(a => a.CreationDate) + .IsRequired(); + + // Relationship with TaskSection + builder.HasOne(a => a.Section) + .WithMany(s => s.Activities) + .HasForeignKey(a => a.SectionId) + .OnDelete(DeleteBehavior.Cascade); + + // Ignore domain events + builder.Ignore(a => a.DomainEvents); + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionAdditionalTimeMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionAdditionalTimeMapping.cs new file mode 100644 index 00000000..e6789d94 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionAdditionalTimeMapping.cs @@ -0,0 +1,39 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class TaskSectionAdditionalTimeMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("TaskSectionAdditionalTimes"); + + builder.HasKey(at => at.Id); + + builder.Property(at => at.Id) + .ValueGeneratedNever(); + + builder.Property(at => at.Hours) + .HasTimeSpanConversion() + .IsRequired(); + + builder.Property(at => at.Reason) + .HasMaxLength(500) + .IsRequired(false); + + builder.Property(at => at.AddedByUserId) + .IsRequired(false); + + builder.Property(at => at.AddedAt) + .IsRequired(); + + builder.Property(at => at.CreationDate) + .IsRequired(); + + // Ignore domain events + builder.Ignore(at => at.DomainEvents); + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionMapping.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionMapping.cs new file mode 100644 index 00000000..836580f0 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/TaskSectionMapping.cs @@ -0,0 +1,53 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Mappings; + +public class TaskSectionMapping : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("TaskSections"); + + builder.HasKey(ts => ts.Id); + + builder.Property(ts => ts.Id) + .ValueGeneratedNever(); + + builder.Property(ts => ts.TaskId) + .IsRequired(); + + + builder.Property(ts => ts.InitialEstimatedHours) + .HasTimeSpanConversion(); + + builder.Property(ts => ts.Status) + .HasConversion() + .HasMaxLength(50) + .IsRequired(); + + builder.Property(x=>x.InitialDescription) + .HasMaxLength(500) + .IsRequired(false); + + builder.Property(ts => ts.CurrentAssignedUserId); + + // Navigation to ProjectTask (Task level) + builder.HasOne(ts => ts.Task) + .WithMany(t => t.Sections) + .HasForeignKey(ts => ts.TaskId) + .OnDelete(DeleteBehavior.Cascade); + + builder.HasMany(ts => ts.Activities) + .WithOne(a => a.Section) + .HasForeignKey(a => a.SectionId) + .OnDelete(DeleteBehavior.Cascade); + + builder.HasOne(x => x.Skill) + .WithMany(y => y.Sections).HasForeignKey(y => y.SkillId) + .OnDelete(DeleteBehavior.Cascade); + } +} 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/CheckoutRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CheckoutRepository.cs new file mode 100644 index 00000000..a34fcce7 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CheckoutRepository.cs @@ -0,0 +1,22 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CheckoutAgg.Entities; +using GozareshgirProgramManager.Domain.CheckoutAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class CheckoutRepository : RepositoryBase, ICheckoutRepository +{ + private readonly ProgramManagerDbContext _context; + public CheckoutRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public async Task> GetCheckoutListByIds(List checkoutIds) + { + return await _context.Checkouts.Where(x => checkoutIds.Contains(x.Id)).ToListAsync(); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CustomerRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CustomerRepository.cs new file mode 100644 index 00000000..da0d9037 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/CustomerRepository.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore; +using GozareshgirProgramManager.Domain.CustomerAgg; +using GozareshgirProgramManager.Domain.CustomerAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class CustomerRepository : ICustomerRepository +{ + private readonly ProgramManagerDbContext _context; + + public CustomerRepository(ProgramManagerDbContext context) + { + _context = context; + } + + public async Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default) + { + return await _context.Customers + .FirstOrDefaultAsync(c => c.Id == id, cancellationToken); + } + + public async Task AddAsync(Customer customer, CancellationToken cancellationToken = default) + { + await _context.Customers.AddAsync(customer, cancellationToken); + } + + public void Update(Customer customer) + { + _context.Customers.Update(customer); + } + + public void Delete(Customer customer) + { + _context.Customers.Remove(customer); + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/OrderRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/OrderRepository.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/PhaseSectionRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/PhaseSectionRepository.cs new file mode 100644 index 00000000..c582dffd --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/PhaseSectionRepository.cs @@ -0,0 +1,18 @@ +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; +public class PhaseSectionRepository : RepositoryBase, IPhaseSectionRepository +{ + private readonly ProgramManagerDbContext _programManagerDbContext; + public PhaseSectionRepository(ProgramManagerDbContext context) : base(context) + { + _programManagerDbContext = context; + } + +} + + + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProductRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProductRepository.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectPhaseRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectPhaseRepository.cs new file mode 100644 index 00000000..81306c82 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectPhaseRepository.cs @@ -0,0 +1,60 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class ProjectPhaseRepository : RepositoryBase, IProjectPhaseRepository +{ + private readonly ProgramManagerDbContext _context; + + public ProjectPhaseRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public Task GetWithTasksAsync(Guid phaseId) + { + return _context.ProjectPhases + .Include(p => p.Tasks) + .ThenInclude(t => t.Sections) + .ThenInclude(s => s.Skill) + .Include(p => p.Tasks) + .ThenInclude(t => t.Sections) + .ThenInclude(s => s.Activities) + .Include(p => p.Tasks) + .ThenInclude(t => t.Sections) + .ThenInclude(s => s.AdditionalTimes) + .FirstOrDefaultAsync(p => p.Id == phaseId); + } + + public Task> GetByProjectIdAsync(Guid projectId) + { + return _context.ProjectPhases + .Where(p => p.ProjectId == projectId) + .OrderBy(p => p.OrderIndex) + .ToListAsync(); + } + + public Task> GetPhasesWithAssignmentOverridesAsync() + { + return _context.ProjectPhases + .Where(p => p.HasAssignmentOverride) + .ToListAsync(); + } + + public Task> GetByStatusAsync(PhaseStatus status) + { + return _context.ProjectPhases + .Where(p => p.Status == status) + .ToListAsync(); + } + + public void Remove(ProjectPhase phase) + { + _context.ProjectPhases.Remove(phase); + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectRepository.cs new file mode 100644 index 00000000..21afca93 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectRepository.cs @@ -0,0 +1,70 @@ + +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class ProjectRepository : RepositoryBase, IProjectRepository +{ + private readonly ProgramManagerDbContext _context; + + public ProjectRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public Task GetWithFullHierarchyAsync(Guid projectId) + { + return _context.Projects + .Include(p => p.Phases) + .ThenInclude(ph => ph.Tasks) + .ThenInclude(t => t.Sections) + .ThenInclude(s => s.Skill) + .Include(p => p.Phases) + .ThenInclude(ph => ph.Tasks) + .ThenInclude(t => t.Sections) + .ThenInclude(s => s.Activities) + .Include(p => p.Phases) + .ThenInclude(ph => ph.Tasks) + .ThenInclude(t => t.Sections) + .ThenInclude(s => s.AdditionalTimes) + .FirstOrDefaultAsync(p => p.Id == projectId); + } + + public Task GetWithPhasesAsync(Guid projectId) + { + return _context.Projects + .Include(p => p.Phases) + .FirstOrDefaultAsync(p => p.Id == projectId); + } + + public Task> GetByStatusAsync(ProjectStatus status) + { + return _context.Projects + .Where(p => p.Status == status) + .ToListAsync(); + } + + public Task> GetProjectsWithAssignmentOverridesAsync() + { + return _context.Projects + .Where(p => p.HasAssignmentOverride) + .ToListAsync(); + } + + public Task> SearchByNameAsync(string searchTerm) + { + return _context.Projects + .Where(p => p.Name.Contains(searchTerm)) + .ToListAsync(); + } + + public void Remove(Project project) + { + _context.Projects.Remove(project); + } +} diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectSectionRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectSectionRepository.cs new file mode 100644 index 00000000..d2b115db --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectSectionRepository.cs @@ -0,0 +1,17 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class ProjectSectionRepository : RepositoryBase, IProjectSectionRepository +{ + private readonly ProgramManagerDbContext _programManagerDbContext; + public ProjectSectionRepository(ProgramManagerDbContext context) : base(context) + { + _programManagerDbContext = context; + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectTaskRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectTaskRepository.cs new file mode 100644 index 00000000..4e09e8cb --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/ProjectTaskRepository.cs @@ -0,0 +1,79 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using TaskStatus = GozareshgirProgramManager.Domain.ProjectAgg.Enums.TaskStatus; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class ProjectTaskRepository : RepositoryBase, IProjectTaskRepository +{ + private readonly ProgramManagerDbContext _context; + + public ProjectTaskRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public Task GetWithSectionsAsync(Guid taskId) + { + return _context.ProjectTasks + .Include(t => t.Sections) + .ThenInclude(s => s.Skill) + .Include(t => t.Sections) + .ThenInclude(s => s.Activities) + .Include(t => t.Sections) + .ThenInclude(s => s.AdditionalTimes) + .FirstOrDefaultAsync(t => t.Id == taskId); + } + + public Task> GetByPhaseIdAsync(Guid phaseId) + { + return _context.ProjectTasks + .Where(t => t.PhaseId == phaseId) + .OrderBy(t => t.OrderIndex) + .ToListAsync(); + } + + public Task> GetTasksWithTimeOverridesAsync() + { + return _context.ProjectTasks + .Where(t => t.HasTimeOverride) + .ToListAsync(); + } + + public Task> GetTasksWithAssignmentOverridesAsync() + { + return _context.ProjectTasks + .Where(t => t.HasAssignmentOverride) + .ToListAsync(); + } + + public Task> GetByStatusAsync(TaskStatus status) + { + return _context.ProjectTasks + .Where(t => t.Status == status) + .ToListAsync(); + } + + public Task> GetByPriorityAsync(TaskPriority priority) + { + return _context.ProjectTasks + .Where(t => t.Priority == priority) + .ToListAsync(); + } + + public Task> GetAssignedToUserAsync(long userId) + { + return _context.ProjectTasks + .Where(t => t.Sections.Any(s => s.CurrentAssignedUserId == userId)) + .ToListAsync(); + } + + public void Remove(ProjectTask task) + { + _context.ProjectTasks.Remove(task); + } +} 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 new file mode 100644 index 00000000..a3d43ccd --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs @@ -0,0 +1,60 @@ +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; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class SalaryPaymentSettingRepository : RepositoryBase, ISalaryPaymentSettingRepository +{ + private readonly ProgramManagerDbContext _context; + public SalaryPaymentSettingRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + + public async Task GetSalarySettingByUserId(long userId) + { + return await _context.SalaryPaymentSettings.FirstOrDefaultAsync(x => x.UserId == userId); + } + + + public async Task> GetAllSettings(List userIdList) + { + _context.SalaryPaymentSettings.AsNoTracking(); + var query = await _context.SalaryPaymentSettings.Where(s=> userIdList.Contains(s.UserId)) + .Join(_context.Users.AsNoTracking(), + setting => setting.UserId, + 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(); + + return query; + + } + + public void RemoveRangeSalarySettings(List removedItems) + { + _context.SalaryPaymentSettings.RemoveRange(removedItems); + + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SkillRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SkillRepository.cs new file mode 100644 index 00000000..935bfda3 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SkillRepository.cs @@ -0,0 +1,16 @@ +using GozareshgirProgramManager.Domain.SkillAgg.Entities; +using GozareshgirProgramManager.Domain.SkillAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class SkillRepository:RepositoryBase, ISkillRepository +{ + private readonly ProgramManagerDbContext _context; + public SkillRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionActivityRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionActivityRepository.cs new file mode 100644 index 00000000..4ae98bf7 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionActivityRepository.cs @@ -0,0 +1,83 @@ +using GozareshgirProgramManager.Application.Modules.Projects.DTOs; +using GozareshgirProgramManager.Application.Modules.Projects.Extensions; +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class TaskSectionActivityRepository : RepositoryBase, ITaskSectionActivityRepository +{ + private readonly ProgramManagerDbContext _programManagerDbContext; + + public TaskSectionActivityRepository(ProgramManagerDbContext programManagerDbContext) : base(programManagerDbContext) + { + _programManagerDbContext = programManagerDbContext; + } + + public async Task> GetBySectionIdAsync(Guid sectionId) + { + return await _programManagerDbContext.TaskSectionActivities + .Where(a => a.SectionId == sectionId).ToListAsync(); + } + + public async Task> GetByUserIdAsync(long userId) + { + return await _programManagerDbContext.TaskSectionActivities + .Where(x => x.UserId == userId).ToListAsync(); + } + + public async Task> GetActiveByUserAsync(long userId) + { + return await _programManagerDbContext.TaskSectionActivities + .Where(x => x.UserId == userId && x.IsActive) + .ToListAsync(); + } + + public async Task> GetByDateRangeAsync(DateTime from, DateTime to) + { + return await _programManagerDbContext.TaskSectionActivities + .Where(x => x.EndDate >= from && x.StartDate <= to).ToListAsync(); + } + + public async Task> GetByDateRangeUserIdAsync(DateTime from, DateTime to, long userId) + { + return await _programManagerDbContext.TaskSectionActivities + .Where(x => x.EndDate >= from && x.StartDate <= to && x.UserId == userId).ToListAsync(); + } + + public async Task GetTotalTimeSpentByUserInRangeAsync(long userId, DateTime from, DateTime to) + { + var data = await GetByDateRangeUserIdAsync(from, to, userId); + + return data.Aggregate(TimeSpan.Zero, (total, activity) => + { + var adjustedStart = activity.StartDate < from ? from : activity.StartDate; + var adjustedEnd = activity.EndDate > to ? to : (activity.EndDate ?? to); + return total.Add(adjustedEnd - adjustedStart); + }); + } + + public async Task> GetTotalTimeSpentPerUserInRangeAsync(DateTime from, + DateTime to) + { + var data = await GetByDateRangeAsync(from, to); + var result = data + .GroupBy(x => x.UserId) + .Select(group => + { + var totalTime = group.Aggregate(TimeSpan.Zero, (total, activity) => + { + var adjustedStart = activity.StartDate < from ? from : activity.StartDate; + var adjustedEnd = activity.EndDate > to ? to : (activity.EndDate ?? to); + return total.Add(adjustedEnd - adjustedStart); + }); + return (totalTime, group.Key); + }) + .ToList(); + + return result; + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs new file mode 100644 index 00000000..80564915 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs @@ -0,0 +1,31 @@ +using GozareshgirProgramManager.Domain.ProjectAgg.Entities; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Infrastructure.Persistence._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Repositories; + +public class TaskSectionRepository:RepositoryBase,ITaskSectionRepository +{ + private readonly ProgramManagerDbContext _context; + public TaskSectionRepository(ProgramManagerDbContext context) : base(context) + { + _context = context; + } + + public async Task GetByIdWithActivitiesAsync(Guid id, CancellationToken cancellationToken = default) + { + return await _context.TaskSections + .Include(x => x.Activities) + .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); + } + + public async Task GetByIdWithFullDataAsync(Guid id, CancellationToken cancellationToken = default) + { + return await _context.TaskSections + .Include(x => x.Activities) + .Include(x => x.AdditionalTimes) + .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); + } +} \ No newline at end of file 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/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/DataSeeder.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/DataSeeder.cs new file mode 100644 index 00000000..5afe7e82 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/DataSeeder.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using GozareshgirProgramManager.Domain.SkillAgg.Entities; +using System.Linq; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Seed +{ + public class DataSeeder : IDataSeeder + { + private readonly ProgramManagerDbContext _dbContext; + public DataSeeder(ProgramManagerDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task SeedAllAsync() + { + await SeedSkillsIfEmptyAsync(); + // در آینده متدهای Seed دیگر را اینجا فراخوانی کنید + } + + private async Task SeedSkillsIfEmptyAsync() + { + if (!_dbContext.Skills.Any()) + { + _dbContext.Skills.AddRange( + new Skill("UI/UX Design"), + new Skill("Frontend"), + new Skill("Backend") + ); + await _dbContext.SaveChangesAsync(); + } + } + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/IDataSeeder.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/IDataSeeder.cs new file mode 100644 index 00000000..2db95adc --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Seed/IDataSeeder.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace GozareshgirProgramManager.Infrastructure.Persistence.Seed +{ + public interface IDataSeeder + { + Task SeedAllAsync(); + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/UnitOfWork.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/UnitOfWork.cs new file mode 100644 index 00000000..2a071185 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/UnitOfWork.cs @@ -0,0 +1,53 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using MediatR; +using Microsoft.Identity.Client; +using GozareshgirProgramManager.Application._Common.Models; + +namespace GozareshgirProgramManager.Infrastructure.Persistence; + +public class UnitOfWork : IUnitOfWork +{ + private readonly ProgramManagerDbContext _context; + private readonly IPublisher _publisher; + + public UnitOfWork(ProgramManagerDbContext context, IPublisher publisher) + { + _context = context; + _publisher = publisher; + } + + public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + // Publish Domain Events before saving + await PublishDomainEvents(cancellationToken); + + return await _context.SaveChangesAsync(cancellationToken); + } + + private async Task PublishDomainEvents(CancellationToken cancellationToken) + { + var domainEntities = _context.ChangeTracker + .Entries>() + .Where(x => x.Entity.DomainEvents.Any()) + .ToList(); + + var domainEvents = domainEntities + .SelectMany(x => x.Entity.DomainEvents) + .ToList(); + + domainEntities.ForEach(entity => entity.Entity.ClearDomainEvents()); + + foreach (var domainEvent in domainEvents) + { + var notificationType = typeof(DomainEventNotification<>).MakeGenericType(domainEvent.GetType()); + var notification = Activator.CreateInstance(notificationType, domainEvent); + + if (notification != null) + { + await _publisher.Publish(notification, cancellationToken); + } + } + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/PropertyBuilderExtensions.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/PropertyBuilderExtensions.cs new file mode 100644 index 00000000..672d399e --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/PropertyBuilderExtensions.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace GozareshgirProgramManager.Infrastructure.Persistence._Common; + +public static class PropertyBuilderExtensions +{ + public static PropertyBuilder HasTimeSpanConversion(this PropertyBuilder builder) + { + return builder.HasConversion( + v => v == TimeSpan.Zero ? "" : v.ToString(), + v => string.IsNullOrWhiteSpace(v) ? TimeSpan.Zero : TimeSpan.Parse(v) + ).HasMaxLength(30); + } + public static PropertyBuilder HasTimeSpanConversion(this PropertyBuilder builder) + { + return builder.HasConversion( + v =>v==null || v == TimeSpan.Zero ? "" : v.ToString(), + v => string.IsNullOrWhiteSpace(v) ? TimeSpan.Zero : TimeSpan.Parse(v) + ).HasMaxLength(30); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/RepositoryBase.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/RepositoryBase.cs new file mode 100644 index 00000000..def0cf17 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/_Common/RepositoryBase.cs @@ -0,0 +1,70 @@ +using System.Linq.Expressions; +using GozareshgirProgramManager.Domain._Common; +using Microsoft.EntityFrameworkCore; + +namespace GozareshgirProgramManager.Infrastructure.Persistence._Common; + +public class RepositoryBase : IRepository where T : class +{ + private readonly DbContext _context; + + public RepositoryBase(DbContext context) + { + _context = context; + } + + public void AddRange(IEnumerable entities) + { + _context.AddRange(entities); + } + public void Create(T entity) + { + _context.Add(entity); + } + + public async Task CreateAsync(T entity) + { + await _context.AddAsync(entity); + } + + + public bool ExistsIgnoreQueryFilter(Expression> expression) + { + return _context.Set().IgnoreQueryFilters().Any(expression); + } + + public bool Exists(Expression> expression) + { + return _context.Set().Any(expression); + } + + public T Get(TKey id) + { + return _context.Find(id); + } + + public async Task GetByIdAsync(TKey id) + { + return await _context.Set().FindAsync(id); + } + + public List Get() + { + return _context.Set().ToList(); + } + + public IQueryable GetQueryable() + { + return _context.Set().AsQueryable(); + } + + public void Remove(T entity) + { + _context.Set().Remove(entity); + } + + public void RemoveRange(IEnumerable entities) + { + _context.Set().RemoveRange(entities); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs new file mode 100644 index 00000000..ec70492e --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs @@ -0,0 +1,215 @@ +using System.Security.Claims; +using GozareshgirProgramManager.Application._Common.Interfaces; +using Microsoft.AspNetCore.Http; + +namespace GozareshgirProgramManager.Infrastructure.Services.Authentication; + +/// +/// سرویس کمکی برای کار با JWT و HttpContext +/// این کلاس فقط با توکن و Context کار می‌کند و هیچ عملیات دیتابیسی ندارد +/// +public class AuthHelper : IAuthHelper +{ + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly JwtTokenGenerator _jwtTokenGenerator; + + public AuthHelper( + IHttpContextAccessor httpContextAccessor, + JwtTokenGenerator jwtTokenGenerator) + { + _httpContextAccessor = httpContextAccessor; + _jwtTokenGenerator = jwtTokenGenerator; + } + + public LoginSession SignIn(long userId, string userName, string fullName, long accountId, List roles) + { + + // 1. تولید Access Token + var accessToken = GenerateAccessToken(userId, userName, fullName, accountId, roles); + var accessTokenExpiration = DateTime.Now.AddMinutes(30); + + // 2. تولید Refresh Token + var refreshToken = GenerateRefreshToken(); + var refreshTokenExpiration = GetRefreshTokenExpiration(); + + // 3. ذخیره Refresh Token در Cookie + _httpContextAccessor.HttpContext?.Response.Cookies.Append("rf-token", refreshToken, new CookieOptions + { + HttpOnly = true, + Secure = true, + SameSite = SameSiteMode.Lax, + Expires = refreshTokenExpiration + }); + + // 4. تنظیم Authorization Header (اختیاری - معمولاً کلاینت خودش این کار را می‌کند) + _httpContextAccessor.HttpContext?.Response.Headers.Append("Authorization", $"Bearer {accessToken}"); + + return new LoginSession + { + AccessToken = accessToken, + RefreshToken = refreshToken, + RefreshTokenExpiration = refreshTokenExpiration, + AccessTokenExpiration = accessTokenExpiration + }; + } + + /// + /// تولید Access Token + /// + public string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles) + { + return _jwtTokenGenerator.GenerateAccessToken(userId, userName, fullName, accountId, roles); + } + + /// + /// تولید Refresh Token + /// + public string GenerateRefreshToken() + { + return _jwtTokenGenerator.GenerateRefreshToken(); + } + + /// + /// دریافت تاریخ انقضای Refresh Token + /// + public DateTime GetRefreshTokenExpiration() + { + return _jwtTokenGenerator.GetRefreshTokenExpiration(); + } + + /// + /// اعتبارسنجی توکن و استخراج Claims + /// + public ClaimsPrincipal? ValidateToken(string token) + { + return _jwtTokenGenerator.ValidateToken(token); + } + + /// + /// اعتبارسنجی توکن منقضی شده (بدون چک زمان) + /// + public ClaimsPrincipal? ValidateExpiredToken(string token) + { + return _jwtTokenGenerator.ValidateExpiredToken(token); + } + + /// + /// استخراج UserId از توکن (حتی اگر منقضی شده باشد) + /// + public long? GetUserIdFromToken(string token) + { + try + { + var principal = _jwtTokenGenerator.ValidateExpiredToken(token); + if (principal == null) return null; + + var userIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value; + return long.TryParse(userIdClaim, out var userId) ? userId : null; + } + catch + { + return null; + } + } + + /// + /// دریافت اطلاعات IP کاربر جاری + /// + public string? GetClientIpAddress() + { + return _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString(); + } + + /// + /// دریافت User Agent کاربر جاری + /// + public string? GetUserAgent() + { + return _httpContextAccessor.HttpContext?.Request.Headers["User-Agent"].ToString(); + } + + /// + /// دریافت Refresh Token از Header + /// + public string? GetRefreshTokenFromCookie() + { + return _httpContextAccessor.HttpContext?.Request.Cookies["rf-token"]; + } + + /// + /// بررسی احراز هویت کاربر جاری + /// + public bool IsAuthenticated() + { + return _httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false; + } + + /// + /// دریافت شناسه کاربر جاری از Claims + /// + public long? GetCurrentUserId() + { + var userIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + return long.TryParse(userIdClaim, out var userId) ? userId : null; + } + + /// + /// دریافت نام کاربری جاری از Claims + /// + public string? GetCurrentUserName() + { + return _httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.Name)?.Value; + } + + /// + /// دریافت نام کامل کاربر جاری از Claims + /// + public string? GetCurrentFullName() + { + return _httpContextAccessor.HttpContext?.User?.FindFirst("FullName")?.Value; + } + + /// + /// دریافت AccountId کاربر جاری از Claims + /// + public long? GetCurrentAccountId() + { + var accountIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst("AccountId")?.Value; + return long.TryParse(accountIdClaim, out var accountId) ? accountId : null; + } + + /// + /// دریافت نقش‌های کاربر جاری از Claims + /// + public List GetCurrentUserRoles() + { + var roles = _httpContextAccessor.HttpContext?.User?.FindAll(ClaimTypes.Role) + .Select(c => c.Value) + .ToList(); + + return roles ?? new List(); + } + + /// + /// بررسی دسترسی کاربر به نقش خاص + /// + public bool HasRole(string roleName) + { + return _httpContextAccessor.HttpContext?.User?.IsInRole(roleName) ?? false; + } + + /// + /// بررسی دسترسی کاربر به یکی از نقش‌ها + /// + public bool HasAnyRole(params string[] roleNames) + { + return roleNames.Any(HasRole); + } + + public void SignOut() + { + _httpContextAccessor.HttpContext?.Response.Cookies.Delete("rf-token"); + _httpContextAccessor.HttpContext?.Response.Headers.Remove("Authorization"); + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtSettings.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtSettings.cs new file mode 100644 index 00000000..97d0b849 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtSettings.cs @@ -0,0 +1,14 @@ +namespace GozareshgirProgramManager.Infrastructure.Services.Authentication; +/// +/// تنظیمات JWT +/// +public class JwtSettings +{ + public int RefreshTokenExpirationDays { get; set; } = 7; + public int AccessTokenExpirationMinutes { get; set; } = 30; + public string Audience { get; set; } = string.Empty; + public string Issuer { get; set; } = string.Empty; + public string SecretKey { get; set; } = string.Empty; +} + + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtTokenGenerator.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtTokenGenerator.cs new file mode 100644 index 00000000..2b15bd15 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/JwtTokenGenerator.cs @@ -0,0 +1,153 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace GozareshgirProgramManager.Infrastructure.Services.Authentication; + +/// +/// سرویس تولید توکن JWT +/// +public class JwtTokenGenerator +{ + private readonly JwtSettings _jwtSettings; + + public JwtTokenGenerator(IOptions jwtSettings) + { + _jwtSettings = jwtSettings.Value; + } + + /// + /// تولید Access Token + /// + public string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles) + { + var claims = new List + { + new(ClaimTypes.NameIdentifier, userId.ToString()), + new(ClaimTypes.Name, userName), + new("FullName", fullName), + new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) + }; + + if (accountId.HasValue) + { + claims.Add(new Claim("AccountId", accountId.Value.ToString())); + } + + // افزودن نقش‌ها به Claims + claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role))); + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey)); + var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + var expires = DateTime.Now.AddMinutes(_jwtSettings.AccessTokenExpirationMinutes); + + var token = new JwtSecurityToken( + issuer: _jwtSettings.Issuer, + audience: _jwtSettings.Audience, + claims: claims, + expires: expires, + signingCredentials: credentials + ); + + return new JwtSecurityTokenHandler().WriteToken(token); + } + + /// + /// تولید Refresh Token + /// + public string GenerateRefreshToken() + { + var randomNumber = new byte[64]; + using var rng = RandomNumberGenerator.Create(); + rng.GetBytes(randomNumber); + return Convert.ToBase64String(randomNumber); + } + + /// + /// اعتبارسنجی و استخراج اطلاعات از توکن + /// + public ClaimsPrincipal? ValidateToken(string token) + { + try + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.UTF8.GetBytes(_jwtSettings.SecretKey); + + var validationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateIssuer = true, + ValidIssuer = _jwtSettings.Issuer, + ValidateAudience = true, + ValidAudience = _jwtSettings.Audience, + ValidateLifetime = true, + ClockSkew = TimeSpan.Zero + }; + + var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken); + + if (validatedToken is not JwtSecurityToken jwtToken || + !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) + { + return null; + } + + return principal; + } + catch + { + return null; + } + } + + /// + /// اعتبارسنجی توکن بدون چک کردن زمان انقضا (برای استخراج اطلاعات از توکن منقضی شده) + /// + public ClaimsPrincipal? ValidateExpiredToken(string token) + { + try + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.UTF8.GetBytes(_jwtSettings.SecretKey); + + var validationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateIssuer = true, + ValidIssuer = _jwtSettings.Issuer, + ValidateAudience = true, + ValidAudience = _jwtSettings.Audience, + ValidateLifetime = false, // توکن منقضی شده هم قبول می‌شود + ClockSkew = TimeSpan.Zero + }; + + var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken); + + if (validatedToken is not JwtSecurityToken jwtToken || + !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) + { + return null; + } + + return principal; + } + catch + { + return null; + } + } + + /// + /// دریافت تاریخ انقضای Refresh Token + /// + public DateTime GetRefreshTokenExpiration() + { + return DateTime.Now.AddDays(_jwtSettings.RefreshTokenExpirationDays); + } +} + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/CacheService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/CacheService.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/DateTimeService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/DateTimeService.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/EmailService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/EmailService.cs new file mode 100644 index 00000000..e69de29b diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileService.cs new file mode 100644 index 00000000..e69de29b diff --git a/Query.Bootstrapper/Query.Bootstrapper.csproj b/Query.Bootstrapper/Query.Bootstrapper.csproj index 2a4ad0a3..dfbcb641 100644 --- a/Query.Bootstrapper/Query.Bootstrapper.csproj +++ b/Query.Bootstrapper/Query.Bootstrapper.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/Query/Query.csproj b/Query/Query.csproj index 38ac1440..e3f95f0d 100644 --- a/Query/Query.csproj +++ b/Query/Query.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/ServiceHost/Areas/Admin/Controllers/AuthController.cs b/ServiceHost/Areas/Admin/Controllers/AuthController.cs new file mode 100644 index 00000000..cac9318f --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/AuthController.cs @@ -0,0 +1,143 @@ +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; + +/// +/// کنترلر احراز هویت +/// +[Route("api/[controller]")] +[ApiController] +public class AuthController :AdminBaseController +{ + 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/CheckoutController.cs b/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs new file mode 100644 index 00000000..69128d3a --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs @@ -0,0 +1,93 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Checkouts.Commands.CreateCheckout; +using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetCheckoutList; +using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate; +using GozareshgirProgramManager.Domain.CheckoutAgg.Enums; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers; + +public class CheckoutController : AdminBaseController +{ + private readonly IMediator _mediator; + + public CheckoutController(IMediator mediator) + { + _mediator = mediator; + } + + [HttpGet("GetUsersToGroupCreating")] + public async Task>> GetUserListWhoHaveSettings([FromQuery] GetUserToGroupCreatingQuery command) + { + + var res = await _mediator.Send(command); + + return res; + } + + //[HttpGet("TypeOfCheckoutHandlerDictionary")] + //public IActionResult GetTypeOfCheckoutHandlerDictionary() + //{ + // var names = Enum.GetNames(typeof(TypeOfCheckoutHandler)); + // List result = new List(); + + // foreach (var name in names) + // { + // if (name == "CreateInGroup") + // { + // result.Add("CreateInGroup ایجاد گروهی sample('1404', '8', UserIdList : [1,2,3] "); + // result.Add("------------------------------------------------------------------------------------------------------------------------------------"); + // } + + // if (name == "CreateInGroup") + // { + // result.Add("GroupEditing ویرایش گروهی sample(checkoutIdList : ['3fa85f64-5717-4562-b3fc-2c963f66afa6', '3fa85f64-5717-4562-b3fc-2c963f66afa6'])"); + // result.Add("------------------------------------------------------------------------------------------------------------------------------------"); + // } + + // if (name == "CreateInGroup") + // result.Add("SingleEdit ویرایش تکی sample(checkoutId : '3fa85f64-5717-4562-b3fc-2c963f66afa6')" ); + // } + // return Ok(result); + //} + + [HttpPost("Create")] + public async Task Create([FromBody] List? UserIdlist, string Year, string Month) + { + var createCommand = new CreateOrEditCheckoutCommand( + TypeOfCheckoutHandler.CreateInGroup, + Year, + Month,UserIdlist, new List()); + + + var res = await _mediator.Send(createCommand); + + return res; + } + + [HttpPost("Edit")] + public async Task EditSingleOrGroup([FromBody] List CheckoutIdList) + { + var createCommand = new CreateOrEditCheckoutCommand( + TypeOfCheckoutHandler.GroupEditing, + null, + null, null, CheckoutIdList); + + + var res = await _mediator.Send(createCommand); + + return res; + } + + + [HttpGet("GetCheckoutList")] + public async Task>>> GetCheckoutList([FromQuery] GetCheckoutListQuery command) + { + + var res = await _mediator.Send(command); + + return res; + } +} \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Controllers/GeneralController.cs b/ServiceHost/Areas/Admin/Controllers/GeneralController.cs new file mode 100644 index 00000000..64b27217 --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/GeneralController.cs @@ -0,0 +1,29 @@ +using System.Globalization; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers; + +public class GeneralController:AdminBaseController +{ + /// + /// نمایش اطلاعات عمومی مانند تاریخ ها و سال ها + /// + /// + [HttpGet("Dates")] + public IActionResult GetDates() + { + var pc = new PersianCalendar(); + var now = DateTime.Now; + var currentYear = pc.GetYear(now); + var years = Enumerable.Range(1370, currentYear - 1370 + 1).ToList(); + var months = Enumerable.Range(1, 12).ToList(); + var currentDate = new { Year = currentYear, Month = pc.GetMonth(now), Day = pc.GetDayOfMonth(now) }; + return new JsonResult(new + { + years, + months, + currentDate + }); + } +} \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Controllers/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProjectController.cs new file mode 100644 index 00000000..a52e8ab1 --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/ProjectController.cs @@ -0,0 +1,102 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.EditProject; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.SetTimeProject; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; +using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectAssignDetails; +using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList; +using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList; +using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers; + +public class ProjectController : AdminBaseController +{ + private readonly IMediator _mediator; + + public ProjectController(IMediator mediator) + { + _mediator = mediator; + } + + [HttpGet] + public async Task>> Get([FromQuery]GetProjectsListQuery query) + { + var res=await _mediator.Send(query); + return res; + } + + [HttpPost] + public async Task> Create([FromBody] CreateProjectCommand command) + { + var res=await _mediator.Send(command); + return res; + } + + [HttpPut] + public async Task> Edit([FromBody] EditProjectCommand command) + { + var res=await _mediator.Send(command); + return res; + } + + [HttpDelete] + public async Task> Delete([FromQuery] DeleteProjectCommand command) + { + var res=await _mediator.Send(command); + return res; + } + + [HttpGet("assign")] + public async Task>> GetAssignableProjects(GetProjectAssignDetailsQuery query) + { + var res=await _mediator.Send(query); + return res; + } + + [HttpPost("assign")] + public async Task> Assign(AssignProjectCommand command) + { + var res=await _mediator.Send(command); + return res; + } + [HttpGet("set-time")] + public async Task>> GetSetTimeProjectDetails(ProjectSetTimeDetailsQuery query) + { + var res=await _mediator.Send(query); + return res; + } + [HttpPost("set-time")] + public async Task> SetTimeProject(SetTimeProjectCommand command) + { + var res=await _mediator.Send(command); + return res; + } + + [HttpPost("change-status")] + public async Task> ChangeStatus(ChangeStatusSectionCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + [HttpPost("transfer-section")] + public async Task> TransferSection([FromBody] TransferSectionCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + [HttpGet("board")] + public async Task>>> GetProjectBoard([FromQuery] ProjectBoardListQuery query) + { + var res = await _mediator.Send(query); + return res; + } +} \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Controllers/RoleController.cs b/ServiceHost/Areas/Admin/Controllers/RoleController.cs new file mode 100644 index 00000000..b074f105 --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/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; + +public class RoleController : AdminBaseController +{ + 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/SalaryPaymentSettingsController.cs b/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs new file mode 100644 index 00000000..bb09a5a3 --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs @@ -0,0 +1,67 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.EditSalarySettings; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; +using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetUserListWhoHaveSettings; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers; + +public class SalaryPaymentSettingsController : AdminBaseController +{ + private readonly IMediator _mediator; + + public SalaryPaymentSettingsController(IMediator mediator) + { + _mediator = mediator; + } + + [HttpGet("PersianDayOfWeekDictionary")] + public IActionResult GetPersianDayOfWeekDictionary() + { + var names = Enum.GetNames(typeof(PersianDayOfWeek)); + + return Ok(names); + } + + [HttpGet("GetUsers")] + public async Task>> GetUserListWhoHaveSettings([FromQuery] GetUserListWhoHaveSettingsQuery command) + { + + var res = await _mediator.Send(command); + + return res; + } + + [HttpGet("GetToEdit/{UserId}")] + public async Task>> GetSalarySettingsByUserId(long UserId) + { + var query = new GetSalarySettingToEditQuery(UserId); + var res = await _mediator.Send(query); + + return res; + } + + [HttpPost("edit")] + public async Task> Edit([FromBody] EditSalarySettingsCommand command) + { + var res = await _mediator.Send(command); + return res; + } + + + [HttpPost("create")] + public async Task> Create([FromBody] CreateSalarySettingsCommand command) + { + var res = await _mediator.Send(command); + return res; + + } + + + +} + diff --git a/ServiceHost/Areas/Admin/Controllers/SkillController.cs b/ServiceHost/Areas/Admin/Controllers/SkillController.cs new file mode 100644 index 00000000..4fcc373e --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/SkillController.cs @@ -0,0 +1,24 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Skills.Queries.GetSkillList; +using MediatR; +using Microsoft.AspNetCore.Mvc; +using ServiceHost.BaseControllers; + +namespace ServiceHost.Areas.Admin.Controllers; + +public class SkillController:AdminBaseController +{ + private readonly IMediator _mediator; + + public SkillController(IMediator mediator) + { + _mediator = mediator; + } + + [HttpGet] + public async Task>> GetList([FromQuery]GetSkillListQuery query) + { + var res = await _mediator.Send(query); + return res; + } +} \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Controllers/UserController.cs b/ServiceHost/Areas/Admin/Controllers/UserController.cs new file mode 100644 index 00000000..9fabaf9f --- /dev/null +++ b/ServiceHost/Areas/Admin/Controllers/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; + +public class UserController : AdminBaseController +{ + 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 d6882906..a414829e 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -37,6 +37,11 @@ using Parbad.Builder; using Parbad.Gateway.Sepehr; using Swashbuckle.AspNetCore.SwaggerUI; using AccountManagement.Domain.InternalApiCaller; +using FluentValidation; +using GozareshgirProgramManager.Application._Bootstrapper; +using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; +using GozareshgirProgramManager.Infrastructure; +using GozareshgirProgramManager.Infrastructure.Persistence.Seed; var builder = WebApplication.CreateBuilder(args); @@ -55,6 +60,11 @@ var connectionString = builder.Configuration.GetConnectionString("MesbahDb"); var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb"); var connectionStringProgramManager = builder.Configuration.GetConnectionString("ProgramManagerDb"); + +builder.Services.AddProgramManagerApplication(); +builder.Services.AddProgramManagerInfrastructure(builder.Configuration); +builder.Services.AddValidatorsFromAssemblyContaining(); +builder.Services.AddScoped(); #region MongoDb var mongoConnectionSection = builder.Configuration.GetSection("MongoDb"); @@ -216,6 +226,7 @@ builder.Services.AddSignalR(); builder.Services.AddSwaggerGen(options => { options.UseInlineDefinitionsForEnums(); + options.CustomSchemaIds(type => type.FullName); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); diff --git a/ServiceHost/ServiceHost.csproj b/ServiceHost/ServiceHost.csproj index 56999321..28681ae7 100644 --- a/ServiceHost/ServiceHost.csproj +++ b/ServiceHost/ServiceHost.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable true @@ -68,6 +68,8 @@ + + @@ -77,6 +79,8 @@ + + diff --git a/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj b/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj index 62f2add8..55d6ce9b 100644 --- a/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj +++ b/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj b/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj index 231fd693..ea896886 100644 --- a/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj +++ b/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj b/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj index 242d5353..5d5c21f8 100644 --- a/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj +++ b/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj index ed7e9ba4..9bc635b9 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj index 0fe5e5ec..b5bb9483 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj index de6a663d..f5e37417 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/_0_Framework/_0_Framework_b.csproj b/_0_Framework/_0_Framework_b.csproj index bb6a3bd7..4b8e918f 100644 --- a/_0_Framework/_0_Framework_b.csproj +++ b/_0_Framework/_0_Framework_b.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 diff --git a/backService/backService.csproj b/backService/backService.csproj index eb699246..848d38c6 100644 --- a/backService/backService.csproj +++ b/backService/backService.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 From c059066b1316a3910d015223217e13defd23604b Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 12:17:29 +0330 Subject: [PATCH 02/15] refactor: restructure controllers and update user references for ProgramManager --- .../CreateOrEditCheckoutCommandHandler.cs | 2 +- .../GetUserToGroupCreatingQueryHandler.cs | 7 +- .../CreateSalarySettingsCommandHandler.cs | 2 +- .../GetSalarySettingToEditQueryHandler.cs | 2 +- .../GetUserListWhoHaveSettingsQueryHandler.cs | 2 +- .../Interfaces/IProgramManagerDbContext.cs | 6 - .../RoleAgg/Entities/Role.cs | 48 ----- .../RoleAgg/Repositories/IRoleRepository.cs | 12 -- .../RoleUserAgg/RoleUser.cs | 19 -- .../Entities/SalaryPaymentSetting.cs | 15 +- .../UserAgg/Entities/User.cs | 169 ------------------ .../UserAgg/Entities/UserRefreshToken.cs | 90 ---------- .../UserAgg/Enums/ExternalAuthProvider.cs | 1 - .../UserAgg/Events/UserEvents.cs | 47 ----- .../IUserRefreshTokenRepository.cs | 9 - .../UserAgg/Repositories/IUserRepository.cs | 32 ---- .../Context/ProgramManagerDbContext.cs | 4 - .../SalaryPaymentSettingRepository.cs | 6 +- .../{ => ProgramManager}/AuthController.cs | 6 +- .../CheckoutController.cs | 4 +- .../{ => ProgramManager}/ProjectController.cs | 4 +- .../{ => ProgramManager}/RoleController.cs | 6 +- .../SalaryPaymentSettingsController.cs | 6 +- .../{ => ProgramManager}/SkillController.cs | 4 +- .../{ => ProgramManager}/UserController.cs | 6 +- .../ProgramManagerBaseController.cs | 13 ++ ServiceHost/Program.cs | 53 +++--- 27 files changed, 77 insertions(+), 498 deletions(-) delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/AuthController.cs (97%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/CheckoutController.cs (96%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/ProjectController.cs (96%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/RoleController.cs (84%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/SalaryPaymentSettingsController.cs (90%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/SkillController.cs (82%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/UserController.cs (90%) create mode 100644 ServiceHost/BaseControllers/ProgramManagerBaseController.cs diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs index d7704b1f..d8c4a5b4 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs @@ -10,7 +10,7 @@ using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; -using GozareshgirProgramManager.Domain.UserAgg.Entities; + using MediatR; using PersianTools.Core; using System.Runtime.InteropServices; 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 1b04026a..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 @@ -14,10 +14,12 @@ namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUse public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; + private readonly IGozareshgirDbContext _gozareshgirDbContext; - public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context) + public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context, IGozareshgirDbContext gozareshgirDbContext) { _context = context; + _gozareshgirDbContext = gozareshgirDbContext; } public async Task> Handle(GetUserToGroupCreatingQuery request, CancellationToken cancellationToken) @@ -48,13 +50,14 @@ public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler Handle(CreateSalarySettingsCommand request, CancellationToken cancellationToken) { - if(_salaryPaymentSettingRepository.Exists(x=>x.UserId == request.UserId)) + if(_salaryPaymentSettingRepository.Exists(x=>x.AccountId == request.UserId)) return OperationResult.Failure(" برای این پرسنل قبلا تنظیمات ایجاد شده است"); 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 c3bd3385..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 @@ -27,7 +27,7 @@ public class GetSalarySettingToEditQueryHandler : IBaseQueryHandler new WorkingHoursListDto 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 2e9361e6..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 @@ -21,7 +21,7 @@ public class GetUserListWhoHaveSettingsQueryHandler : IBaseQueryHandler Checkouts { set; get; } DbSet SalaryPaymentSettings { set; get; } - DbSet Roles { get; set; } - DbSet Users { get; set; } - DbSet RefreshTokens { get; set; } DbSet Customers { get; } DbSet Projects { get; set; } DbSet ProjectPhases { get; set; } diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs deleted file mode 100644 index 81bb10ba..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs +++ /dev/null @@ -1,48 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.PermissionAgg.Entities; -using System.Security.Principal; -using System.Xml.Linq; -using GozareshgirProgramManager.Domain.UserAgg.Entities; - -namespace GozareshgirProgramManager.Domain.RoleAgg.Entities; - -public class Role : EntityBase -{ - /// - /// نام نقش - /// - public string RoleName { get; private set; } - - - /// - /// لیست پرمیشن کد ها - /// - public List Permissions { get; private set; } - - /// - /// ای دی نقش در گزارشگیر - /// - public long? GozareshgirRoleId { get; private set; } - - - protected Role() - { - } - - public Role(string roleName,long? gozareshgirRolId, List permissions) - { - RoleName = roleName; - Permissions = permissions; - GozareshgirRoleId = gozareshgirRolId; - - } - - - public void Edit(string roleName, List permissions) - { - RoleName = roleName; - Permissions = permissions; - } - - -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs deleted file mode 100644 index 6d30ae22..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.RoleAgg.Entities; -using GozareshgirProgramManager.Domain.UserAgg.Entities; - -namespace GozareshgirProgramManager.Domain.RoleAgg.Repositories; - -public interface IRoleRepository : IRepository -{ - Task GetByGozareshgirRoleIdAsync(long? gozareshgirRolId); - - -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs deleted file mode 100644 index b8a05dc9..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs +++ /dev/null @@ -1,19 +0,0 @@ -using GozareshgirProgramManager.Domain.UserAgg.Entities; - -namespace GozareshgirProgramManager.Domain.RoleUserAgg; - -public class RoleUser -{ - public RoleUser(long roleId) - { - RoleId = roleId; - } - - public long Id { get; private set; } - public long RoleId { get; private set; } - - - public User User { get; set; } - - -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs index d98e3454..e5923ad6 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs @@ -1,5 +1,4 @@ using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.UserAgg.Entities; namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; @@ -13,13 +12,13 @@ public class SalaryPaymentSetting : EntityBase /// برای اولین بار /// /// - /// + /// /// /// - public SalaryPaymentSetting(bool holidayWorking, long userId, double monthlySalary, List workingHoursList) + public SalaryPaymentSetting(bool holidayWorking, long accountId, double monthlySalary, List workingHoursList) { HolidayWorking = holidayWorking; - UserId = userId; + AccountId = accountId; MonthlySalary = monthlySalary; WorkingHoursList = workingHoursList; StartSettingDate = new DateTime(2025, 3, 21); @@ -28,14 +27,14 @@ public class SalaryPaymentSetting : EntityBase /// افزودن تنظیمات جدید /// /// - /// + /// /// /// /// - public SalaryPaymentSetting(bool holidayWorking, long userId, List workingHoursList, DateTime startSettingDate) + public SalaryPaymentSetting(bool holidayWorking, long accountId, List workingHoursList, DateTime startSettingDate) { HolidayWorking = holidayWorking; - UserId = userId; + AccountId = accountId; WorkingHoursList = workingHoursList; StartSettingDate = startSettingDate; @@ -56,7 +55,7 @@ public class SalaryPaymentSetting : EntityBase /// /// آی دی کاربر /// - public long UserId { get; private set; } + public long AccountId { get; private set; } /// /// دستمزد ماهانه diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs deleted file mode 100644 index d112136d..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs +++ /dev/null @@ -1,169 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.PermissionAgg.Entities; -using GozareshgirProgramManager.Domain.RoleAgg.Entities; -using GozareshgirProgramManager.Domain.RoleUserAgg; - -namespace GozareshgirProgramManager.Domain.UserAgg.Entities; - -/// -/// کاربر -/// -public class User : EntityBase -{ - /// - /// ایجاد - /// - /// - /// - /// - /// - /// - /// - /// - public User(string fullName, string userName, string password, string mobile, string? email, long? accountId, List roles) - { - FullName = fullName; - UserName = userName; - Password = password; - Mobile = mobile; - Email = email; - IsActive = true; - AccountId = accountId; - RoleUser = roles; - } - - protected User() - { - - } - /// - /// نام و نام خانوادگی - /// - public string FullName { get; private set; } - - /// - /// نام کاربری - /// - public string UserName { get; private set; } - - /// - /// گذرواژه - /// - public string Password { get; private set; } - - /// - /// مسیر عکس پروفایل - /// - public string ProfilePhotoPath { get; private set; } - - /// - /// شماره موبایل - /// - public string Mobile { get; set; } - - /// - /// ایمیل - /// - public string? Email { get; private set; } - - /// - /// فعال/غیر فعال بودن یوزر - /// - public bool IsActive { get; private set; } - - - /// - /// کد یکبارمصرف ورود - /// - public string? VerifyCode { get; private set; } - - /// - /// آی دی کاربر در گزارشگیر - /// - public long? AccountId { get; private set; } - - - /// - /// لیست پرمیشن کد ها - /// - public List RoleUser { get; private set; } - - /// - /// لیست توکن‌های تازه‌سازی - /// - private List _refreshTokens = new(); - public IReadOnlyCollection RefreshTokens => _refreshTokens.AsReadOnly(); - - /// - /// آپدیت کاربر - /// - /// - /// - /// - /// - /// - public void Edit(string fullName, string userName, string mobile, List roles, bool isActive) - { - FullName = fullName; - UserName = userName; - Mobile = mobile; - RoleUser = roles; - IsActive = isActive; - } - - /// - /// غیرفعال سازی - /// - public void DeActive() - { - IsActive = false; - } - - /// - /// فعال سازی - /// - public void ReActive() - { - IsActive = true; - } - - /// - /// افزودن توکن تازه‌سازی - /// - public void AddRefreshToken(string token, DateTime expiresAt, string? ipAddress = null, string? userAgent = null) - { - var refreshToken = new UserRefreshToken(Id, token, expiresAt, ipAddress, userAgent); - _refreshTokens.Add(refreshToken); - } - - /// - /// لغو توکن تازه‌سازی - /// - public void RevokeRefreshToken(string token) - { - var refreshToken = _refreshTokens.FirstOrDefault(x => x.Token == token); - if (refreshToken == null) - throw new InvalidOperationException("توکن یافت نشد"); - - refreshToken.Revoke(); - } - - /// - /// لغو تمام توکن‌های فعال - /// - public void RevokeAllRefreshTokens() - { - foreach (var token in _refreshTokens.Where(x => x.IsActive)) - { - token.Revoke(); - } - } - - /// - /// پاکسازی توکن‌های منقضی شده - /// - public void RemoveExpiredRefreshTokens() - { - _refreshTokens.RemoveAll(x => !x.IsActive); - } -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs deleted file mode 100644 index b04b3615..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs +++ /dev/null @@ -1,90 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; - -namespace GozareshgirProgramManager.Domain.UserAgg.Entities; - -/// -/// توکن تازه‌سازی برای احراز هویت -/// -public class UserRefreshToken : EntityBase -{ - /// - /// سازنده محافظت شده برای EF Core - /// - protected UserRefreshToken() - { - } - - /// - /// ایجاد توکن تازه‌سازی - /// - public UserRefreshToken(long userId, string token, DateTime expiresAt, string? ipAddress = null, string? userAgent = null) - { - UserId = userId; - Token = token; - ExpiresAt = expiresAt; - IpAddress = ipAddress; - UserAgent = userAgent; - } - - /// - /// شناسه کاربر - /// - public long UserId { get; private set; } - - /// - /// توکن تازه‌سازی - /// - public string Token { get; private set; } - - /// - /// تاریخ انقضا - /// - public DateTime ExpiresAt { get; private set; } - - /// - /// تاریخ لغو - /// - public DateTime? RevokedAt { get; private set; } - - /// - /// آی‌پی کاربر - /// - public string? IpAddress { get; private set; } - - /// - /// User Agent مرورگر - /// - public string? UserAgent { get; private set; } - - /// - /// آیا منقضی شده؟ - /// - public bool IsExpired => DateTime.Now >= ExpiresAt; - - /// - /// آیا لغو شده؟ - /// - public bool IsRevoked => RevokedAt.HasValue; - - /// - /// آیا فعال است؟ - /// - public bool IsActive => !IsRevoked && !IsExpired; - - /// - /// لغو توکن - /// - public void Revoke() - { - if (IsRevoked) - throw new InvalidOperationException("توکن قبلاً لغو شده است"); - - RevokedAt = DateTime.Now; - } - - /// - /// کاربر صاحب توکن - /// - public User User { get; private set; } -} - diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs deleted file mode 100644 index e02abfc9..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs deleted file mode 100644 index 83b95f05..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs +++ /dev/null @@ -1,47 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.UserAgg.Entities; - - -namespace GozareshgirProgramManager.Domain.UserAgg.Events; - -public record UserCreatedEvent(long UserId, string FirstName, string LastName, string Email) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} - -public record UserPersonalInfoUpdatedEvent(long UserId, string OldFirstName, string OldLastName, string NewFirstName, string NewLastName) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} - -public record UserEmailUpdatedEvent(long UserId, string OldEmail, string NewEmail) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} - -public record UserWorkInfoUpdatedEvent(long UserId, string? Department, string? Position) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} - - - - - - - - -public record UserDeactivatedEvent(long UserId, string? Reason) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} - -public record UserActivatedEvent(long UserId) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} - -public record UserLoggedInEvent(long UserId, DateTime LoginTime) : IDomainEvent -{ - public DateTime OccurredOn { get; init; } = DateTime.UtcNow; -} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs deleted file mode 100644 index 62146e68..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs +++ /dev/null @@ -1,9 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.UserAgg.Entities; - -namespace GozareshgirProgramManager.Domain.UserAgg.Repositories; - -public interface IUserRefreshTokenRepository : IRepository -{ - -} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs deleted file mode 100644 index 5ce68190..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs +++ /dev/null @@ -1,32 +0,0 @@ -using GozareshgirProgramManager.Domain._Common; -using GozareshgirProgramManager.Domain.UserAgg.Entities; - -namespace GozareshgirProgramManager.Domain.UserAgg.Repositories; - -public interface IUserRepository: IRepository -{ - Task GetByIdAsync(long id); - - /// - /// یافتن کاربر با آی دی اکانت گزارشگیر او - /// - /// - /// - Task GetByGozareshgirAccountId(long accountId); - Task GetByEmailAsync(string email); - Task GetByMobileAsync(string mobile); - Task> GetAllAsync(); - Task> GetActiveUsersAsync(); - - Task AddAsync(User user); - void Update(User user); - void Delete(User user); - Task ExistsAsync(long id); - Task UsernameExistsAsync(string username); - Task EmailExistsAsync(string email); - Task MobileExistsAsync(string mobile); - Task GetUserWithRolesByIdAsync(long userId, CancellationToken cancellationToken); -} - - - diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs index 2fc4854c..69327586 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs @@ -31,13 +31,9 @@ public class ProgramManagerDbContext : DbContext, IProgramManagerDbContext public DbSet TaskSectionActivities { get; set; } = null!; public DbSet TaskSectionAdditionalTimes { get; set; } = null!; - - public DbSet Users { get; set; } = null!; - public DbSet RefreshTokens { get; set; } = null!; public DbSet Checkouts { get; set; } = null!; public DbSet SalaryPaymentSettings { get; set; } = null!; - public DbSet Roles { get; set; } = null!; public DbSet Skills { get; set; } = null!; protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs index a3d43ccd..4af80655 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs @@ -19,16 +19,16 @@ public class SalaryPaymentSettingRepository : RepositoryBase GetSalarySettingByUserId(long userId) { - return await _context.SalaryPaymentSettings.FirstOrDefaultAsync(x => x.UserId == userId); + return await _context.SalaryPaymentSettings.FirstOrDefaultAsync(x => x.AccountId == userId); } public async Task> GetAllSettings(List userIdList) { _context.SalaryPaymentSettings.AsNoTracking(); - var query = await _context.SalaryPaymentSettings.Where(s=> userIdList.Contains(s.UserId)) + var query = await _context.SalaryPaymentSettings.Where(s=> userIdList.Contains(s.AccountId)) .Join(_context.Users.AsNoTracking(), - setting => setting.UserId, + setting => setting.AccountId, user => user.Id, (setting, user) => new { setting, user } ) diff --git a/ServiceHost/Areas/Admin/Controllers/AuthController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs similarity index 97% rename from ServiceHost/Areas/Admin/Controllers/AuthController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs index cac9318f..22e3c173 100644 --- a/ServiceHost/Areas/Admin/Controllers/AuthController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs @@ -9,14 +9,12 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; /// /// کنترلر احراز هویت /// -[Route("api/[controller]")] -[ApiController] -public class AuthController :AdminBaseController +public class AuthController : ProgramManagerBaseController { private readonly IAuthHelper _authHelper; private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs similarity index 96% rename from ServiceHost/Areas/Admin/Controllers/CheckoutController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs index 69128d3a..29edd65c 100644 --- a/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs @@ -7,9 +7,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class CheckoutController : AdminBaseController +public class CheckoutController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs similarity index 96% rename from ServiceHost/Areas/Admin/Controllers/ProjectController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index a52e8ab1..266e72d4 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -14,9 +14,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class ProjectController : AdminBaseController +public class ProjectController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/RoleController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs similarity index 84% rename from ServiceHost/Areas/Admin/Controllers/RoleController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs index b074f105..39e7ff7d 100644 --- a/ServiceHost/Areas/Admin/Controllers/RoleController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs @@ -1,4 +1,4 @@ -using GozareshgirProgramManager.Application._Common.Models; +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; @@ -6,9 +6,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class RoleController : AdminBaseController +public class RoleController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs similarity index 90% rename from ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs index bb09a5a3..bbf188ed 100644 --- a/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs @@ -1,4 +1,4 @@ -using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.EditSalarySettings; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; @@ -8,9 +8,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class SalaryPaymentSettingsController : AdminBaseController +public class SalaryPaymentSettingsController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/SkillController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs similarity index 82% rename from ServiceHost/Areas/Admin/Controllers/SkillController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs index 4fcc373e..da770a7e 100644 --- a/ServiceHost/Areas/Admin/Controllers/SkillController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs @@ -4,9 +4,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class SkillController:AdminBaseController +public class SkillController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/UserController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs similarity index 90% rename from ServiceHost/Areas/Admin/Controllers/UserController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs index 9fabaf9f..f0f7ada3 100644 --- a/ServiceHost/Areas/Admin/Controllers/UserController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs @@ -1,4 +1,4 @@ -using GozareshgirProgramManager.Application._Common.Models; +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; @@ -8,9 +8,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class UserController : AdminBaseController +public class UserController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/BaseControllers/ProgramManagerBaseController.cs b/ServiceHost/BaseControllers/ProgramManagerBaseController.cs new file mode 100644 index 00000000..1a174236 --- /dev/null +++ b/ServiceHost/BaseControllers/ProgramManagerBaseController.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +namespace ServiceHost.BaseControllers; + +[Authorize(Policy = "AdminArea")] +[Area("Admin")] +[ApiExplorerSettings(GroupName = "ProgramManager")] +[Route("api/admin/programmanager/[controller]")] +public class ProgramManagerBaseController:ControllerBase +{ + +} + diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index a414829e..3bb89c85 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -242,36 +242,38 @@ builder.Services.AddSwaggerGen(options => options.SwaggerDoc("Admin", new OpenApiInfo { Title = "API - Admin", Version = "v1" }); options.SwaggerDoc("Client", new OpenApiInfo { Title = "API - Client", Version = "v1" }); options.SwaggerDoc("Camera", new OpenApiInfo { Title = "API - Camera", Version = "v1" }); + options.SwaggerDoc("ProgramManager", new OpenApiInfo { Title = "API - ProgramManager", Version = "v1" }); + options.DocInclusionPredicate((docName, apiDesc) => string.Equals(docName, apiDesc.GroupName, StringComparison.OrdinalIgnoreCase)); - // اضافه کردن پشتیبانی از JWT در Swagger - options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme - { - Name = "Authorization", - Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey, - Scheme = "Bearer", - BearerFormat = "JWT", - In = Microsoft.OpenApi.Models.ParameterLocation.Header, - Description = "لطفاً 'Bearer [space] token' را وارد کنید." - }); - - options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement - { - { - new Microsoft.OpenApi.Models.OpenApiSecurityScheme - { - Reference = new Microsoft.OpenApi.Models.OpenApiReference - { - Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, - Id = "Bearer" - } - }, - Array.Empty() - } - }); + // // اضافه کردن پشتیبانی از JWT در Swagger + // options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + // { + // Name = "Authorization", + // Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey, + // Scheme = "Bearer", + // BearerFormat = "JWT", + // In = Microsoft.OpenApi.Models.ParameterLocation.Header, + // Description = "لطفاً 'Bearer [space] token' را وارد کنید." + // }); + // + // options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement + // { + // { + // new Microsoft.OpenApi.Models.OpenApiSecurityScheme + // { + // Reference = new Microsoft.OpenApi.Models.OpenApiReference + // { + // Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, + // Id = "Bearer" + // } + // }, + // Array.Empty() + // } + // }); options.EnableAnnotations(); }); @@ -405,6 +407,7 @@ if (app.Environment.IsDevelopment()) options.DocExpansion(DocExpansion.None); options.SwaggerEndpoint("/swagger/General/swagger.json", "API - General"); options.SwaggerEndpoint("/swagger/Admin/swagger.json", "API - Admin"); + options.SwaggerEndpoint("/swagger/ProgramManager/swagger.json", "API - ProgramManager"); options.SwaggerEndpoint("/swagger/Client/swagger.json", "API - Client"); options.SwaggerEndpoint("/swagger/Camera/swagger.json", "API - Camera"); }); From 9469a5f76ef94306f597eadc2ee6f209d2d7840d Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 13:48:05 +0330 Subject: [PATCH 03/15] feat: introduce Shared.Contracts for account management and refactor related services --- ...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, 520 insertions(+), 1622 deletions(-) create mode 100644 AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/CreateRole/CreateRoleCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/EditRole/EditRoleCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Queries/GetRoles/GetRolesQueryHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandValidators.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/EditUser/EditUserCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUserSelectList/GetUserSelectListQueryHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQuery.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQueryHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersResponse.cs delete mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RefreshTokenMapping.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RoleMapping.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRefreshTokenRepository.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRepository.cs delete mode 100644 ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs delete mode 100644 ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs delete mode 100644 ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs create mode 100644 Shared.Contracts/Account/AccountBasicDto.cs create mode 100644 Shared.Contracts/Account/IAccountQueryService.cs create 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 393ad8f9..0e58ca5f 100644 --- a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj +++ b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj @@ -10,6 +10,7 @@ + diff --git a/AccountManagement.Configuration/AccountManagementBootstrapper.cs b/AccountManagement.Configuration/AccountManagementBootstrapper.cs index 132bf2d6..f51b7baa 100644 --- a/AccountManagement.Configuration/AccountManagementBootstrapper.cs +++ b/AccountManagement.Configuration/AccountManagementBootstrapper.cs @@ -32,9 +32,11 @@ 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; @@ -46,6 +48,7 @@ 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 d75abbba..80362a81 100644 --- a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj +++ b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj @@ -14,8 +14,10 @@ + + diff --git a/AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs b/AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs new file mode 100644 index 00000000..83c4a350 --- /dev/null +++ b/AccountMangement.Infrastructure.EFCore/Services/AccountQueryService.cs @@ -0,0 +1,49 @@ +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 358d6d87..d4d76d3a 100644 --- a/DadmehrGostar.sln +++ b/DadmehrGostar.sln @@ -104,128 +104,378 @@ 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 7bd51642..40b5a7bb 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj @@ -14,6 +14,7 @@ + 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 c98b88e9..f7b3d82d 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,6 +5,7 @@ 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; @@ -14,12 +15,14 @@ namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUse public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; - private readonly IGozareshgirDbContext _gozareshgirDbContext; + private readonly IAccountQueryService _accountQueryService; - public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context, IGozareshgirDbContext gozareshgirDbContext) + public GetUserToGroupCreatingQueryHandler( + IProgramManagerDbContext context, + IAccountQueryService accountQueryService) { _context = context; - _gozareshgirDbContext = gozareshgirDbContext; + _accountQueryService = accountQueryService; } public async Task> Handle(GetUserToGroupCreatingQuery request, CancellationToken cancellationToken) @@ -50,35 +53,46 @@ public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler x.CheckoutStartDate < lastMonthStart + && x.CheckoutEndDate >= lastMonthStart) + on s.AccountId equals ch.UserId into chJoin + from ch in chJoin.DefaultIfEmpty() - // LEFT JOIN - // تنظیمات حقوق - join s in _context.SalaryPaymentSettings - on u.Id equals s.AccountId into sJoin - from s in sJoin.DefaultIfEmpty() + 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 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() + // دریافت اطلاعات Account ها از AccountManagement + var accountIds = settingsAndCheckouts.Select(x => x.AccountId).Distinct().ToList(); + var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(accountIds); + var accountsDict = accounts.ToDictionary(a => a.Id); - 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); + // ترکیب داده‌ها + 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(); 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 4f27773a..91bdbc8a 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 GozareshgirProgramManager.Domain.UserAgg.Repositories; +using Shared.Contracts.Account; namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.TransferSection; @@ -10,15 +10,15 @@ public class TransferSectionCommandHandler : IBaseCommandHandler>> Handle(ProjectBoardListQuery request, @@ -30,10 +33,9 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler x.Activities).Select(a => a.UserId).Distinct().ToList(); - 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); + // 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 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 f99f3370..e2084f20 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,11 +1,9 @@ -using DNTPersianUtils.Core; -using GozareshgirProgramManager.Application._Common.Interfaces; +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; @@ -14,10 +12,12 @@ public class ProjectSetTimeDetailsQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; + private readonly IAccountQueryService _accountQueryService; - public ProjectSetTimeDetailsQueryHandler(IProgramManagerDbContext context) + public ProjectSetTimeDetailsQueryHandler(IProgramManagerDbContext context, IAccountQueryService accountQueryService) { _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(); - var users = await _context.Users - .Where(x => userIds.Contains(x.Id)) - .AsNoTracking() - .ToListAsync(cancellationToken); + // Fetch account basics in batch (instead of _context.Users) + var accounts = await _accountQueryService.GetProgramManagerAccountListAsync(userIds); + var accountDict = accounts.ToDictionary(a => a.Id); + 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 = user?.UserName ?? "", + UserName = account?.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 deleted file mode 100644 index c5ef5b2c..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/CreateRole/CreateRoleCommandHandler.cs +++ /dev/null @@ -1,44 +0,0 @@ -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 deleted file mode 100644 index 36e50fbb..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Commands/EditRole/EditRoleCommandHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -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 deleted file mode 100644 index bcdb5fe1..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Roles/Queries/GetRoles/GetRolesQueryHandler.cs +++ /dev/null @@ -1,76 +0,0 @@ -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 1fe869c7..080fcef6 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,60 +3,66 @@ using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; using GozareshgirProgramManager.Domain._Common; using Microsoft.EntityFrameworkCore; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; +using Shared.Contracts.Account; namespace GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; public class GetSalarySettingToEditQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; + private readonly IAccountQueryService _accountQueryService; - public GetSalarySettingToEditQueryHandler(IProgramManagerDbContext context) + public GetSalarySettingToEditQueryHandler(IProgramManagerDbContext context, IAccountQueryService accountQueryService) { _context = context; + _accountQueryService = accountQueryService; } public async Task> Handle(GetSalarySettingToEditQuery request, CancellationToken cancellationToken) { - var user =await _context.Users.FirstOrDefaultAsync(x => x.Id == request.UserId); - if(user == null) + // دریافت اطلاعات حساب از AccountManagement + var account = await _accountQueryService.GetAccountAsync(request.UserId); + if (account == 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(x => x.UserId == request.UserId); + }).FirstOrDefaultAsync(cancellationToken); - var response = new GetSalarySettingToEditResponse(request.UserId,user.FullName,editSalarySettingsList); + if (editSalarySettingsList == null) + { + return OperationResult.NotFound("تنظیمات مورد نظر یافت نشد"); + } + + var response = new GetSalarySettingToEditResponse(request.UserId, account.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 { @@ -77,12 +83,10 @@ public record GetSalarySettingToEdit /// /// حقوق ماهانه /// - public string MonthlySalary { get; set; } + public string MonthlySalary { get; set; } = string.Empty; /// /// لیست روزهای هفته و ساعات کاری /// - public List WorkingHoursList { get; set; } + public List WorkingHoursList { get; set; } = new(); } - - 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 05fd3674..ea2192df 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,62 +4,71 @@ 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) + public GetUserListWhoHaveSettingsQueryHandler(IProgramManagerDbContext context, IAccountQueryService accountQueryService) { _context = context; + _accountQueryService = accountQueryService; } public async Task> Handle(GetUserListWhoHaveSettingsQuery request, CancellationToken cancellationToken) { - var query = await ( - from u in _context.Users - join s in _context.SalaryPaymentSettings - on u.Id equals s.AccountId into settingsGroup - select new GetUserWhoHaveSettingsDto + // 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 => { - 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); + 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; if (!string.IsNullOrWhiteSpace(request.FullName)) - query = query.Where(x => x.FullName.Contains(request.FullName)).ToList(); + list = list.Where(x => x.FullName.Contains(request.FullName)).ToList(); if (request.HasSalarySettings != HasSalarySettings.Default) { bool hasSettings = request.HasSalarySettings == HasSalarySettings.HasSettings; - query = query.Where(x => x.HasSalarySettings == hasSettings).ToList(); + list = list.Where(x => x.HasSalarySettings == hasSettings).ToList(); } - - var operationQuery = query.Select(user => + + var operationQuery = list.Select(user => { var weeklyWorkingTimeAvrage = user.WeeklyWorkingTimeAvrageInt.ConvertIntDurationToHoursAndMinutes(); - return new GetUserWhoHaveSettingsDto - { - UserId = user.UserId, - FullName = user.FullName, - HasSalarySettings = user.HasSalarySettings, - MontlySalary = user.MontlySalary, - WeeklyWorkingTimeAvrageInt = user.WeeklyWorkingTimeAvrageInt, - WeeklyWorkingTimeAvrage = weeklyWorkingTimeAvrage - }; + return user with { 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 deleted file mode 100644 index 4eba06a0..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommand.cs +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 535697b3..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -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 deleted file mode 100644 index 68f9f1a7..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/CreateUser/CreateUserCommandValidators.cs +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 1920f1fb..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/EditUser/EditUserCommandHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -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 deleted file mode 100644 index 80d51cb2..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index cb284fd0..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs +++ /dev/null @@ -1,98 +0,0 @@ -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 deleted file mode 100644 index 31cf5838..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 12bfb62b..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs +++ /dev/null @@ -1,86 +0,0 @@ -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 deleted file mode 100644 index 7c9c6bda..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 92c69fcf..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs +++ /dev/null @@ -1,68 +0,0 @@ -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 deleted file mode 100644 index 0c6d5a33..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index 3e638729..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs +++ /dev/null @@ -1,115 +0,0 @@ -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 deleted file mode 100644 index 2d79108e..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs +++ /dev/null @@ -1,124 +0,0 @@ -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 deleted file mode 100644 index 7b45273a..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUserSelectList/GetUserSelectListQueryHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -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 deleted file mode 100644 index 9a3e15e8..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQuery.cs +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index cb6467f4..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersQueryHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -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 deleted file mode 100644 index e1cd043c..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetUsers/GetUsersResponse.cs +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index 49e5cdc8..00000000 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/PermissionAgg/Entities/Permission.cs +++ /dev/null @@ -1,21 +0,0 @@ -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 a17403b0..4cfa127e 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -6,21 +6,14 @@ 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; @@ -55,12 +48,7 @@ public static class DependencyInjection // Unit of Work services.AddScoped(); - - //Users - services.AddScoped(); - - //Roles - services.AddScoped(); + //WorkingHours services.AddScoped(); @@ -83,8 +71,6 @@ 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 69327586..5a8b0fc5 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs @@ -4,10 +4,7 @@ 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 deleted file mode 100644 index 42ac6330..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RefreshTokenMapping.cs +++ /dev/null @@ -1,50 +0,0 @@ -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 deleted file mode 100644 index 085a3d81..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/RoleMapping.cs +++ /dev/null @@ -1,23 +0,0 @@ -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 deleted file mode 100644 index 39ca99ac..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Mappings/UserMapping.cs +++ /dev/null @@ -1,34 +0,0 @@ -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 deleted file mode 100644 index 01198c37..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/RoleRepository.cs +++ /dev/null @@ -1,24 +0,0 @@ -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 4af80655..d016c134 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs @@ -1,19 +1,22 @@ -using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; -using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; +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; - public SalaryPaymentSettingRepository(ProgramManagerDbContext context) : base(context) + private readonly IAccountQueryService _accountQueryService; + + public SalaryPaymentSettingRepository(ProgramManagerDbContext context, IAccountQueryService accountQueryService) : base(context) { _context = context; + _accountQueryService = accountQueryService; } @@ -25,31 +28,36 @@ public class SalaryPaymentSettingRepository : RepositoryBase> GetAllSettings(List userIdList) { - _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() - }) + // دریافت تنظیمات حقوق + var settings = await _context.SalaryPaymentSettings + .AsNoTracking() + .Where(s => userIdList.Contains(s.AccountId)) .ToListAsync(); - return query; + // دریافت اطلاعات پایه کاربران از 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); + // ترکیب داده‌ها + 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 deleted file mode 100644 index 7200e888..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRefreshTokenRepository.cs +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 7b83ef6e..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/UserRepository.cs +++ /dev/null @@ -1,87 +0,0 @@ -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 a4f55718..d6582d18 100644 --- a/Query.Bootstrapper/QueryBootstrapper.cs +++ b/Query.Bootstrapper/QueryBootstrapper.cs @@ -12,6 +12,5 @@ namespace Query.Bootstrapper services.AddTransient(); } - } } diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs deleted file mode 100644 index 22e3c173..00000000 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs +++ /dev/null @@ -1,141 +0,0 @@ -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 deleted file mode 100644 index 39e7ff7d..00000000 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index f0f7ada3..00000000 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs +++ /dev/null @@ -1,67 +0,0 @@ -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 3bb89c85..b75816e4 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -39,7 +39,7 @@ using Swashbuckle.AspNetCore.SwaggerUI; using AccountManagement.Domain.InternalApiCaller; using FluentValidation; using GozareshgirProgramManager.Application._Bootstrapper; -using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; using GozareshgirProgramManager.Infrastructure; using GozareshgirProgramManager.Infrastructure.Persistence.Seed; @@ -63,7 +63,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 new file mode 100644 index 00000000..0f97fa61 --- /dev/null +++ b/Shared.Contracts/Account/AccountBasicDto.cs @@ -0,0 +1,14 @@ +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 new file mode 100644 index 00000000..15d52361 --- /dev/null +++ b/Shared.Contracts/Account/IAccountQueryService.cs @@ -0,0 +1,25 @@ +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 new file mode 100644 index 00000000..5fd9bd06 --- /dev/null +++ b/Shared.Contracts/Shared.Contracts.csproj @@ -0,0 +1,10 @@ + + + + net10.0 + enable + enable + + + + From e89aae1cc9624c13a105fcc9acd3b58eef46e722 Mon Sep 17 00:00:00 2001 From: SamSys Date: Sat, 13 Dec 2025 14:11:41 +0330 Subject: [PATCH 04/15] change accountTable --- .../AccountApplication.cs | 322 +++++++++--------- .../AccountAgg/Account.cs | 12 +- .../Repository/AccountRepository.cs | 3 +- .../Pages/Accounts/Account/Create.cshtml | 4 +- .../Pages/Accounts/Account/CreateRole.cshtml | 31 +- .../Admin/Pages/Accounts/Account/Edit.cshtml | 4 +- .../Pages/Accounts/Account/EditRole.cshtml | 33 +- .../Pages/Accounts/Account/Index.cshtml.cs | 26 +- 8 files changed, 227 insertions(+), 208 deletions(-) diff --git a/AccountManagement.Application/AccountApplication.cs b/AccountManagement.Application/AccountApplication.cs index bba09128..c36cea6a 100644 --- a/AccountManagement.Application/AccountApplication.cs +++ b/AccountManagement.Application/AccountApplication.cs @@ -155,7 +155,7 @@ public class AccountApplication : IAccountApplication } var account = new Account(command.Fullname, command.Username, password, command.Mobile, command.RoleId, - picturePath, roleName.Name, "true", "false"); + picturePath, roleName.Name, "true", "false", command.IsProgramManagerUser); _unitOfWork.BeginAccountContext(); @@ -163,64 +163,64 @@ public class AccountApplication : IAccountApplication _accountRepository.Create(account); _accountRepository.SaveChanges(); - if (command.IsProgramManagerUser) - { + //if (command.IsProgramManagerUser) + //{ - try - { - if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("نام و خانوادگی تکراری است"); - } + // try + // { + // if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("نام و خانوادگی تکراری است"); + // } - if (_pmUserRepository.Exists(x => x.UserName == command.Username)) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("نام کاربری تکراری است"); - } + // if (_pmUserRepository.Exists(x => x.UserName == command.Username)) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("نام کاربری تکراری است"); + // } - if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); - } + // if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); + // } - var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); - var create = new PmUser(command.Fullname, command.Username, command.Password, command.Mobile, - null, account.id, userRoles); - await _pmUserRepository.CreateAsync(create); - await _pmUserRepository.SaveChangesAsync(); - } - catch (Exception e) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("خطا در ایجاد کاربر پروگرام منیجر"); - } + // var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); + // var create = new PmUser(command.Fullname, command.Username, command.Password, command.Mobile, + // null, account.id, userRoles); + // await _pmUserRepository.CreateAsync(create); + // await _pmUserRepository.SaveChangesAsync(); + // } + // catch (Exception e) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("خطا در ایجاد کاربر پروگرام منیجر"); + // } - //var url = "api/user/create"; - //var key = SecretKeys.ProgramManagerInternalApi; + // //var url = "api/user/create"; + // //var key = SecretKeys.ProgramManagerInternalApi; - //var response = InternalApiCaller.PostAsync( - // url, - // key, - // parameters - //); + // //var response = InternalApiCaller.PostAsync( + // // url, + // // key, + // // parameters + // //); - //if (!response.Success) - //{ - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed(response.Error); - //} + // //if (!response.Success) + // //{ + // // _unitOfWork.RollbackAccountContext(); + // // return operation.Failed(response.Error); + // //} - //if (!response.Result.isSuccess) - //{ - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed(response.Result.errorMessage); - //} - } + // //if (!response.Result.isSuccess) + // //{ + // // _unitOfWork.RollbackAccountContext(); + // // return operation.Failed(response.Result.errorMessage); + // //} + //} _unitOfWork.CommitAccountContext(); return operation.Succcedded(); @@ -276,148 +276,148 @@ public class AccountApplication : IAccountApplication var path = $"profilePhotos"; var picturePath = _fileUploader.Upload(command.ProfilePhoto, path); _unitOfWork.BeginAccountContext(); - account.Edit(command.Fullname, command.Username, command.Mobile, command.RoleId, picturePath, roleName.Name); + account.Edit(command.Fullname, command.Username, command.Mobile, command.RoleId, picturePath, roleName.Name, command.IsProgramManagerUser); _accountRepository.SaveChanges(); - var key = SecretKeys.ProgramManagerInternalApi; + // var key = SecretKeys.ProgramManagerInternalApi; //var apiResult = InternalApiCaller.GetAsync( // $"api/user/{account.id}", // key //); - var userResult = _pmUserRepository.GetByPmUsertoEditbyAccountId(account.id).GetAwaiter().GetResult(); + // var userResult = _pmUserRepository.GetByPmUsertoEditbyAccountId(account.id).GetAwaiter().GetResult(); //اگر کاربر در پروگرام منیجر قبلا ایجاد شده - if (userResult != null) - { - if (!command.UserRoles.Any()) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("حداقل یک نقش باید انتخاب شود"); - } + //if (userResult != null) + //{ + // if (!command.UserRoles.Any()) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("حداقل یک نقش باید انتخاب شود"); + // } - try - { + // try + // { - var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); - userResult.Edit(command.Fullname, command.Username, command.Mobile, userRoles, command.IsProgramManagerUser); - await _pmUserRepository.SaveChangesAsync(); - } - catch (Exception) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); - } - //var parameters = new EditUserCommand( - // command.Fullname, - // command.Username, - // command.Mobile, - // account.id, - // command.UserRoles, - // command.IsProgramManagerUser - //); - //var url = "api/user/edit"; - //var response = InternalApiCaller.PostAsync( - // url, - // key, - // parameters - //); + // var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); + // userResult.Edit(command.Fullname, command.Username, command.Mobile, userRoles, command.IsProgramManagerUser); + // await _pmUserRepository.SaveChangesAsync(); + // } + // catch (Exception) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); + // } + // //var parameters = new EditUserCommand( + // // command.Fullname, + // // command.Username, + // // command.Mobile, + // // account.id, + // // command.UserRoles, + // // command.IsProgramManagerUser + // //); + // //var url = "api/user/edit"; + // //var response = InternalApiCaller.PostAsync( + // // url, + // // key, + // // parameters + // //); - //if (!response.Success) - //{ - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed(response.Error); + // //if (!response.Success) + // //{ + // // _unitOfWork.RollbackAccountContext(); + // // return operation.Failed(response.Error); - //} + // //} - //if (!response.Result.isSuccess) - //{ - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed(response.Error); - //} + // //if (!response.Result.isSuccess) + // //{ + // // _unitOfWork.RollbackAccountContext(); + // // return operation.Failed(response.Error); + // //} - } - else //اگر کاربر قبلا ایجاد نشده - { - //اگر تیک فعالیت در پروگرام منیجر روشن بود - if (command.IsProgramManagerUser) - { - if (!command.UserRoles.Any()) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("حداقل یک نقش باید انتخاب شود"); - } + //} + //else //اگر کاربر قبلا ایجاد نشده + //{ + // //اگر تیک فعالیت در پروگرام منیجر روشن بود + // if (command.IsProgramManagerUser) + // { + // if (!command.UserRoles.Any()) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("حداقل یک نقش باید انتخاب شود"); + // } - if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("نام و خانوادگی تکراری است"); - } + // if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("نام و خانوادگی تکراری است"); + // } - if (_pmUserRepository.Exists(x => x.UserName == command.Username)) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("نام کاربری تکراری است"); - } + // if (_pmUserRepository.Exists(x => x.UserName == command.Username)) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("نام کاربری تکراری است"); + // } - if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) - { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); - } + // if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) + // { + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); + // } - try - { - var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); - var create = new PmUser(command.Fullname, command.Username, account.Password, command.Mobile, - null, account.id, userRoles); - await _pmUserRepository.CreateAsync(create); - await _pmUserRepository.SaveChangesAsync(); - } - catch (Exception) - { + // try + // { + // var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); + // var create = new PmUser(command.Fullname, command.Username, account.Password, command.Mobile, + // null, account.id, userRoles); + // await _pmUserRepository.CreateAsync(create); + // await _pmUserRepository.SaveChangesAsync(); + // } + // catch (Exception) + // { - _unitOfWork.RollbackAccountContext(); - return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); - } + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); + // } - //var parameters = new CreateProgramManagerUser( - // command.Fullname, - // command.Username, - // account.Password, - // command.Mobile, - // command.Email, - // account.id, - // command.UserRoles - //); + // //var parameters = new CreateProgramManagerUser( + // // command.Fullname, + // // command.Username, + // // account.Password, + // // command.Mobile, + // // command.Email, + // // account.id, + // // command.UserRoles + // //); - //var url = "api/user/Create"; + // //var url = "api/user/Create"; - //var response = InternalApiCaller.PostAsync( - // url, - // key, - // parameters - //); + // //var response = InternalApiCaller.PostAsync( + // // url, + // // key, + // // parameters + // //); - //if (!response.Success) - //{ - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed(response.Error); + // //if (!response.Success) + // //{ + // // _unitOfWork.RollbackAccountContext(); + // // return operation.Failed(response.Error); - //} + // //} - //if (!response.Result.isSuccess) - //{ - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed(response.Error); - //} - } + // //if (!response.Result.isSuccess) + // //{ + // // _unitOfWork.RollbackAccountContext(); + // // return operation.Failed(response.Error); + // //} + // } - } + //} _unitOfWork.CommitAccountContext(); return operation.Succcedded(); @@ -919,7 +919,7 @@ public class AccountApplication : IAccountApplication if (!string.IsNullOrWhiteSpace(command.PhoneNumber)) { - entity.Edit(entity.Fullname, entity.Username, command.PhoneNumber, entity.RoleId, entity.ProfilePhoto, entity.RoleName); + entity.Edit(entity.Fullname, entity.Username, command.PhoneNumber, entity.RoleId, entity.ProfilePhoto, entity.RoleName, false); } _accountRepository.SaveChanges(); return op.Succcedded(); diff --git a/AccountManagement.Domain/AccountAgg/Account.cs b/AccountManagement.Domain/AccountAgg/Account.cs index 253297ba..2b797142 100644 --- a/AccountManagement.Domain/AccountAgg/Account.cs +++ b/AccountManagement.Domain/AccountAgg/Account.cs @@ -25,6 +25,11 @@ namespace AccountManagement.Domain.AccountAgg public string VerifyCode { get; set; } public string IsActiveString { get; private set; } + /// + /// آیا کاربر در پروگرام منیجر فعالیت می کند + /// + public bool IsProgramManagerUser { get; private set; } + #region Mahan public string PositionIsActive { get; private set; } public long? PositionId { get; private set; } @@ -35,7 +40,7 @@ namespace AccountManagement.Domain.AccountAgg public List CameraAccounts { get; private set; } public List AccountLeftWorkList { get; set; } public Account(string fullname, string username, string password, string mobile, - long roleId, string profilePhoto, string roleName, string adminAreaPermission, string clientAriaPermission) + long roleId, string profilePhoto, string roleName, string adminAreaPermission, string clientAriaPermission, bool isProgramManagerUser) { Fullname = fullname; Username = username; @@ -50,6 +55,7 @@ namespace AccountManagement.Domain.AccountAgg RoleName = roleName; AdminAreaPermission = adminAreaPermission; ClientAriaPermission = clientAriaPermission; + IsProgramManagerUser = isProgramManagerUser; IsActiveString = "true"; } @@ -70,18 +76,20 @@ namespace AccountManagement.Domain.AccountAgg public Account() { + ProfilePhoto = " "; } public void Edit(string fullname, string username, string mobile, - long roleId, string profilePhoto, string roleName) + long roleId, string profilePhoto, string roleName, bool isProgramManagerUser) { Fullname = fullname; Username = username; Mobile = mobile; RoleId = roleId; RoleName = roleName; + IsProgramManagerUser = isProgramManagerUser; if (!string.IsNullOrWhiteSpace(profilePhoto)) ProfilePhoto = profilePhoto; } diff --git a/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs b/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs index 1947a65b..4e0a4dc4 100644 --- a/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs +++ b/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs @@ -46,7 +46,8 @@ public class AccountRepository : RepositoryBase, IAccountReposito Mobile = x.Mobile, RoleId = x.RoleId, Username = x.Username, - IsActiveString = x.IsActiveString + IsActiveString = x.IsActiveString, + IsProgramManagerUser = x.IsProgramManagerUser, }).FirstOrDefault(x => x.Id == id); } diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml index 4819c826..23e201b4 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml @@ -142,7 +142,7 @@
-
+ @*
- `); - pmIndex++; - } else { $("#hiddenInput").append(` `); normalIndex++; - } + // const isPm = chk.hasAttribute("data-pm"); + + // if (isPm) { + // $("#hiddenInput").append(` + // + // `); + // pmIndex++; + // } else { + // $("#hiddenInput").append(` + // + // `); + // normalIndex++; + // } }); diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml index cfcf1bab..c3918b66 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml @@ -146,7 +146,7 @@
-
+@*
@if (Model.IsProgramManagerUser) @@ -165,7 +165,7 @@ -
+
*@
diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml index da948964..8f0688a9 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml @@ -1363,30 +1363,35 @@ function saveRole() { const checks = document.querySelectorAll("input.check-btn"); - let pmIndex = 0; + //let pmIndex = 0; let normalIndex = 0; $("#hiddenInput").empty(); // مهم!! قبل از اضافه‌کردن، خالی کن checks.forEach(chk => { - - const isPm = chk.hasAttribute("data-pm"); - - if (isPm) { - $("#hiddenInput").append(` - - `); - pmIndex++; - } else { - $("#hiddenInput").append(` + $("#hiddenInput").append(` `); normalIndex++; - } + // const isPm = chk.hasAttribute("data-pm"); + + // if (isPm) { + // $("#hiddenInput").append(` + // + // `); + // pmIndex++; + // } else { + // $("#hiddenInput").append(` + // + // `); + // normalIndex++; + // } }); diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs index e4597d4f..f7f192db 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs @@ -121,22 +121,22 @@ public class IndexModel : PageModel //); - var result = _accountApplication.GetPmUserByAccountId(account.Id).GetAwaiter().GetResult(); + //var result = _accountApplication.GetPmUserByAccountId(account.Id).GetAwaiter().GetResult(); - // مثل قبل: - if (result != null) - { - account.IsProgramManagerUser = (result.AccountId== account.Id && result.IsActive); - account.UserRoles = result.Roles; - } - else - { - account.IsProgramManagerUser = false; - } + //// مثل قبل: + //if (result != null) + //{ + // account.IsProgramManagerUser = (result.AccountId== account.Id && result.IsActive); + // account.UserRoles = result.Roles; + //} + //else + //{ + // account.IsProgramManagerUser = false; + //} - var pmRolseSelectList = _roleApplication.GetPmRoleList(null).GetAwaiter().GetResult(); - account.RoleList = pmRolseSelectList; + //var pmRolseSelectList = _roleApplication.GetPmRoleList(null).GetAwaiter().GetResult(); + //account.RoleList = pmRolseSelectList; //var response = InternalApiCaller.GetAsync( // "api/role", From c9882f0b593a18ab404be58b287f8d98841ca9cf Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 14:54:45 +0330 Subject: [PATCH 05/15] update to 10 --- 0_Framework/0_Framework.csproj | 22 +- ...untManagement.Application.Contracts.csproj | 6 +- .../AccountManagement.Configuration.csproj | 6 +- .../AccountManagement.Domain.csproj | 7 + ...ountMangement.Infrastructure.EFCore.csproj | 8 +- ...d programmanger boo in account.Designer.cs | 1452 +++++++++++++++++ ...112030_add programmanger boo in account.cs | 31 + .../Migrations/AccountContextModelSnapshot.cs | 151 +- Company.Domain/Company.Domain.csproj | 6 +- ...panyManagement.Infrastructure.Excel.csproj | 5 +- ...panyManagement.Infrastructure.Mongo.csproj | 3 +- .../CompanyManagment.App.Contracts.csproj | 4 + .../CompanyManagment.Application.csproj | 3 +- .../CompanyManagment.EFCore.csproj | 12 +- .../PersonalContractingParty.Config.csproj | 2 +- ...zareshgirProgramManager.Application.csproj | 8 +- ...eshgirProgramManager.Infrastructure.csproj | 11 +- Query.Bootstrapper/Query.Bootstrapper.csproj | 4 +- Query/Query.csproj | 5 + ServiceHost/Program.cs | 15 +- ServiceHost/ServiceHost.csproj | 21 +- .../WorkFlow.Application.Contracts.csproj | 7 + .../WorkFlow.Application.csproj | 7 + .../WorkFlow.Domain/WorkFlow.Domain.csproj | 7 + .../WorkFlow.Infrastructure.ACL.csproj | 7 + .../WorkFlow.Infrastructure.Config.csproj | 4 +- .../WorkFlow.Infrastructure.EfCore.csproj | 11 +- _0_Framework/_0_Framework_b.csproj | 11 +- 28 files changed, 1767 insertions(+), 69 deletions(-) create mode 100644 AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.Designer.cs create mode 100644 AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.cs diff --git a/0_Framework/0_Framework.csproj b/0_Framework/0_Framework.csproj index d4a5ba2f..ad747dc2 100644 --- a/0_Framework/0_Framework.csproj +++ b/0_Framework/0_Framework.csproj @@ -6,16 +6,20 @@ - - - - - - + + + + + + + + + - - - + + + + diff --git a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj index 0e58ca5f..57db0cd1 100644 --- a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj +++ b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj @@ -5,7 +5,11 @@ - + + + + + diff --git a/AccountManagement.Configuration/AccountManagement.Configuration.csproj b/AccountManagement.Configuration/AccountManagement.Configuration.csproj index 3914494a..1500e750 100644 --- a/AccountManagement.Configuration/AccountManagement.Configuration.csproj +++ b/AccountManagement.Configuration/AccountManagement.Configuration.csproj @@ -5,9 +5,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/AccountManagement.Domain/AccountManagement.Domain.csproj b/AccountManagement.Domain/AccountManagement.Domain.csproj index b0cc8442..bcefc806 100644 --- a/AccountManagement.Domain/AccountManagement.Domain.csproj +++ b/AccountManagement.Domain/AccountManagement.Domain.csproj @@ -4,6 +4,13 @@ net10.0 + + + + + + + diff --git a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj index 80362a81..997ca351 100644 --- a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj +++ b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj @@ -5,9 +5,11 @@ - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.Designer.cs b/AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.Designer.cs new file mode 100644 index 00000000..4b9d6614 --- /dev/null +++ b/AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.Designer.cs @@ -0,0 +1,1452 @@ +// +using System; +using AccountMangement.Infrastructure.EFCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace AccountMangement.Infrastructure.EFCore.Migrations +{ + [DbContext(typeof(AccountContext))] + [Migration("20251213112030_add programmanger boo in account")] + partial class addprogrammangerbooinaccount + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("AccountManagement.Domain.AccountAgg.Account", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AdminAreaPermission") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("ClientAriaPermission") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("Fullname") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActiveString") + .HasMaxLength(6) + .HasColumnType("nvarchar(6)"); + + b.Property("IsProgramManagerUser") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("NationalCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("PositionId") + .HasMaxLength(10) + .HasColumnType("bigint"); + + b.Property("PositionIsActive") + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("ProfilePhoto") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("RoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("id"); + + b.HasIndex("PositionId"); + + b.HasIndex("RoleId"); + + b.ToTable("Accounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountLeftWorkAgg.AccountLeftWork", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LeftWorkGr") + .HasColumnType("datetime2"); + + b.Property("RoleId") + .HasColumnType("bigint"); + + b.Property("StartWorkGr") + .HasColumnType("datetime2"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("AccountId"); + + b.ToTable("AccountLeftWork", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseAgg.AdminResponse", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AdminAccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActiveString") + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("Response") + .HasColumnType("ntext"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("TicketId"); + + b.ToTable("AdminResponses", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseMediaAgg.AdminResponseMedia", b => + { + b.Property("AdminResponseId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("AdminResponseId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("AdminResponseMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AssignAgg.Assign", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AcceptedTimeRequest") + .HasColumnType("int"); + + b.Property("AssignedId") + .HasColumnType("bigint"); + + b.Property("AssignedName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("AssignedPositionValue") + .HasColumnType("int"); + + b.Property("AssignerId") + .HasColumnType("bigint"); + + b.Property("AssignerPositionValue") + .HasColumnType("int"); + + b.Property("CancelDescription") + .HasColumnType("ntext"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DoneDescription") + .HasColumnType("ntext"); + + b.Property("EndTaskDate") + .HasColumnType("datetime2"); + + b.Property("FirstTimeCreation") + .HasColumnType("bit"); + + b.Property("IsCancel") + .HasColumnType("bit"); + + b.Property("IsCanceledRequest") + .HasColumnType("bit"); + + b.Property("IsDone") + .HasColumnType("bit"); + + b.Property("IsDoneRequest") + .HasColumnType("bit"); + + b.Property("RequestDate") + .HasColumnType("datetime2"); + + b.Property("TaskId") + .HasColumnType("bigint"); + + b.Property("TimeRequest") + .HasColumnType("bit"); + + b.Property("TimeRequestDescription") + .HasColumnType("ntext"); + + b.HasKey("id"); + + b.HasIndex("TaskId"); + + b.ToTable("Assigns", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.CameraAccountAgg.CameraAccount", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActiveSting") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("Mobile") + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.Property("WorkshopName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.HasIndex("AccountId"); + + b.ToTable("CameraAccounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseAgg.ClientResponse", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Response") + .HasColumnType("ntext"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("TicketId"); + + b.ToTable("ClientResponses", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseMediaAgg.ClientResponseMedia", b => + { + b.Property("ClientResponseId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("ClientResponseId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("ClientResponseMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.MediaAgg.Media", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Category") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Path") + .HasColumnType("ntext"); + + b.Property("ServiceName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Type") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("Medias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("PmRoles", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PositionName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PositionValue") + .HasMaxLength(2) + .HasColumnType("int"); + + b.HasKey("id"); + + b.ToTable("Positions", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountAgg.SubAccount", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("FName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsActive") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("LName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("NationalCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("ProfilePhoto") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("SubAccountRoleId") + .HasColumnType("bigint"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.HasIndex("SubAccountRoleId"); + + b.ToTable("SubAccounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle1Agg.SubAccountPermissionSubtitle1", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.ToTable("SubAccountPermissionSubtitle1", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.HasIndex("ParentId"); + + b.ToTable("SubAccountPermissionSubtitle2", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.HasIndex("ParentId"); + + b.ToTable("SubAccountPermissionSubtitle3", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle4Agg.SubAccountPermissionSubtitle4", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.HasIndex("ParentId"); + + b.ToTable("SubAccountPermissionSubtitle4", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Title") + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("id"); + + b.ToTable("SubAccountRoles", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskAgg.Tasks", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("ContractingPartyName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("ntext"); + + b.Property("IsActiveString") + .HasMaxLength(7) + .HasColumnType("nvarchar(7)"); + + b.Property("SenderId") + .HasColumnType("bigint"); + + b.Property("StartTaskDate") + .HasColumnType("datetime2"); + + b.Property("TaskScheduleId") + .HasColumnType("bigint"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.HasIndex("TaskScheduleId"); + + b.ToTable("TasksManager", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMediaAgg.TaskMedia", b => + { + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("TaskId") + .HasColumnType("bigint"); + + b.HasKey("MediaId", "TaskId"); + + b.HasIndex("TaskId"); + + b.ToTable("TasksMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageAgg.TaskMessage", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AssignId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Message") + .HasColumnType("ntext"); + + b.Property("RequestedDateFa") + .HasMaxLength(25) + .HasColumnType("nvarchar(25)"); + + b.Property("TypeOfMessage") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.HasKey("id"); + + b.HasIndex("AssignId"); + + b.ToTable("TaskMessages", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageItemsAgg.TaskMessageItems", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ReceiverAccountId") + .HasColumnType("bigint"); + + b.Property("SenderAccountId") + .HasColumnType("bigint"); + + b.Property("TaskMessageId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("TaskMessageId"); + + b.ToTable("TaskMessageItems", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskScheduleAgg.TaskSchedule", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Count") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("LastEndTaskDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("UnitNumber") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("UnitType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("TaskSchedules", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskSubjectAgg.TaskSubject", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("TaskSubjects", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketAccessAccountAgg.TicketAccessAccount", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.HasKey("id"); + + b.ToTable("TicketAccessAccounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketAgg.Ticket", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("ContractingPartyName") + .HasMaxLength(155) + .HasColumnType("nvarchar(155)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("ntext"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("SenderId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("SubAccountSenderId") + .HasColumnType("bigint"); + + b.Property("TicketNumber") + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("TicketType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.ToTable("Tickets", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketMediasAgg.TicketMedia", b => + { + b.Property("TicketId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("TicketId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("TicketMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountAgg.Account", b => + { + b.HasOne("AccountManagement.Domain.PositionAgg.Position", "Position") + .WithMany("Accounts") + .HasForeignKey("PositionId"); + + b.HasOne("AccountManagement.Domain.RoleAgg.Role", "Role") + .WithMany("Accounts") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Position"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountLeftWorkAgg.AccountLeftWork", b => + { + b.HasOne("AccountManagement.Domain.AccountAgg.Account", "Account") + .WithMany("AccountLeftWorkList") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseAgg.AdminResponse", b => + { + b.HasOne("AccountManagement.Domain.TicketAgg.Ticket", "Ticket") + .WithMany("AdminResponses") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseMediaAgg.AdminResponseMedia", b => + { + b.HasOne("AccountManagement.Domain.AdminResponseAgg.AdminResponse", "AdminResponse") + .WithMany("AdminResponseMedias") + .HasForeignKey("AdminResponseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("AdminResponseMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AdminResponse"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AssignAgg.Assign", b => + { + b.HasOne("AccountManagement.Domain.TaskAgg.Tasks", "Task") + .WithMany("Assigns") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("AccountManagement.Domain.CameraAccountAgg.CameraAccount", b => + { + b.HasOne("AccountManagement.Domain.AccountAgg.Account", "Account") + .WithMany("CameraAccounts") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseAgg.ClientResponse", b => + { + b.HasOne("AccountManagement.Domain.TicketAgg.Ticket", "Ticket") + .WithMany("ClientResponses") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseMediaAgg.ClientResponseMedia", b => + { + b.HasOne("AccountManagement.Domain.ClientResponseAgg.ClientResponse", "ClientResponse") + .WithMany("ClientResponseMedias") + .HasForeignKey("ClientResponseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("ClientResponseMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ClientResponse"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b => + { + b.OwnsMany("AccountManagement.Domain.PmDomains.PmPermissionAgg.PmPermission", "PmPermission", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("Roleid") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("Roleid"); + + b1.ToTable("PmRolePermissions", null, t => + { + t.ExcludeFromMigrations(); + }); + + b1.WithOwner("Role") + .HasForeignKey("Roleid"); + + b1.Navigation("Role"); + }); + + b.Navigation("PmPermission"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b => + { + b.OwnsMany("AccountManagement.Domain.PmDomains.PmRoleUserAgg.PmRoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("Userid") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("Userid"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("Userid"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => + { + b.OwnsMany("AccountManagement.Domain.RoleAgg.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountAgg.SubAccount", b => + { + b.HasOne("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", "SubAccountRole") + .WithMany("SubAccounts") + .HasForeignKey("SubAccountRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("SubAccountRole"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", b => + { + b.HasOne("AccountManagement.Domain.SubAccountPermissionSubtitle1Agg.SubAccountPermissionSubtitle1", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", b => + { + b.HasOne("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle4Agg.SubAccountPermissionSubtitle4", b => + { + b.HasOne("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", b => + { + b.OwnsMany("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRoleWorkshop", "RoleWorkshops", b1 => + { + b1.Property("SubAccountId") + .HasColumnType("bigint"); + + b1.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("id")); + + b1.Property("CreationDate") + .HasColumnType("datetime2"); + + b1.Property("WorkshopId") + .HasColumnType("bigint"); + + b1.HasKey("SubAccountId", "id"); + + b1.ToTable("SubAccountRoleWorkshop"); + + b1.WithOwner("SubAccountRole") + .HasForeignKey("SubAccountId"); + + b1.Navigation("SubAccountRole"); + }); + + b.OwnsMany("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRolePermission", "RolePermissions", b1 => + { + b1.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("id")); + + b1.Property("PermissionCode") + .HasColumnType("int"); + + b1.Property("SubAccountRoleId") + .HasColumnType("bigint"); + + b1.HasKey("id"); + + b1.HasIndex("SubAccountRoleId"); + + b1.ToTable("SubAccountRolePermissions", (string)null); + + b1.WithOwner("SubAccountRole") + .HasForeignKey("SubAccountRoleId"); + + b1.Navigation("SubAccountRole"); + }); + + b.Navigation("RolePermissions"); + + b.Navigation("RoleWorkshops"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskAgg.Tasks", b => + { + b.HasOne("AccountManagement.Domain.TaskScheduleAgg.TaskSchedule", "TaskSchedule") + .WithMany("TasksList") + .HasForeignKey("TaskScheduleId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("TaskSchedule"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMediaAgg.TaskMedia", b => + { + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("TaskMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.TaskAgg.Tasks", "Tasks") + .WithMany("TaskMedias") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageAgg.TaskMessage", b => + { + b.HasOne("AccountManagement.Domain.AssignAgg.Assign", "Assign") + .WithMany("TaskMessageList") + .HasForeignKey("AssignId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assign"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageItemsAgg.TaskMessageItems", b => + { + b.HasOne("AccountManagement.Domain.TaskMessageAgg.TaskMessage", "TaskMessage") + .WithMany("TaskMessageItemsList") + .HasForeignKey("TaskMessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskMessage"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketMediasAgg.TicketMedia", b => + { + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("TicketMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.TicketAgg.Ticket", "Ticket") + .WithMany("TicketMedias") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountAgg.Account", b => + { + b.Navigation("AccountLeftWorkList"); + + b.Navigation("CameraAccounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseAgg.AdminResponse", b => + { + b.Navigation("AdminResponseMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AssignAgg.Assign", b => + { + b.Navigation("TaskMessageList"); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseAgg.ClientResponse", b => + { + b.Navigation("ClientResponseMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.MediaAgg.Media", b => + { + b.Navigation("AdminResponseMedias"); + + b.Navigation("ClientResponseMedias"); + + b.Navigation("TaskMedias"); + + b.Navigation("TicketMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b => + { + b.Navigation("Accounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => + { + b.Navigation("Accounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle1Agg.SubAccountPermissionSubtitle1", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", b => + { + b.Navigation("SubAccounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskAgg.Tasks", b => + { + b.Navigation("Assigns"); + + b.Navigation("TaskMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageAgg.TaskMessage", b => + { + b.Navigation("TaskMessageItemsList"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskScheduleAgg.TaskSchedule", b => + { + b.Navigation("TasksList"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketAgg.Ticket", b => + { + b.Navigation("AdminResponses"); + + b.Navigation("ClientResponses"); + + b.Navigation("TicketMedias"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.cs b/AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.cs new file mode 100644 index 00000000..0c315d34 --- /dev/null +++ b/AccountMangement.Infrastructure.EFCore/Migrations/20251213112030_add programmanger boo in account.cs @@ -0,0 +1,31 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AccountMangement.Infrastructure.EFCore.Migrations +{ + /// + public partial class addprogrammangerbooinaccount : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsProgramManagerUser", + table: "Accounts", + type: "bit", + nullable: false, + defaultValue: false); + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsProgramManagerUser", + table: "Accounts"); + } + } +} diff --git a/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs b/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs index 44a0ebd1..ca6c5c8d 100644 --- a/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs +++ b/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("ProductVersion", "10.0.1") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -54,6 +54,9 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations .HasMaxLength(6) .HasColumnType("nvarchar(6)"); + b.Property("IsProgramManagerUser") + .HasColumnType("bit"); + b.Property("Mobile") .IsRequired() .HasMaxLength(20) @@ -377,6 +380,87 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations b.ToTable("Medias", (string)null); }); + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("PmRoles", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("Users", (string)null); + }); + modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b => { b.Property("id") @@ -1001,6 +1085,71 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations b.Navigation("Media"); }); + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b => + { + b.OwnsMany("AccountManagement.Domain.PmDomains.PmPermissionAgg.PmPermission", "PmPermission", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("Roleid") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("Roleid"); + + b1.ToTable("PmRolePermissions", null, t => + { + t.ExcludeFromMigrations(); + }); + + b1.WithOwner("Role") + .HasForeignKey("Roleid"); + + b1.Navigation("Role"); + }); + + b.Navigation("PmPermission"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b => + { + b.OwnsMany("AccountManagement.Domain.PmDomains.PmRoleUserAgg.PmRoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("Userid") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("Userid"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("Userid"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => { b.OwnsMany("AccountManagement.Domain.RoleAgg.Permission", "Permissions", b1 => diff --git a/Company.Domain/Company.Domain.csproj b/Company.Domain/Company.Domain.csproj index cde1f022..43b665be 100644 --- a/Company.Domain/Company.Domain.csproj +++ b/Company.Domain/Company.Domain.csproj @@ -20,7 +20,11 @@ - + + + + + diff --git a/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj b/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj index 7053b025..67ee0926 100644 --- a/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj +++ b/CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj @@ -6,8 +6,9 @@ enable - - + + + diff --git a/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj b/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj index 75b4e0f3..6840ab15 100644 --- a/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj +++ b/CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj @@ -11,7 +11,8 @@ - + + diff --git a/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj b/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj index 07606229..460093f3 100644 --- a/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj +++ b/CompanyManagment.App.Contracts/CompanyManagment.App.Contracts.csproj @@ -6,7 +6,11 @@ + + + + diff --git a/CompanyManagment.Application/CompanyManagment.Application.csproj b/CompanyManagment.Application/CompanyManagment.Application.csproj index d6b12f2d..f6e0f038 100644 --- a/CompanyManagment.Application/CompanyManagment.Application.csproj +++ b/CompanyManagment.Application/CompanyManagment.Application.csproj @@ -6,7 +6,8 @@ - + + diff --git a/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj b/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj index 381b2623..ff272f51 100644 --- a/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj +++ b/CompanyManagment.EFCore/CompanyManagment.EFCore.csproj @@ -5,14 +5,16 @@ - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj b/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj index 9e36ff54..ae515e3a 100644 --- a/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj +++ b/PersonalContractingParty.Config/PersonalContractingParty.Config.csproj @@ -5,7 +5,7 @@ - + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj index 40b5a7bb..41ec592d 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj index 57ba7bdb..63dd5c8a 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/GozareshgirProgramManager.Infrastructure.csproj @@ -6,13 +6,16 @@ enable - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Query.Bootstrapper/Query.Bootstrapper.csproj b/Query.Bootstrapper/Query.Bootstrapper.csproj index dfbcb641..b41d79fc 100644 --- a/Query.Bootstrapper/Query.Bootstrapper.csproj +++ b/Query.Bootstrapper/Query.Bootstrapper.csproj @@ -7,7 +7,9 @@ - + + + diff --git a/Query/Query.csproj b/Query/Query.csproj index e3f95f0d..b3fc6fdf 100644 --- a/Query/Query.csproj +++ b/Query/Query.csproj @@ -6,6 +6,11 @@ enable + + + + + diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index b75816e4..3ac9f4f6 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -1,18 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Reflection; +using System.Reflection; using _0_Framework.Application.Sms; using _0_Framework.Application; using AccountManagement.Configuration; using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Features; using PersonalContractingParty.Config; using ServiceHost; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Query.Bootstrapper; using ServiceHost.Hubs; using ServiceHost.MiddleWare; @@ -20,18 +13,13 @@ using WorkFlow.Infrastructure.Config; using _0_Framework.Application.UID; using _0_Framework.Exceptions.Handler; using _0_Framework.Application.FaceEmbedding; -using Microsoft.OpenApi.Models; using ServiceHost.Test; using System.Text.Json.Serialization; -using System.Text.Json; using _0_Framework.InfraStructure.Mongo; -using Bogus; using CompanyManagment.App.Contracts.Hubs; using CompanyManagment.EFCore.Services; -using Microsoft.AspNetCore.CookiePolicy; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Diagnostics; using MongoDB.Driver; using Parbad.Builder; using Parbad.Gateway.Sepehr; @@ -42,6 +30,7 @@ using GozareshgirProgramManager.Application._Bootstrapper; using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject; using GozareshgirProgramManager.Infrastructure; using GozareshgirProgramManager.Infrastructure.Persistence.Seed; +using Microsoft.OpenApi; var builder = WebApplication.CreateBuilder(args); diff --git a/ServiceHost/ServiceHost.csproj b/ServiceHost/ServiceHost.csproj index e5996b55..fe4fb60e 100644 --- a/ServiceHost/ServiceHost.csproj +++ b/ServiceHost/ServiceHost.csproj @@ -79,27 +79,28 @@ - + - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - - + + diff --git a/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj b/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj index 55d6ce9b..6801f518 100644 --- a/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj +++ b/WorkFlow/Application/WorkFlow.Application.Contracts/WorkFlow.Application.Contracts.csproj @@ -6,6 +6,13 @@ enable + + + + + + + diff --git a/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj b/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj index ea896886..00eb5cf6 100644 --- a/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj +++ b/WorkFlow/Application/WorkFlow.Application/WorkFlow.Application.csproj @@ -6,6 +6,13 @@ enable + + + + + + + diff --git a/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj b/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj index 5d5c21f8..c22ace88 100644 --- a/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj +++ b/WorkFlow/Domain/WorkFlow.Domain/WorkFlow.Domain.csproj @@ -6,6 +6,13 @@ enable + + + + + + + diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj index 9bc635b9..3d1e8b51 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.ACL/WorkFlow.Infrastructure.ACL.csproj @@ -6,6 +6,13 @@ enable + + + + + + + diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj index b5bb9483..be68564a 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.Config/WorkFlow.Infrastructure.Config.csproj @@ -6,7 +6,9 @@ enable - + + + diff --git a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj index f5e37417..20fa980a 100644 --- a/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj +++ b/WorkFlow/Infrastructure/WorkFlow.Infrastructure.EfCore/WorkFlow.Infrastructure.EfCore.csproj @@ -7,12 +7,17 @@ - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/_0_Framework/_0_Framework_b.csproj b/_0_Framework/_0_Framework_b.csproj index 4b8e918f..7f4e6b3d 100644 --- a/_0_Framework/_0_Framework_b.csproj +++ b/_0_Framework/_0_Framework_b.csproj @@ -5,11 +5,12 @@ - - - - - + + + + + + From 91259046f6b3cebc14b278d0abde5d10c416178a Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 15:49:31 +0330 Subject: [PATCH 06/15] 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 - - - - From b12b3b9eb83eb1b1b18065395f90d802cffdcef9 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 15:49:57 +0330 Subject: [PATCH 07/15] Revert "refactor: restructure controllers and update user references for ProgramManager" This reverts commit c059066b1316a3910d015223217e13defd23604b. --- .../CreateOrEditCheckoutCommandHandler.cs | 2 +- .../GetUserToGroupCreatingQueryHandler.cs | 7 +- .../CreateSalarySettingsCommandHandler.cs | 2 +- .../GetSalarySettingToEditQueryHandler.cs | 2 +- .../GetUserListWhoHaveSettingsQueryHandler.cs | 2 +- .../Interfaces/IProgramManagerDbContext.cs | 6 + .../RoleAgg/Entities/Role.cs | 48 +++++ .../RoleAgg/Repositories/IRoleRepository.cs | 12 ++ .../RoleUserAgg/RoleUser.cs | 19 ++ .../Entities/SalaryPaymentSetting.cs | 15 +- .../UserAgg/Entities/User.cs | 169 ++++++++++++++++++ .../UserAgg/Entities/UserRefreshToken.cs | 90 ++++++++++ .../UserAgg/Enums/ExternalAuthProvider.cs | 1 + .../UserAgg/Events/UserEvents.cs | 47 +++++ .../IUserRefreshTokenRepository.cs | 9 + .../UserAgg/Repositories/IUserRepository.cs | 32 ++++ .../Context/ProgramManagerDbContext.cs | 4 + .../SalaryPaymentSettingRepository.cs | 6 +- .../{ProgramManager => }/AuthController.cs | 6 +- .../CheckoutController.cs | 4 +- .../{ProgramManager => }/ProjectController.cs | 4 +- .../{ProgramManager => }/RoleController.cs | 6 +- .../SalaryPaymentSettingsController.cs | 6 +- .../{ProgramManager => }/SkillController.cs | 4 +- .../{ProgramManager => }/UserController.cs | 6 +- .../ProgramManagerBaseController.cs | 13 -- ServiceHost/Program.cs | 53 +++--- 27 files changed, 498 insertions(+), 77 deletions(-) create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs create mode 100644 ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/AuthController.cs (97%) rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/CheckoutController.cs (96%) rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/ProjectController.cs (96%) rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/RoleController.cs (84%) rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/SalaryPaymentSettingsController.cs (90%) rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/SkillController.cs (82%) rename ServiceHost/Areas/Admin/Controllers/{ProgramManager => }/UserController.cs (90%) delete mode 100644 ServiceHost/BaseControllers/ProgramManagerBaseController.cs diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs index d8c4a5b4..d7704b1f 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs @@ -10,7 +10,7 @@ using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; - +using GozareshgirProgramManager.Domain.UserAgg.Entities; using MediatR; using PersianTools.Core; using System.Runtime.InteropServices; 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 c98b88e9..1b04026a 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 @@ -14,12 +14,10 @@ namespace GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUse public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler { private readonly IProgramManagerDbContext _context; - private readonly IGozareshgirDbContext _gozareshgirDbContext; - public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context, IGozareshgirDbContext gozareshgirDbContext) + public GetUserToGroupCreatingQueryHandler(IProgramManagerDbContext context) { _context = context; - _gozareshgirDbContext = gozareshgirDbContext; } public async Task> Handle(GetUserToGroupCreatingQuery request, CancellationToken cancellationToken) @@ -50,14 +48,13 @@ public class GetUserToGroupCreatingQueryHandler : IBaseQueryHandler Handle(CreateSalarySettingsCommand request, CancellationToken cancellationToken) { - if(_salaryPaymentSettingRepository.Exists(x=>x.AccountId == request.UserId)) + if(_salaryPaymentSettingRepository.Exists(x=>x.UserId == request.UserId)) return OperationResult.Failure(" برای این پرسنل قبلا تنظیمات ایجاد شده است"); 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 1fe869c7..c3bd3385 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 @@ -27,7 +27,7 @@ public class GetSalarySettingToEditQueryHandler : IBaseQueryHandler new WorkingHoursListDto 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 05fd3674..2e9361e6 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 @@ -21,7 +21,7 @@ public class GetUserListWhoHaveSettingsQueryHandler : IBaseQueryHandler Checkouts { set; get; } DbSet SalaryPaymentSettings { set; get; } + DbSet Roles { get; set; } + DbSet Users { get; set; } + DbSet RefreshTokens { get; set; } DbSet Customers { get; } DbSet Projects { get; set; } DbSet ProjectPhases { get; set; } diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs new file mode 100644 index 00000000..81bb10ba --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Entities/Role.cs @@ -0,0 +1,48 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.PermissionAgg.Entities; +using System.Security.Principal; +using System.Xml.Linq; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.RoleAgg.Entities; + +public class Role : EntityBase +{ + /// + /// نام نقش + /// + public string RoleName { get; private set; } + + + /// + /// لیست پرمیشن کد ها + /// + public List Permissions { get; private set; } + + /// + /// ای دی نقش در گزارشگیر + /// + public long? GozareshgirRoleId { get; private set; } + + + protected Role() + { + } + + public Role(string roleName,long? gozareshgirRolId, List permissions) + { + RoleName = roleName; + Permissions = permissions; + GozareshgirRoleId = gozareshgirRolId; + + } + + + public void Edit(string roleName, List permissions) + { + RoleName = roleName; + Permissions = permissions; + } + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs new file mode 100644 index 00000000..6d30ae22 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleAgg/Repositories/IRoleRepository.cs @@ -0,0 +1,12 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.RoleAgg.Repositories; + +public interface IRoleRepository : IRepository +{ + Task GetByGozareshgirRoleIdAsync(long? gozareshgirRolId); + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs new file mode 100644 index 00000000..b8a05dc9 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/RoleUserAgg/RoleUser.cs @@ -0,0 +1,19 @@ +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.RoleUserAgg; + +public class RoleUser +{ + public RoleUser(long roleId) + { + RoleId = roleId; + } + + public long Id { get; private set; } + public long RoleId { get; private set; } + + + public User User { get; set; } + + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs index e5923ad6..d98e3454 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/SalaryPaymentSettingAgg/Entities/SalaryPaymentSetting.cs @@ -1,4 +1,5 @@ using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; namespace GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities; @@ -12,13 +13,13 @@ public class SalaryPaymentSetting : EntityBase /// برای اولین بار /// /// - /// + /// /// /// - public SalaryPaymentSetting(bool holidayWorking, long accountId, double monthlySalary, List workingHoursList) + public SalaryPaymentSetting(bool holidayWorking, long userId, double monthlySalary, List workingHoursList) { HolidayWorking = holidayWorking; - AccountId = accountId; + UserId = userId; MonthlySalary = monthlySalary; WorkingHoursList = workingHoursList; StartSettingDate = new DateTime(2025, 3, 21); @@ -27,14 +28,14 @@ public class SalaryPaymentSetting : EntityBase /// افزودن تنظیمات جدید /// /// - /// + /// /// /// /// - public SalaryPaymentSetting(bool holidayWorking, long accountId, List workingHoursList, DateTime startSettingDate) + public SalaryPaymentSetting(bool holidayWorking, long userId, List workingHoursList, DateTime startSettingDate) { HolidayWorking = holidayWorking; - AccountId = accountId; + UserId = userId; WorkingHoursList = workingHoursList; StartSettingDate = startSettingDate; @@ -55,7 +56,7 @@ public class SalaryPaymentSetting : EntityBase /// /// آی دی کاربر /// - public long AccountId { get; private set; } + public long UserId { get; private set; } /// /// دستمزد ماهانه diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs new file mode 100644 index 00000000..d112136d --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/User.cs @@ -0,0 +1,169 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.PermissionAgg.Entities; +using GozareshgirProgramManager.Domain.RoleAgg.Entities; +using GozareshgirProgramManager.Domain.RoleUserAgg; + +namespace GozareshgirProgramManager.Domain.UserAgg.Entities; + +/// +/// کاربر +/// +public class User : EntityBase +{ + /// + /// ایجاد + /// + /// + /// + /// + /// + /// + /// + /// + public User(string fullName, string userName, string password, string mobile, string? email, long? accountId, List roles) + { + FullName = fullName; + UserName = userName; + Password = password; + Mobile = mobile; + Email = email; + IsActive = true; + AccountId = accountId; + RoleUser = roles; + } + + protected User() + { + + } + /// + /// نام و نام خانوادگی + /// + public string FullName { get; private set; } + + /// + /// نام کاربری + /// + public string UserName { get; private set; } + + /// + /// گذرواژه + /// + public string Password { get; private set; } + + /// + /// مسیر عکس پروفایل + /// + public string ProfilePhotoPath { get; private set; } + + /// + /// شماره موبایل + /// + public string Mobile { get; set; } + + /// + /// ایمیل + /// + public string? Email { get; private set; } + + /// + /// فعال/غیر فعال بودن یوزر + /// + public bool IsActive { get; private set; } + + + /// + /// کد یکبارمصرف ورود + /// + public string? VerifyCode { get; private set; } + + /// + /// آی دی کاربر در گزارشگیر + /// + public long? AccountId { get; private set; } + + + /// + /// لیست پرمیشن کد ها + /// + public List RoleUser { get; private set; } + + /// + /// لیست توکن‌های تازه‌سازی + /// + private List _refreshTokens = new(); + public IReadOnlyCollection RefreshTokens => _refreshTokens.AsReadOnly(); + + /// + /// آپدیت کاربر + /// + /// + /// + /// + /// + /// + public void Edit(string fullName, string userName, string mobile, List roles, bool isActive) + { + FullName = fullName; + UserName = userName; + Mobile = mobile; + RoleUser = roles; + IsActive = isActive; + } + + /// + /// غیرفعال سازی + /// + public void DeActive() + { + IsActive = false; + } + + /// + /// فعال سازی + /// + public void ReActive() + { + IsActive = true; + } + + /// + /// افزودن توکن تازه‌سازی + /// + public void AddRefreshToken(string token, DateTime expiresAt, string? ipAddress = null, string? userAgent = null) + { + var refreshToken = new UserRefreshToken(Id, token, expiresAt, ipAddress, userAgent); + _refreshTokens.Add(refreshToken); + } + + /// + /// لغو توکن تازه‌سازی + /// + public void RevokeRefreshToken(string token) + { + var refreshToken = _refreshTokens.FirstOrDefault(x => x.Token == token); + if (refreshToken == null) + throw new InvalidOperationException("توکن یافت نشد"); + + refreshToken.Revoke(); + } + + /// + /// لغو تمام توکن‌های فعال + /// + public void RevokeAllRefreshTokens() + { + foreach (var token in _refreshTokens.Where(x => x.IsActive)) + { + token.Revoke(); + } + } + + /// + /// پاکسازی توکن‌های منقضی شده + /// + public void RemoveExpiredRefreshTokens() + { + _refreshTokens.RemoveAll(x => !x.IsActive); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs new file mode 100644 index 00000000..b04b3615 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Entities/UserRefreshToken.cs @@ -0,0 +1,90 @@ +using GozareshgirProgramManager.Domain._Common; + +namespace GozareshgirProgramManager.Domain.UserAgg.Entities; + +/// +/// توکن تازه‌سازی برای احراز هویت +/// +public class UserRefreshToken : EntityBase +{ + /// + /// سازنده محافظت شده برای EF Core + /// + protected UserRefreshToken() + { + } + + /// + /// ایجاد توکن تازه‌سازی + /// + public UserRefreshToken(long userId, string token, DateTime expiresAt, string? ipAddress = null, string? userAgent = null) + { + UserId = userId; + Token = token; + ExpiresAt = expiresAt; + IpAddress = ipAddress; + UserAgent = userAgent; + } + + /// + /// شناسه کاربر + /// + public long UserId { get; private set; } + + /// + /// توکن تازه‌سازی + /// + public string Token { get; private set; } + + /// + /// تاریخ انقضا + /// + public DateTime ExpiresAt { get; private set; } + + /// + /// تاریخ لغو + /// + public DateTime? RevokedAt { get; private set; } + + /// + /// آی‌پی کاربر + /// + public string? IpAddress { get; private set; } + + /// + /// User Agent مرورگر + /// + public string? UserAgent { get; private set; } + + /// + /// آیا منقضی شده؟ + /// + public bool IsExpired => DateTime.Now >= ExpiresAt; + + /// + /// آیا لغو شده؟ + /// + public bool IsRevoked => RevokedAt.HasValue; + + /// + /// آیا فعال است؟ + /// + public bool IsActive => !IsRevoked && !IsExpired; + + /// + /// لغو توکن + /// + public void Revoke() + { + if (IsRevoked) + throw new InvalidOperationException("توکن قبلاً لغو شده است"); + + RevokedAt = DateTime.Now; + } + + /// + /// کاربر صاحب توکن + /// + public User User { get; private set; } +} + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs new file mode 100644 index 00000000..e02abfc9 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Enums/ExternalAuthProvider.cs @@ -0,0 +1 @@ + diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs new file mode 100644 index 00000000..83b95f05 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Events/UserEvents.cs @@ -0,0 +1,47 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + + +namespace GozareshgirProgramManager.Domain.UserAgg.Events; + +public record UserCreatedEvent(long UserId, string FirstName, string LastName, string Email) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserPersonalInfoUpdatedEvent(long UserId, string OldFirstName, string OldLastName, string NewFirstName, string NewLastName) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserEmailUpdatedEvent(long UserId, string OldEmail, string NewEmail) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserWorkInfoUpdatedEvent(long UserId, string? Department, string? Position) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + + + + + + + + +public record UserDeactivatedEvent(long UserId, string? Reason) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserActivatedEvent(long UserId) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} + +public record UserLoggedInEvent(long UserId, DateTime LoginTime) : IDomainEvent +{ + public DateTime OccurredOn { get; init; } = DateTime.UtcNow; +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs new file mode 100644 index 00000000..62146e68 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRefreshTokenRepository.cs @@ -0,0 +1,9 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.UserAgg.Repositories; + +public interface IUserRefreshTokenRepository : IRepository +{ + +} \ No newline at end of file diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs new file mode 100644 index 00000000..5ce68190 --- /dev/null +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/UserAgg/Repositories/IUserRepository.cs @@ -0,0 +1,32 @@ +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.UserAgg.Entities; + +namespace GozareshgirProgramManager.Domain.UserAgg.Repositories; + +public interface IUserRepository: IRepository +{ + Task GetByIdAsync(long id); + + /// + /// یافتن کاربر با آی دی اکانت گزارشگیر او + /// + /// + /// + Task GetByGozareshgirAccountId(long accountId); + Task GetByEmailAsync(string email); + Task GetByMobileAsync(string mobile); + Task> GetAllAsync(); + Task> GetActiveUsersAsync(); + + Task AddAsync(User user); + void Update(User user); + void Delete(User user); + Task ExistsAsync(long id); + Task UsernameExistsAsync(string username); + Task EmailExistsAsync(string email); + Task MobileExistsAsync(string mobile); + Task GetUserWithRolesByIdAsync(long userId, CancellationToken cancellationToken); +} + + + diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs index 69327586..2fc4854c 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/ProgramManagerDbContext.cs @@ -31,9 +31,13 @@ public class ProgramManagerDbContext : DbContext, IProgramManagerDbContext public DbSet TaskSectionActivities { get; set; } = null!; public DbSet TaskSectionAdditionalTimes { get; set; } = null!; + + public DbSet Users { get; set; } = null!; + public DbSet RefreshTokens { get; set; } = null!; public DbSet Checkouts { get; set; } = null!; public DbSet SalaryPaymentSettings { get; set; } = null!; + public DbSet Roles { get; set; } = null!; public DbSet Skills { get; set; } = null!; protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs index 4af80655..a3d43ccd 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/SalaryPaymentSettingRepository.cs @@ -19,16 +19,16 @@ public class SalaryPaymentSettingRepository : RepositoryBase GetSalarySettingByUserId(long userId) { - return await _context.SalaryPaymentSettings.FirstOrDefaultAsync(x => x.AccountId == userId); + return await _context.SalaryPaymentSettings.FirstOrDefaultAsync(x => x.UserId == userId); } public async Task> GetAllSettings(List userIdList) { _context.SalaryPaymentSettings.AsNoTracking(); - var query = await _context.SalaryPaymentSettings.Where(s=> userIdList.Contains(s.AccountId)) + var query = await _context.SalaryPaymentSettings.Where(s=> userIdList.Contains(s.UserId)) .Join(_context.Users.AsNoTracking(), - setting => setting.AccountId, + setting => setting.UserId, user => user.Id, (setting, user) => new { setting, user } ) diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs b/ServiceHost/Areas/Admin/Controllers/AuthController.cs similarity index 97% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs rename to ServiceHost/Areas/Admin/Controllers/AuthController.cs index 22e3c173..cac9318f 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/AuthController.cs +++ b/ServiceHost/Areas/Admin/Controllers/AuthController.cs @@ -9,12 +9,14 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; /// /// کنترلر احراز هویت /// -public class AuthController : ProgramManagerBaseController +[Route("api/[controller]")] +[ApiController] +public class AuthController :AdminBaseController { private readonly IAuthHelper _authHelper; private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs b/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs similarity index 96% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs rename to ServiceHost/Areas/Admin/Controllers/CheckoutController.cs index 29edd65c..69128d3a 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs +++ b/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs @@ -7,9 +7,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; -public class CheckoutController : ProgramManagerBaseController +public class CheckoutController : AdminBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProjectController.cs similarity index 96% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs rename to ServiceHost/Areas/Admin/Controllers/ProjectController.cs index 266e72d4..a52e8ab1 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProjectController.cs @@ -14,9 +14,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; -public class ProjectController : ProgramManagerBaseController +public class ProjectController : AdminBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs b/ServiceHost/Areas/Admin/Controllers/RoleController.cs similarity index 84% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs rename to ServiceHost/Areas/Admin/Controllers/RoleController.cs index 39e7ff7d..b074f105 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs +++ b/ServiceHost/Areas/Admin/Controllers/RoleController.cs @@ -1,4 +1,4 @@ -using GozareshgirProgramManager.Application._Common.Models; +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; @@ -6,9 +6,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; -public class RoleController : ProgramManagerBaseController +public class RoleController : AdminBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs b/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs similarity index 90% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs rename to ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs index bbf188ed..bb09a5a3 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs +++ b/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs @@ -1,4 +1,4 @@ -using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.CreateSalarySettings; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Commands.EditSalarySettings; using GozareshgirProgramManager.Application.Modules.SalaryPaymentSettings.Queries.GetSalarySettingToEdit; @@ -8,9 +8,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; -public class SalaryPaymentSettingsController : ProgramManagerBaseController +public class SalaryPaymentSettingsController : AdminBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs b/ServiceHost/Areas/Admin/Controllers/SkillController.cs similarity index 82% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs rename to ServiceHost/Areas/Admin/Controllers/SkillController.cs index da770a7e..4fcc373e 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs +++ b/ServiceHost/Areas/Admin/Controllers/SkillController.cs @@ -4,9 +4,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; -public class SkillController : ProgramManagerBaseController +public class SkillController:AdminBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs b/ServiceHost/Areas/Admin/Controllers/UserController.cs similarity index 90% rename from ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs rename to ServiceHost/Areas/Admin/Controllers/UserController.cs index f0f7ada3..9fabaf9f 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs +++ b/ServiceHost/Areas/Admin/Controllers/UserController.cs @@ -1,4 +1,4 @@ -using GozareshgirProgramManager.Application._Common.Models; +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; @@ -8,9 +8,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; +namespace ServiceHost.Areas.Admin.Controllers; -public class UserController : ProgramManagerBaseController +public class UserController : AdminBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/BaseControllers/ProgramManagerBaseController.cs b/ServiceHost/BaseControllers/ProgramManagerBaseController.cs deleted file mode 100644 index 1a174236..00000000 --- a/ServiceHost/BaseControllers/ProgramManagerBaseController.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -namespace ServiceHost.BaseControllers; - -[Authorize(Policy = "AdminArea")] -[Area("Admin")] -[ApiExplorerSettings(GroupName = "ProgramManager")] -[Route("api/admin/programmanager/[controller]")] -public class ProgramManagerBaseController:ControllerBase -{ - -} - diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 37dc5ecb..36431242 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -231,38 +231,36 @@ builder.Services.AddSwaggerGen(options => options.SwaggerDoc("Admin", new OpenApiInfo { Title = "API - Admin", Version = "v1" }); options.SwaggerDoc("Client", new OpenApiInfo { Title = "API - Client", Version = "v1" }); options.SwaggerDoc("Camera", new OpenApiInfo { Title = "API - Camera", Version = "v1" }); - options.SwaggerDoc("ProgramManager", new OpenApiInfo { Title = "API - ProgramManager", Version = "v1" }); - options.DocInclusionPredicate((docName, apiDesc) => string.Equals(docName, apiDesc.GroupName, StringComparison.OrdinalIgnoreCase)); - // // اضافه کردن پشتیبانی از JWT در Swagger - // options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - // { - // Name = "Authorization", - // Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey, - // Scheme = "Bearer", - // BearerFormat = "JWT", - // In = Microsoft.OpenApi.Models.ParameterLocation.Header, - // Description = "لطفاً 'Bearer [space] token' را وارد کنید." - // }); - // - // options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement - // { - // { - // new Microsoft.OpenApi.Models.OpenApiSecurityScheme - // { - // Reference = new Microsoft.OpenApi.Models.OpenApiReference - // { - // Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, - // Id = "Bearer" - // } - // }, - // Array.Empty() - // } - // }); + // اضافه کردن پشتیبانی از JWT در Swagger + options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme + { + Name = "Authorization", + Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey, + Scheme = "Bearer", + BearerFormat = "JWT", + In = Microsoft.OpenApi.Models.ParameterLocation.Header, + Description = "لطفاً 'Bearer [space] token' را وارد کنید." + }); + + options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement + { + { + new Microsoft.OpenApi.Models.OpenApiSecurityScheme + { + Reference = new Microsoft.OpenApi.Models.OpenApiReference + { + Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + Array.Empty() + } + }); options.EnableAnnotations(); }); @@ -396,7 +394,6 @@ if (app.Environment.IsDevelopment()) options.DocExpansion(DocExpansion.None); options.SwaggerEndpoint("/swagger/General/swagger.json", "API - General"); options.SwaggerEndpoint("/swagger/Admin/swagger.json", "API - Admin"); - options.SwaggerEndpoint("/swagger/ProgramManager/swagger.json", "API - ProgramManager"); options.SwaggerEndpoint("/swagger/Client/swagger.json", "API - Client"); options.SwaggerEndpoint("/swagger/Camera/swagger.json", "API - Camera"); }); From f2293934d4b24ca72d65f8f214025055bebea276 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 16:41:27 +0330 Subject: [PATCH 08/15] feat: restructure ProgramManager area and integrate Shared.Contracts --- DadmehrGostar.sln | 6 + ...zareshgirProgramManager.Application.csproj | 1 + .../CreateOrEditCheckoutCommandHandler.cs | 13 +- .../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 -------------- .../_Common/Interfaces/IAuthHelper.cs | 93 ++++-------- .../Interfaces/IGozareshgirDbContext.cs | 12 -- .../DependencyInjection.cs | 9 -- .../Context/GozareshgirDbContext.cs | 22 --- .../Services/Authentication/AuthHelper.cs | 2 +- .../Areas/Admin/Controllers/AuthController.cs | 143 ------------------ .../CheckoutController.cs | 4 +- .../{ => ProgramManager}/ProjectController.cs | 4 +- .../{ => ProgramManager}/RoleController.cs | 4 +- .../SalaryPaymentSettingsController.cs | 4 +- .../{ => ProgramManager}/SkillController.cs | 4 +- .../{ => ProgramManager}/UserController.cs | 4 +- .../Admin/Pages/Accounts/Account/Index.cshtml | 2 - .../Company/Checkouts/CreateLoadList.cshtml | 3 +- .../Pages/Company/Checkouts/Details.cshtml | 3 +- .../Pages/Company/Checkouts/Index.cshtml | 1 - .../Company/ContractingParties/Index.cshtml | 1 - .../Pages/Company/Contracts/Index.cshtml | 1 - .../Pages/Company/Employees/Create.cshtml | 3 +- .../Company/Employees/CreateEmployee.cshtml | 3 +- .../Pages/Company/Employees/Index.cshtml | 1 - .../Pages/Company/Employers/Index.cshtml | 1 - .../Admin/Pages/Company/Holidays/Index.cshtml | 3 - .../_Partials/OperationsModal.cshtml | 1 - .../Admin/Pages/Company/Jobs/Index.cshtml | 1 - .../Pages/Company/MandatoryHours/Index.cshtml | 1 - .../Pages/Company/Representative/Index.cshtml | 1 - .../Company/SmsResult/SmsSettings.cshtml | 2 - .../Company/Workshops/EditWorkshop.cshtml | 1 - .../Pages/Company/Workshops/Index.cshtml | 1 - .../_EditForms/FormPermissionAccount.cshtml | 1 - ServiceHost/Areas/Admin/Pages/Index.cshtml | 1 - .../Admin/Pages/Shared/_AdminLayout.cshtml | 4 +- .../Areas/Admin/Pages/Shared/_Menu.cshtml | 1 - .../Areas/Admin/Pages/_ViewImports.cshtml | 3 +- .../ProgramManagerBaseController.cs | 14 ++ ServiceHost/Program.cs | 51 ++++--- Shared.Contracts/Holidays/HolidayDto.cs | 8 + .../Holidays/IHolidayQueryService.cs | 6 + .../PmUser/IPmUserCommandService.cs | 6 + Shared.Contracts/Shared.Contracts.csproj | 9 ++ 52 files changed, 134 insertions(+), 735 deletions(-) delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs delete mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs delete mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs delete mode 100644 ServiceHost/Areas/Admin/Controllers/AuthController.cs rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/CheckoutController.cs (96%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/ProjectController.cs (96%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/RoleController.cs (90%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/SalaryPaymentSettingsController.cs (93%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/SkillController.cs (82%) rename ServiceHost/Areas/Admin/Controllers/{ => ProgramManager}/UserController.cs (93%) create mode 100644 ServiceHost/BaseControllers/ProgramManagerBaseController.cs create mode 100644 Shared.Contracts/Holidays/HolidayDto.cs create mode 100644 Shared.Contracts/Holidays/IHolidayQueryService.cs create mode 100644 Shared.Contracts/PmUser/IPmUserCommandService.cs create mode 100644 Shared.Contracts/Shared.Contracts.csproj diff --git a/DadmehrGostar.sln b/DadmehrGostar.sln index 358d6d87..f31d5bcb 100644 --- a/DadmehrGostar.sln +++ b/DadmehrGostar.sln @@ -104,6 +104,8 @@ 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", "{08B234B6-783B-44E9-9961-4F97EAD16308}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -226,6 +228,10 @@ Global {408281FE-615F-4CBE-BD95-2E86F5ACC6C3}.Debug|Any CPU.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 + {08B234B6-783B-44E9-9961-4F97EAD16308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08B234B6-783B-44E9-9961-4F97EAD16308}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08B234B6-783B-44E9-9961-4F97EAD16308}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08B234B6-783B-44E9-9961-4F97EAD16308}.Release|Any CPU.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 e20615bf..41ec592d 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/GozareshgirProgramManager.Application.csproj @@ -14,6 +14,7 @@ + diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs index d7704b1f..3536ad0e 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs @@ -15,6 +15,7 @@ using MediatR; using PersianTools.Core; using System.Runtime.InteropServices; using Microsoft.EntityFrameworkCore; +using Shared.Contracts.Holidays; namespace GozareshgirProgramManager.Application.Modules.Checkouts.Commands.CreateCheckout; @@ -25,16 +26,18 @@ public class CreateOrEditCheckoutCommandHandler : IBaseCommandHandler Handle(CreateOrEditCheckoutCommand request, CancellationToken cancellationToken) @@ -182,9 +185,7 @@ public class CreateOrEditCheckoutCommandHandler : IBaseCommandHandlerx.Holidaydate >= start && x.Holidaydate <= end).ToListAsync(); - - + var holidays = await _holidayQueryService.GetHolidaysInDates(start, end) ; int mandatoryHours = 0; for (var currentDay = persianStart; currentDay <= persianEnd; currentDay = currentDay.AddDays(1)) { 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 deleted file mode 100644 index 80d51cb2..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index cb284fd0..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/LoginUser/LoginUserCommandHandler.cs +++ /dev/null @@ -1,98 +0,0 @@ -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 deleted file mode 100644 index 31cf5838..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 12bfb62b..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/RefreshUserToken/RefreshUserTokenCommandHandler.cs +++ /dev/null @@ -1,86 +0,0 @@ -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 deleted file mode 100644 index 7c9c6bda..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 92c69fcf..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SignOutUser/SignOutUserCommandHandler.cs +++ /dev/null @@ -1,68 +0,0 @@ -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 deleted file mode 100644 index 0c6d5a33..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index 3e638729..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Commands/SsoLogin/SsoLoginCommandHandler.cs +++ /dev/null @@ -1,115 +0,0 @@ -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/_Common/Interfaces/IAuthHelper.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs index 7b392d47..a41dad2b 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IAuthHelper.cs @@ -9,38 +9,38 @@ namespace GozareshgirProgramManager.Application._Common.Interfaces; public interface IAuthHelper { // ==================== Token Generation ==================== - LoginSession SignIn(long userId, string userName, string fullName, long accountId, List roles); - /// - /// تولید Access Token - /// - string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles); + // LoginSession SignIn(long userId, string userName, string fullName, long accountId, List roles); + // /// + // /// تولید Access Token + // /// + // string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles); - /// - /// تولید Refresh Token - /// - string GenerateRefreshToken(); + // /// + // /// تولید Refresh Token + // /// + // string GenerateRefreshToken(); - /// - /// دریافت تاریخ انقضای Refresh Token - /// - DateTime GetRefreshTokenExpiration(); + // /// + // /// دریافت تاریخ انقضای Refresh Token + // /// + // DateTime GetRefreshTokenExpiration(); // ==================== Token Validation ==================== - - /// - /// اعتبارسنجی توکن و استخراج Claims - /// - ClaimsPrincipal? ValidateToken(string token); + // + // /// + // /// اعتبارسنجی توکن و استخراج Claims + // /// + // ClaimsPrincipal? ValidateToken(string token); - /// - /// اعتبارسنجی توکن منقضی شده (بدون چک زمان انقضا) - /// - ClaimsPrincipal? ValidateExpiredToken(string token); + // /// + // /// اعتبارسنجی توکن منقضی شده (بدون چک زمان انقضا) + // /// + // ClaimsPrincipal? ValidateExpiredToken(string token); - /// - /// استخراج UserId از توکن (حتی اگر منقضی شده باشد) - /// - long? GetUserIdFromToken(string token); + // /// + // /// استخراج UserId از توکن (حتی اگر منقضی شده باشد) + // /// + // long? GetUserIdFromToken(string token); // ==================== HttpContext Helpers ==================== @@ -49,15 +49,11 @@ public interface IAuthHelper /// string? GetClientIpAddress(); - /// - /// دریافت User Agent کاربر جاری - /// - string? GetUserAgent(); - - /// - /// دریافت Refresh Token از Cookie - /// - string? GetRefreshTokenFromCookie(); + + // /// + // /// دریافت Refresh Token از Cookie + // /// + // string? GetRefreshTokenFromCookie(); // ==================== Current User Claims ==================== @@ -71,39 +67,12 @@ public interface IAuthHelper /// long? GetCurrentUserId(); - /// - /// دریافت نام کاربری جاری از Claims - /// - string? GetCurrentUserName(); - /// /// دریافت نام کامل کاربر جاری از Claims /// string? GetCurrentFullName(); - /// - /// دریافت AccountId کاربر جاری از Claims - /// - long? GetCurrentAccountId(); - - /// - /// دریافت نقش‌های کاربر جاری از Claims - /// - List GetCurrentUserRoles(); - - // ==================== Role Checking ==================== - /// - /// بررسی دسترسی کاربر به نقش خاص - /// - bool HasRole(string roleName); - - /// - /// بررسی دسترسی کاربر به یکی از نقش‌ها - /// - bool HasAnyRole(params string[] roleNames); - - void SignOut(); } public class LoginSession { diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs deleted file mode 100644 index 8baad5be..00000000 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/_Common/Interfaces/IGozareshgirDbContext.cs +++ /dev/null @@ -1,12 +0,0 @@ -using GozareshgirProgramManager.Domain.HolidayAgg; -using GozareshgirProgramManager.Domain.HolidayItemAgg; -using Microsoft.EntityFrameworkCore; - -namespace GozareshgirProgramManager.Application._Common.Interfaces; - -public interface IGozareshgirDbContext -{ - DbSet HolidayItems { get; set; } - DbSet Holidays { get; set; } - -} \ 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 a17403b0..5d73a0b3 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -42,16 +42,7 @@ public static class DependencyInjection // Register IAppDbContext services.AddScoped(provider => provider.GetRequiredService()); - - - #region GozareshgirDbContext - - services.AddDbContext(x => x.UseSqlServer(configuration.GetConnectionString("GozareshgirDb"))); - - services.AddScoped(provider => - provider.GetRequiredService()); - #endregion // Unit of Work services.AddScoped(); diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs deleted file mode 100644 index 181e1779..00000000 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Context/GozareshgirDbContext.cs +++ /dev/null @@ -1,22 +0,0 @@ -using GozareshgirProgramManager.Application._Common.Interfaces; -using GozareshgirProgramManager.Domain.HolidayAgg; -using GozareshgirProgramManager.Domain.HolidayItemAgg; -using Microsoft.EntityFrameworkCore; - -namespace GozareshgirProgramManager.Infrastructure.Persistence.Context; - -public class GozareshgirDbContext : DbContext, IGozareshgirDbContext -{ - public GozareshgirDbContext(DbContextOptions options) : base(options) - { - } - - public DbSet HolidayItems { get; set; } = null!; - public DbSet Holidays { get; set; } = null!; - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.ApplyConfigurationsFromAssembly(typeof(GozareshgirDbContext).Assembly); - base.OnModelCreating(modelBuilder); - } -} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs index ec70492e..9ca8e545 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs @@ -149,7 +149,7 @@ public class AuthHelper : IAuthHelper /// public long? GetCurrentUserId() { - var userIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; + var userIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst("pm.userId")?.Value; return long.TryParse(userIdClaim, out var userId) ? userId : null; } diff --git a/ServiceHost/Areas/Admin/Controllers/AuthController.cs b/ServiceHost/Areas/Admin/Controllers/AuthController.cs deleted file mode 100644 index cac9318f..00000000 --- a/ServiceHost/Areas/Admin/Controllers/AuthController.cs +++ /dev/null @@ -1,143 +0,0 @@ -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; - -/// -/// کنترلر احراز هویت -/// -[Route("api/[controller]")] -[ApiController] -public class AuthController :AdminBaseController -{ - 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/CheckoutController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs similarity index 96% rename from ServiceHost/Areas/Admin/Controllers/CheckoutController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs index 69128d3a..29edd65c 100644 --- a/ServiceHost/Areas/Admin/Controllers/CheckoutController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/CheckoutController.cs @@ -7,9 +7,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class CheckoutController : AdminBaseController +public class CheckoutController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs similarity index 96% rename from ServiceHost/Areas/Admin/Controllers/ProjectController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index a52e8ab1..266e72d4 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -14,9 +14,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class ProjectController : AdminBaseController +public class ProjectController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/RoleController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs similarity index 90% rename from ServiceHost/Areas/Admin/Controllers/RoleController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs index b074f105..d7994d7a 100644 --- a/ServiceHost/Areas/Admin/Controllers/RoleController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/RoleController.cs @@ -6,9 +6,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class RoleController : AdminBaseController +public class RoleController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs similarity index 93% rename from ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs index bb09a5a3..bc4784e2 100644 --- a/ServiceHost/Areas/Admin/Controllers/SalaryPaymentSettingsController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SalaryPaymentSettingsController.cs @@ -8,9 +8,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class SalaryPaymentSettingsController : AdminBaseController +public class SalaryPaymentSettingsController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/SkillController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs similarity index 82% rename from ServiceHost/Areas/Admin/Controllers/SkillController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs index 4fcc373e..0966a65a 100644 --- a/ServiceHost/Areas/Admin/Controllers/SkillController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/SkillController.cs @@ -4,9 +4,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class SkillController:AdminBaseController +public class SkillController:ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Controllers/UserController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs similarity index 93% rename from ServiceHost/Areas/Admin/Controllers/UserController.cs rename to ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs index 9fabaf9f..03ef60b8 100644 --- a/ServiceHost/Areas/Admin/Controllers/UserController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/UserController.cs @@ -8,9 +8,9 @@ using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; -namespace ServiceHost.Areas.Admin.Controllers; +namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; -public class UserController : AdminBaseController +public class UserController : ProgramManagerBaseController { private readonly IMediator _mediator; diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml index 92dca681..900be1d3 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml @@ -1,6 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty -@using Microsoft.EntityFrameworkCore @using _0_Framework.Application @model ServiceHost.Areas.Admin.Pages.Accounts.Account.IndexModel @inject IAuthHelper _AuthHelper; diff --git a/ServiceHost/Areas/Admin/Pages/Company/Checkouts/CreateLoadList.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Checkouts/CreateLoadList.cshtml index e49343e6..318d6972 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Checkouts/CreateLoadList.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Checkouts/CreateLoadList.cshtml @@ -1,5 +1,4 @@ -@using Microsoft.CodeAnalysis.CSharp.Syntax -@model CompanyManagment.App.Contracts.Checkout.CreateCheckoutListViewModel +@model CompanyManagment.App.Contracts.Checkout.CreateCheckoutListViewModel @{ var i = 1; var b = 0; diff --git a/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Details.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Details.cshtml index 95c72111..1a6af7f7 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Details.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Details.cshtml @@ -1,5 +1,4 @@ -@using System.Security.Cryptography.X509Certificates -@model CompanyManagment.App.Contracts.Checkout.CheckoutViewModel +@model CompanyManagment.App.Contracts.Checkout.CheckoutViewModel @{ var totalDays = Model.MonthlyRollCall?.Count ?? 0; var rightSideDays = totalDays / 2; diff --git a/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Index.cshtml index e416cff2..929dc0c9 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Checkouts/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.Checkouts.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/ContractingParties/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/ContractingParties/Index.cshtml index f2e5c44c..51973794 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/ContractingParties/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/ContractingParties/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.ContractingParties.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Contracts/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Contracts/Index.cshtml index 4865d1a4..778f0284 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Contracts/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Contracts/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.Contracts.IndexModel diff --git a/ServiceHost/Areas/Admin/Pages/Company/Employees/Create.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Employees/Create.cshtml index c0921767..659894e6 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Employees/Create.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Employees/Create.cshtml @@ -1,5 +1,4 @@ -@using _0_Framework.Application -@model CompanyManagment.App.Contracts.Employee.CreateEmployee +@model CompanyManagment.App.Contracts.Employee.CreateEmployee @{ var adminVersion = _0_Framework.Application.Version.AdminVersion; diff --git a/ServiceHost/Areas/Admin/Pages/Company/Employees/CreateEmployee.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Employees/CreateEmployee.cshtml index 28543bbb..e48dfc71 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Employees/CreateEmployee.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Employees/CreateEmployee.cshtml @@ -1,5 +1,4 @@ -@using _0_Framework.Application -@model CompanyManagment.App.Contracts.Employee.CreateEmployee +@model CompanyManagment.App.Contracts.Employee.CreateEmployee @{ var adminVersion = _0_Framework.Application.Version.AdminVersion; diff --git a/ServiceHost/Areas/Admin/Pages/Company/Employees/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Employees/Index.cshtml index dcfb2559..845c6b61 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Employees/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Employees/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.Employees.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Employers/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Employers/Index.cshtml index 64e33aaf..8ecf3052 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Employers/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Employers/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.Employers.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Holidays/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Holidays/Index.cshtml index 69c2dad9..75e213a8 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Holidays/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Holidays/Index.cshtml @@ -1,7 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty -@using Microsoft.EntityFrameworkCore -@using CompanyManagment.App.Contracts.Holiday @model ServiceHost.Areas.Admin.Pages.Company.Holidays.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/InsuranceList/_Partials/OperationsModal.cshtml b/ServiceHost/Areas/Admin/Pages/Company/InsuranceList/_Partials/OperationsModal.cshtml index c8d15d51..84bc4fd5 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/InsuranceList/_Partials/OperationsModal.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/InsuranceList/_Partials/OperationsModal.cshtml @@ -1,5 +1,4 @@ @using CompanyManagment.App.Contracts.InsuranceList.Enums -@using Microsoft.AspNetCore.Mvc.TagHelpers @model CompanyManagment.App.Contracts.InsuranceList.InsuranceListConfirmOperation @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Jobs/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Jobs/Index.cshtml index 9e035d35..a4e80527 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Jobs/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Jobs/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.Jobs.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/MandatoryHours/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/MandatoryHours/Index.cshtml index c1370298..fc059cf3 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/MandatoryHours/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/MandatoryHours/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.MandatoryHours.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Representative/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Representative/Index.cshtml index 1065f4e7..c9143498 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Representative/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Representative/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.Representative @model ServiceHost.Areas.Admin.Pages.Company.Representative.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/SmsResult/SmsSettings.cshtml b/ServiceHost/Areas/Admin/Pages/Company/SmsResult/SmsSettings.cshtml index ee6275a3..279d822f 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/SmsResult/SmsSettings.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/SmsResult/SmsSettings.cshtml @@ -1,6 +1,4 @@ @page -@using _0_Framework.Application.Enums -@using Microsoft.AspNetCore.Mvc.TagHelpers @model ServiceHost.Areas.Admin.Pages.Company.SmsResult.SmsSettingsModel @Html.AntiForgeryToken() @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Workshops/EditWorkshop.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Workshops/EditWorkshop.cshtml index 21ea2cfe..4a24360f 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Workshops/EditWorkshop.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Workshops/EditWorkshop.cshtml @@ -1,6 +1,5 @@ @page @using _0_Framework.Application -@using Microsoft.AspNetCore.Mvc.TagHelpers @model ServiceHost.Areas.Admin.Pages.Company.Workshops.EditWorkshopModel @{ string adminVersion = _0_Framework.Application.Version.AdminVersion; diff --git a/ServiceHost/Areas/Admin/Pages/Company/Workshops/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Workshops/Index.cshtml index 61c89eca..4a82840a 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Workshops/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Workshops/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CompanyManagment.App.Contracts.PersonalContractingParty @model ServiceHost.Areas.Admin.Pages.Company.Workshops.IndexModel @{ diff --git a/ServiceHost/Areas/Admin/Pages/Company/Workshops/_EditForms/FormPermissionAccount.cshtml b/ServiceHost/Areas/Admin/Pages/Company/Workshops/_EditForms/FormPermissionAccount.cshtml index ac030de9..27765263 100644 --- a/ServiceHost/Areas/Admin/Pages/Company/Workshops/_EditForms/FormPermissionAccount.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Company/Workshops/_EditForms/FormPermissionAccount.cshtml @@ -1,5 +1,4 @@ @using AccountManagement.Application.Contracts.Account -@using Microsoft.AspNetCore.Mvc.TagHelpers @model CompanyManagment.App.Contracts.Workshop.EditWorkshop @{ diff --git a/ServiceHost/Areas/Admin/Pages/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Index.cshtml index a36a3d4b..3e1a948d 100644 --- a/ServiceHost/Areas/Admin/Pages/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Index.cshtml @@ -2,7 +2,6 @@ @page @using _0_Framework.Application @using AccountManagement.Application.Contracts.TicketAccessAccount -@using Microsoft.AspNetCore.Mvc.TagHelpers @model ServiceHost.Areas.Admin.Pages.IndexModel @inject ITicketAccessAccountApplication TicketAccessAccount; @inject IAuthHelper authHelper; diff --git a/ServiceHost/Areas/Admin/Pages/Shared/_AdminLayout.cshtml b/ServiceHost/Areas/Admin/Pages/Shared/_AdminLayout.cshtml index 2c17b1cf..a6e21401 100644 --- a/ServiceHost/Areas/Admin/Pages/Shared/_AdminLayout.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Shared/_AdminLayout.cshtml @@ -1,6 +1,4 @@ -@using Microsoft.AspNetCore.Razor.Language.Intermediate -@using _0_Framework.Application -@using Version = _0_Framework.Application.Version +@using Version = _0_Framework.Application.Version @inject _0_Framework.Application.IAuthHelper AuthHelper; @{ diff --git a/ServiceHost/Areas/Admin/Pages/Shared/_Menu.cshtml b/ServiceHost/Areas/Admin/Pages/Shared/_Menu.cshtml index 33621097..2734ee67 100644 --- a/ServiceHost/Areas/Admin/Pages/Shared/_Menu.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Shared/_Menu.cshtml @@ -1,6 +1,5 @@ @using _0_Framework.Application @using AccountManagement.Domain.TicketAccessAccountAgg -@using Microsoft.AspNetCore.Mvc.TagHelpers @using Microsoft.Extensions.Options @inject _0_Framework.Application.IAuthHelper AuthHelper; @inject ITicketAccessAccountRepository TicketAccessAccount; diff --git a/ServiceHost/Areas/Admin/Pages/_ViewImports.cshtml b/ServiceHost/Areas/Admin/Pages/_ViewImports.cshtml index 1dd320b1..100a2f8a 100644 --- a/ServiceHost/Areas/Admin/Pages/_ViewImports.cshtml +++ b/ServiceHost/Areas/Admin/Pages/_ViewImports.cshtml @@ -1,4 +1,3 @@ -@using ServiceHost -@namespace ServiceHost.Pages +@namespace ServiceHost.Areas.Admin.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, ServiceHost \ No newline at end of file diff --git a/ServiceHost/BaseControllers/ProgramManagerBaseController.cs b/ServiceHost/BaseControllers/ProgramManagerBaseController.cs new file mode 100644 index 00000000..db83d401 --- /dev/null +++ b/ServiceHost/BaseControllers/ProgramManagerBaseController.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace ServiceHost.BaseControllers; + +[Authorize(Policy = "AdminArea")] +[Area("ProgramManager")] +[ApiExplorerSettings(GroupName = "ProgramManager")] +[Route("api/[area]/[controller]")] +public class ProgramManagerBaseController : ControllerBase +{ + +} + diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 36431242..40ca19b2 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -231,36 +231,37 @@ builder.Services.AddSwaggerGen(options => options.SwaggerDoc("Admin", new OpenApiInfo { Title = "API - Admin", Version = "v1" }); options.SwaggerDoc("Client", new OpenApiInfo { Title = "API - Client", Version = "v1" }); options.SwaggerDoc("Camera", new OpenApiInfo { Title = "API - Camera", Version = "v1" }); + options.SwaggerDoc("ProgramManager", new OpenApiInfo { Title = "API - ProgramManager", Version = "v1" }); options.DocInclusionPredicate((docName, apiDesc) => string.Equals(docName, apiDesc.GroupName, StringComparison.OrdinalIgnoreCase)); // اضافه کردن پشتیبانی از JWT در Swagger - options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme - { - Name = "Authorization", - Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey, - Scheme = "Bearer", - BearerFormat = "JWT", - In = Microsoft.OpenApi.Models.ParameterLocation.Header, - Description = "لطفاً 'Bearer [space] token' را وارد کنید." - }); - - options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement - { - { - new Microsoft.OpenApi.Models.OpenApiSecurityScheme - { - Reference = new Microsoft.OpenApi.Models.OpenApiReference - { - Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, - Id = "Bearer" - } - }, - Array.Empty() - } - }); + // options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + // { + // Name = "Authorization", + // Type = SecuritySchemeType.ApiKey, + // Scheme = "Bearer", + // BearerFormat = "JWT", + // In = ParameterLocation.Header, + // Description = "لطفاً 'Bearer [space] token' را وارد کنید." + // }); + // + // options.AddSecurityRequirement(new OpenApiSecurityRequirement + // { + // { + // new Microsoft.OpenApi.Models.OpenApiSecurityScheme + // { + // Reference = new Microsoft.OpenApi.Models.OpenApiReference + // { + // Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, + // Id = "Bearer" + // } + // }, + // Array.Empty() + // } + // }); options.EnableAnnotations(); }); @@ -396,6 +397,8 @@ if (app.Environment.IsDevelopment()) options.SwaggerEndpoint("/swagger/Admin/swagger.json", "API - Admin"); options.SwaggerEndpoint("/swagger/Client/swagger.json", "API - Client"); options.SwaggerEndpoint("/swagger/Camera/swagger.json", "API - Camera"); + options.SwaggerEndpoint("/swagger/ProgramManager/swagger.json", "API - ProgramManager"); + }); } diff --git a/Shared.Contracts/Holidays/HolidayDto.cs b/Shared.Contracts/Holidays/HolidayDto.cs new file mode 100644 index 00000000..7318b83e --- /dev/null +++ b/Shared.Contracts/Holidays/HolidayDto.cs @@ -0,0 +1,8 @@ +namespace Shared.Contracts.Holidays; + +public record HolidayDto +{ + public DateTime Holidaydate { get; private set; } + public long HolidayId { get; private set; } + public string HolidayYear { get; private set; } +} \ No newline at end of file diff --git a/Shared.Contracts/Holidays/IHolidayQueryService.cs b/Shared.Contracts/Holidays/IHolidayQueryService.cs new file mode 100644 index 00000000..8b41c745 --- /dev/null +++ b/Shared.Contracts/Holidays/IHolidayQueryService.cs @@ -0,0 +1,6 @@ +namespace Shared.Contracts.Holidays; + +public interface IHolidayQueryService +{ + Task> GetHolidaysInDates(DateTime startDate, DateTime endDate); +} \ No newline at end of file diff --git a/Shared.Contracts/PmUser/IPmUserCommandService.cs b/Shared.Contracts/PmUser/IPmUserCommandService.cs new file mode 100644 index 00000000..193bcb71 --- /dev/null +++ b/Shared.Contracts/PmUser/IPmUserCommandService.cs @@ -0,0 +1,6 @@ +namespace Shared.Contracts.PmUser; + +public interface IPmUserCommandService +{ + Task<(bool isSuccess, string pmUserDto)> Create(); +} \ No newline at end of file diff --git a/Shared.Contracts/Shared.Contracts.csproj b/Shared.Contracts/Shared.Contracts.csproj new file mode 100644 index 00000000..237d6616 --- /dev/null +++ b/Shared.Contracts/Shared.Contracts.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + From 32065aec33e2b6560053931a4acd39ba3b9edc25 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 16:45:17 +0330 Subject: [PATCH 09/15] refactor: remove unused authentication methods and clean up AuthHelper --- .../Services/Authentication/AuthHelper.cs | 204 +++++++++--------- 1 file changed, 103 insertions(+), 101 deletions(-) diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs index 9ca8e545..ec2ccd4f 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Authentication/AuthHelper.cs @@ -21,70 +21,7 @@ public class AuthHelper : IAuthHelper _jwtTokenGenerator = jwtTokenGenerator; } - public LoginSession SignIn(long userId, string userName, string fullName, long accountId, List roles) - { - - // 1. تولید Access Token - var accessToken = GenerateAccessToken(userId, userName, fullName, accountId, roles); - var accessTokenExpiration = DateTime.Now.AddMinutes(30); - - // 2. تولید Refresh Token - var refreshToken = GenerateRefreshToken(); - var refreshTokenExpiration = GetRefreshTokenExpiration(); - - // 3. ذخیره Refresh Token در Cookie - _httpContextAccessor.HttpContext?.Response.Cookies.Append("rf-token", refreshToken, new CookieOptions - { - HttpOnly = true, - Secure = true, - SameSite = SameSiteMode.Lax, - Expires = refreshTokenExpiration - }); - - // 4. تنظیم Authorization Header (اختیاری - معمولاً کلاینت خودش این کار را می‌کند) - _httpContextAccessor.HttpContext?.Response.Headers.Append("Authorization", $"Bearer {accessToken}"); - - return new LoginSession - { - AccessToken = accessToken, - RefreshToken = refreshToken, - RefreshTokenExpiration = refreshTokenExpiration, - AccessTokenExpiration = accessTokenExpiration - }; - } - - /// - /// تولید Access Token - /// - public string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles) - { - return _jwtTokenGenerator.GenerateAccessToken(userId, userName, fullName, accountId, roles); - } - - /// - /// تولید Refresh Token - /// - public string GenerateRefreshToken() - { - return _jwtTokenGenerator.GenerateRefreshToken(); - } - - /// - /// دریافت تاریخ انقضای Refresh Token - /// - public DateTime GetRefreshTokenExpiration() - { - return _jwtTokenGenerator.GetRefreshTokenExpiration(); - } - - /// - /// اعتبارسنجی توکن و استخراج Claims - /// - public ClaimsPrincipal? ValidateToken(string token) - { - return _jwtTokenGenerator.ValidateToken(token); - } - + /// /// اعتبارسنجی توکن منقضی شده (بدون چک زمان) /// @@ -169,47 +106,112 @@ public class AuthHelper : IAuthHelper return _httpContextAccessor.HttpContext?.User?.FindFirst("FullName")?.Value; } - /// - /// دریافت AccountId کاربر جاری از Claims - /// - public long? GetCurrentAccountId() - { - var accountIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst("AccountId")?.Value; - return long.TryParse(accountIdClaim, out var accountId) ? accountId : null; - } + // /// + // /// دریافت AccountId کاربر جاری از Claims + // /// + // public long? GetCurrentAccountId() + // { + // var accountIdClaim = _httpContextAccessor.HttpContext?.User?.FindFirst("AccountId")?.Value; + // return long.TryParse(accountIdClaim, out var accountId) ? accountId : null; + // } - /// - /// دریافت نقش‌های کاربر جاری از Claims - /// - public List GetCurrentUserRoles() - { - var roles = _httpContextAccessor.HttpContext?.User?.FindAll(ClaimTypes.Role) - .Select(c => c.Value) - .ToList(); + // /// + // /// دریافت نقش‌های کاربر جاری از Claims + // /// + // public List GetCurrentUserRoles() + // { + // var roles = _httpContextAccessor.HttpContext?.User?.FindAll(ClaimTypes.Role) + // .Select(c => c.Value) + // .ToList(); + // + // return roles ?? new List(); + // } - return roles ?? new List(); - } + // /// + // /// بررسی دسترسی کاربر به نقش خاص + // /// + // public bool HasRole(string roleName) + // { + // return _httpContextAccessor.HttpContext?.User?.IsInRole(roleName) ?? false; + // } + // + // /// + // /// بررسی دسترسی کاربر به یکی از نقش‌ها + // /// + // public bool HasAnyRole(params string[] roleNames) + // { + // return roleNames.Any(HasRole); + // } + // + // public void SignOut() + // { + // _httpContextAccessor.HttpContext?.Response.Cookies.Delete("rf-token"); + // _httpContextAccessor.HttpContext?.Response.Headers.Remove("Authorization"); + // } + // public LoginSession SignIn(long userId, string userName, string fullName, long accountId, List roles) + // { + // + // // 1. تولید Access Token + // var accessToken = GenerateAccessToken(userId, userName, fullName, accountId, roles); + // var accessTokenExpiration = DateTime.Now.AddMinutes(30); + // + // // 2. تولید Refresh Token + // var refreshToken = GenerateRefreshToken(); + // var refreshTokenExpiration = GetRefreshTokenExpiration(); + // + // // 3. ذخیره Refresh Token در Cookie + // _httpContextAccessor.HttpContext?.Response.Cookies.Append("rf-token", refreshToken, new CookieOptions + // { + // HttpOnly = true, + // Secure = true, + // SameSite = SameSiteMode.Lax, + // Expires = refreshTokenExpiration + // }); + // + // // 4. تنظیم Authorization Header (اختیاری - معمولاً کلاینت خودش این کار را می‌کند) + // _httpContextAccessor.HttpContext?.Response.Headers.Append("Authorization", $"Bearer {accessToken}"); + // + // return new LoginSession + // { + // AccessToken = accessToken, + // RefreshToken = refreshToken, + // RefreshTokenExpiration = refreshTokenExpiration, + // AccessTokenExpiration = accessTokenExpiration + // }; + // } + // + + // /// + // /// تولید Access Token + // /// + // public string GenerateAccessToken(long userId, string userName, string fullName, long? accountId, List roles) + // { + // return _jwtTokenGenerator.GenerateAccessToken(userId, userName, fullName, accountId, roles); + // } - /// - /// بررسی دسترسی کاربر به نقش خاص - /// - public bool HasRole(string roleName) - { - return _httpContextAccessor.HttpContext?.User?.IsInRole(roleName) ?? false; - } + // /// + // /// تولید Refresh Token + // /// + // public string GenerateRefreshToken() + // { + // return _jwtTokenGenerator.GenerateRefreshToken(); + // } + // + // /// + // /// دریافت تاریخ انقضای Refresh Token + // /// + // public DateTime GetRefreshTokenExpiration() + // { + // return _jwtTokenGenerator.GetRefreshTokenExpiration(); + // } - /// - /// بررسی دسترسی کاربر به یکی از نقش‌ها - /// - public bool HasAnyRole(params string[] roleNames) - { - return roleNames.Any(HasRole); - } + // /// + // /// اعتبارسنجی توکن و استخراج Claims + // /// + // public ClaimsPrincipal? ValidateToken(string token) + // { + // return _jwtTokenGenerator.ValidateToken(token); + // } - public void SignOut() - { - _httpContextAccessor.HttpContext?.Response.Cookies.Delete("rf-token"); - _httpContextAccessor.HttpContext?.Response.Headers.Remove("Authorization"); - } } From c9d582877b447ec6f5d9ab8fe7c91029ae5948d8 Mon Sep 17 00:00:00 2001 From: SamSys Date: Sat, 13 Dec 2025 18:25:19 +0330 Subject: [PATCH 10/15] create PmRole Completed --- ...untManagement.Application.Contracts.csproj | 1 + .../Role/IRoleApplication.cs | 3 +- .../AccountApplication.cs | 322 ++-- .../AccountManagement.Application.csproj | 1 + .../RoleApplication.cs | 36 +- .../AccountAgg/Account.cs | 12 +- ...ountMangement.Infrastructure.EFCore.csproj | 4 + ...sProgramManagerUserFromAccount.Designer.cs | 1449 +++++++++++++++++ ...2_romoveIsProgramManagerUserFromAccount.cs | 29 + .../Migrations/AccountContextModelSnapshot.cs | 3 - .../Repository/AccountRepository.cs | 3 +- .../Services/HolidayQueryService.cs | 14 + .../PersonalBootstrapper.cs | 290 ++-- .../DependencyInjection.cs | 28 +- .../Services/Role/PmRoleCommandService.cs | 28 + .../Services/Role/PmRoleQueryService.cs | 34 + .../Pages/Accounts/Account/Create.cshtml | 4 +- .../Pages/Accounts/Account/CreateRole.cshtml | 31 +- .../Admin/Pages/Accounts/Account/Edit.cshtml | 4 +- .../Pages/Accounts/Account/EditRole.cshtml | 33 +- .../Admin/Pages/Accounts/Account/Index.cshtml | 2 + .../Pages/Accounts/Account/Index.cshtml.cs | 26 +- .../PmRole/Commands/CreatePmRoleDto.cs | 9 + .../PmRole/Commands/IPmRoleCommandService.cs | 6 + .../PmRole/Queries/GetPmRolesDto.cs | 24 + .../PmRole/Queries/IPmRoleQueryService.cs | 12 + 26 files changed, 2010 insertions(+), 398 deletions(-) create mode 100644 AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.Designer.cs create mode 100644 AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.cs create mode 100644 CompanyManagment.EFCore/Services/HolidayQueryService.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleQueryService.cs create mode 100644 Shared.Contracts/PmRole/Commands/CreatePmRoleDto.cs create mode 100644 Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs create mode 100644 Shared.Contracts/PmRole/Queries/GetPmRolesDto.cs create mode 100644 Shared.Contracts/PmRole/Queries/IPmRoleQueryService.cs diff --git a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj index b73ec3c5..57db0cd1 100644 --- a/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj +++ b/AccountManagement.Application.Contracts/AccountManagement.Application.Contracts.csproj @@ -14,6 +14,7 @@ +
diff --git a/AccountManagement.Application.Contracts/Role/IRoleApplication.cs b/AccountManagement.Application.Contracts/Role/IRoleApplication.cs index 9d49f8e2..68f3ab52 100644 --- a/AccountManagement.Application.Contracts/Role/IRoleApplication.cs +++ b/AccountManagement.Application.Contracts/Role/IRoleApplication.cs @@ -1,8 +1,9 @@ using _0_Framework.Application; -using AccountManagement.Application.Contracts.ProgramManager; + using Microsoft.AspNetCore.Mvc.Rendering; using System.Collections.Generic; using System.Threading.Tasks; +using Shared.Contracts.PmRole.Queries; namespace AccountManagement.Application.Contracts.Role { diff --git a/AccountManagement.Application/AccountApplication.cs b/AccountManagement.Application/AccountApplication.cs index c36cea6a..bba09128 100644 --- a/AccountManagement.Application/AccountApplication.cs +++ b/AccountManagement.Application/AccountApplication.cs @@ -155,7 +155,7 @@ public class AccountApplication : IAccountApplication } var account = new Account(command.Fullname, command.Username, password, command.Mobile, command.RoleId, - picturePath, roleName.Name, "true", "false", command.IsProgramManagerUser); + picturePath, roleName.Name, "true", "false"); _unitOfWork.BeginAccountContext(); @@ -163,64 +163,64 @@ public class AccountApplication : IAccountApplication _accountRepository.Create(account); _accountRepository.SaveChanges(); - //if (command.IsProgramManagerUser) - //{ + if (command.IsProgramManagerUser) + { - // try - // { - // if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("نام و خانوادگی تکراری است"); - // } + try + { + if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("نام و خانوادگی تکراری است"); + } - // if (_pmUserRepository.Exists(x => x.UserName == command.Username)) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("نام کاربری تکراری است"); - // } + if (_pmUserRepository.Exists(x => x.UserName == command.Username)) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("نام کاربری تکراری است"); + } - // if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); - // } + if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); + } - // var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); - // var create = new PmUser(command.Fullname, command.Username, command.Password, command.Mobile, - // null, account.id, userRoles); - // await _pmUserRepository.CreateAsync(create); - // await _pmUserRepository.SaveChangesAsync(); - // } - // catch (Exception e) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("خطا در ایجاد کاربر پروگرام منیجر"); - // } + var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); + var create = new PmUser(command.Fullname, command.Username, command.Password, command.Mobile, + null, account.id, userRoles); + await _pmUserRepository.CreateAsync(create); + await _pmUserRepository.SaveChangesAsync(); + } + catch (Exception e) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("خطا در ایجاد کاربر پروگرام منیجر"); + } - // //var url = "api/user/create"; - // //var key = SecretKeys.ProgramManagerInternalApi; + //var url = "api/user/create"; + //var key = SecretKeys.ProgramManagerInternalApi; - // //var response = InternalApiCaller.PostAsync( - // // url, - // // key, - // // parameters - // //); + //var response = InternalApiCaller.PostAsync( + // url, + // key, + // parameters + //); - // //if (!response.Success) - // //{ - // // _unitOfWork.RollbackAccountContext(); - // // return operation.Failed(response.Error); - // //} + //if (!response.Success) + //{ + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed(response.Error); + //} - // //if (!response.Result.isSuccess) - // //{ - // // _unitOfWork.RollbackAccountContext(); - // // return operation.Failed(response.Result.errorMessage); - // //} - //} + //if (!response.Result.isSuccess) + //{ + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed(response.Result.errorMessage); + //} + } _unitOfWork.CommitAccountContext(); return operation.Succcedded(); @@ -276,148 +276,148 @@ public class AccountApplication : IAccountApplication var path = $"profilePhotos"; var picturePath = _fileUploader.Upload(command.ProfilePhoto, path); _unitOfWork.BeginAccountContext(); - account.Edit(command.Fullname, command.Username, command.Mobile, command.RoleId, picturePath, roleName.Name, command.IsProgramManagerUser); + account.Edit(command.Fullname, command.Username, command.Mobile, command.RoleId, picturePath, roleName.Name); _accountRepository.SaveChanges(); - // var key = SecretKeys.ProgramManagerInternalApi; + var key = SecretKeys.ProgramManagerInternalApi; //var apiResult = InternalApiCaller.GetAsync( // $"api/user/{account.id}", // key //); - // var userResult = _pmUserRepository.GetByPmUsertoEditbyAccountId(account.id).GetAwaiter().GetResult(); + var userResult = _pmUserRepository.GetByPmUsertoEditbyAccountId(account.id).GetAwaiter().GetResult(); //اگر کاربر در پروگرام منیجر قبلا ایجاد شده - //if (userResult != null) - //{ - // if (!command.UserRoles.Any()) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("حداقل یک نقش باید انتخاب شود"); - // } + if (userResult != null) + { + if (!command.UserRoles.Any()) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("حداقل یک نقش باید انتخاب شود"); + } - // try - // { + try + { - // var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); - // userResult.Edit(command.Fullname, command.Username, command.Mobile, userRoles, command.IsProgramManagerUser); - // await _pmUserRepository.SaveChangesAsync(); - // } - // catch (Exception) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); - // } - // //var parameters = new EditUserCommand( - // // command.Fullname, - // // command.Username, - // // command.Mobile, - // // account.id, - // // command.UserRoles, - // // command.IsProgramManagerUser - // //); - // //var url = "api/user/edit"; - // //var response = InternalApiCaller.PostAsync( - // // url, - // // key, - // // parameters - // //); + var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); + userResult.Edit(command.Fullname, command.Username, command.Mobile, userRoles, command.IsProgramManagerUser); + await _pmUserRepository.SaveChangesAsync(); + } + catch (Exception) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); + } + //var parameters = new EditUserCommand( + // command.Fullname, + // command.Username, + // command.Mobile, + // account.id, + // command.UserRoles, + // command.IsProgramManagerUser + //); + //var url = "api/user/edit"; + //var response = InternalApiCaller.PostAsync( + // url, + // key, + // parameters + //); - // //if (!response.Success) - // //{ - // // _unitOfWork.RollbackAccountContext(); - // // return operation.Failed(response.Error); + //if (!response.Success) + //{ + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed(response.Error); - // //} + //} - // //if (!response.Result.isSuccess) - // //{ - // // _unitOfWork.RollbackAccountContext(); - // // return operation.Failed(response.Error); - // //} + //if (!response.Result.isSuccess) + //{ + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed(response.Error); + //} - //} - //else //اگر کاربر قبلا ایجاد نشده - //{ - // //اگر تیک فعالیت در پروگرام منیجر روشن بود - // if (command.IsProgramManagerUser) - // { - // if (!command.UserRoles.Any()) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("حداقل یک نقش باید انتخاب شود"); - // } + } + else //اگر کاربر قبلا ایجاد نشده + { + //اگر تیک فعالیت در پروگرام منیجر روشن بود + if (command.IsProgramManagerUser) + { + if (!command.UserRoles.Any()) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("حداقل یک نقش باید انتخاب شود"); + } - // if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("نام و خانوادگی تکراری است"); - // } + if (_pmUserRepository.Exists(x => x.FullName == command.Fullname)) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("نام و خانوادگی تکراری است"); + } - // if (_pmUserRepository.Exists(x => x.UserName == command.Username)) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("نام کاربری تکراری است"); - // } + if (_pmUserRepository.Exists(x => x.UserName == command.Username)) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("نام کاربری تکراری است"); + } - // if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) - // { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); - // } + if (_pmUserRepository.Exists(x => !string.IsNullOrWhiteSpace(x.Mobile) && x.Mobile == command.Mobile)) + { + _unitOfWork.RollbackAccountContext(); + return operation.Failed("این شماره همراه قبلا به فرد دیگری اختصاص داده شده است"); + } - // try - // { - // var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); - // var create = new PmUser(command.Fullname, command.Username, account.Password, command.Mobile, - // null, account.id, userRoles); - // await _pmUserRepository.CreateAsync(create); - // await _pmUserRepository.SaveChangesAsync(); - // } - // catch (Exception) - // { + try + { + var userRoles = command.UserRoles.Where(x => x > 0).Select(x => new PmRoleUser(x)).ToList(); + var create = new PmUser(command.Fullname, command.Username, account.Password, command.Mobile, + null, account.id, userRoles); + await _pmUserRepository.CreateAsync(create); + await _pmUserRepository.SaveChangesAsync(); + } + catch (Exception) + { - // _unitOfWork.RollbackAccountContext(); - // return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); - // } + _unitOfWork.RollbackAccountContext(); + return operation.Failed("خطا در ویرایش کاربر پروگرام منیجر"); + } - // //var parameters = new CreateProgramManagerUser( - // // command.Fullname, - // // command.Username, - // // account.Password, - // // command.Mobile, - // // command.Email, - // // account.id, - // // command.UserRoles - // //); + //var parameters = new CreateProgramManagerUser( + // command.Fullname, + // command.Username, + // account.Password, + // command.Mobile, + // command.Email, + // account.id, + // command.UserRoles + //); - // //var url = "api/user/Create"; + //var url = "api/user/Create"; - // //var response = InternalApiCaller.PostAsync( - // // url, - // // key, - // // parameters - // //); + //var response = InternalApiCaller.PostAsync( + // url, + // key, + // parameters + //); - // //if (!response.Success) - // //{ - // // _unitOfWork.RollbackAccountContext(); - // // return operation.Failed(response.Error); + //if (!response.Success) + //{ + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed(response.Error); - // //} + //} - // //if (!response.Result.isSuccess) - // //{ - // // _unitOfWork.RollbackAccountContext(); - // // return operation.Failed(response.Error); - // //} - // } + //if (!response.Result.isSuccess) + //{ + // _unitOfWork.RollbackAccountContext(); + // return operation.Failed(response.Error); + //} + } - //} + } _unitOfWork.CommitAccountContext(); return operation.Succcedded(); @@ -919,7 +919,7 @@ public class AccountApplication : IAccountApplication if (!string.IsNullOrWhiteSpace(command.PhoneNumber)) { - entity.Edit(entity.Fullname, entity.Username, command.PhoneNumber, entity.RoleId, entity.ProfilePhoto, entity.RoleName, false); + entity.Edit(entity.Fullname, entity.Username, command.PhoneNumber, entity.RoleId, entity.ProfilePhoto, entity.RoleName); } _accountRepository.SaveChanges(); return op.Succcedded(); diff --git a/AccountManagement.Application/AccountManagement.Application.csproj b/AccountManagement.Application/AccountManagement.Application.csproj index 270c0e13..15c192f3 100644 --- a/AccountManagement.Application/AccountManagement.Application.csproj +++ b/AccountManagement.Application/AccountManagement.Application.csproj @@ -8,6 +8,7 @@ + diff --git a/AccountManagement.Application/RoleApplication.cs b/AccountManagement.Application/RoleApplication.cs index 6ea605d4..80a1af83 100644 --- a/AccountManagement.Application/RoleApplication.cs +++ b/AccountManagement.Application/RoleApplication.cs @@ -4,7 +4,6 @@ using AccountManagement.Domain.RoleAgg; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AccountManagement.Application.Contracts.ProgramManager; using AccountManagement.Application.Contracts.ProgramManagerApiResult; using AccountManagement.Domain.InternalApiCaller; using Company.Domain._common; @@ -13,7 +12,10 @@ using AccountManagement.Domain.PmDomains.PmPermissionAgg; using AccountManagement.Domain.PmDomains.PmRoleAgg; using AccountManagement.Domain.PmDomains.PmUserAgg; using Microsoft.AspNetCore.Mvc.Rendering; +using Shared.Contracts.PmRole.Commands; +using GetPmRolesDto = Shared.Contracts.PmRole.Queries.GetPmRolesDto; using Role = AccountManagement.Domain.RoleAgg.Role; +using Shared.Contracts.PmRole.Queries; namespace AccountManagement.Application; @@ -22,14 +24,18 @@ public class RoleApplication : IRoleApplication private readonly IRoleRepository _roleRepository; private readonly IPmRoleRepository _pmRoleRepository; private readonly IPmUserRepository _pmUserRepository; + private readonly IPmRoleQueryService _pmRoleQueryService; + private readonly IPmRoleCommandService _pmRoleCommandService; private readonly IUnitOfWork _unitOfWork; - public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleRepository pmRoleRepository, IPmUserRepository pmUserRepository) + public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleRepository pmRoleRepository, IPmUserRepository pmUserRepository, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService) { _roleRepository = roleRepository; _unitOfWork = unitOfWork; _pmRoleRepository = pmRoleRepository; _pmUserRepository = pmUserRepository; + _pmRoleQueryService = pmRoleQueryService; + _pmRoleCommandService = pmRoleCommandService; } public async Task Create(CreateRole command) @@ -47,19 +53,15 @@ public class RoleApplication : IRoleApplication var pmPermissions = command.PmPermissions.Where(x => x > 0).ToList(); if (pmPermissions.Any()) { - try - { - var pmPermissionsData = pmPermissions.Where(x => x > 0).Select(x => new PmPermission(x)).ToList(); - var pmRole = new PmRole(command.Name, role.id, pmPermissionsData); - await _pmRoleRepository.CreateAsync(pmRole); - await _pmRoleRepository.SaveChangesAsync(); - - } - catch (System.Exception) + + var pmRole = new CreatePmRoleDto{ RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id}; + var res =await _pmRoleCommandService.Create(pmRole); + if (!res.Item1) { _unitOfWork.RollbackAccountContext(); return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر"); } + //var parameters = new CreateProgramManagerRole //{ @@ -136,8 +138,8 @@ public class RoleApplication : IRoleApplication //); - var pmRoleResult = await _pmRoleRepository.GetPmRoleToEdit(command.Id); - + var pmRoleListResult = await _pmRoleQueryService.GetPmRoleList(command.Id); + var pmRoleResult = pmRoleListResult.FirstOrDefault(); //اگر این نقش در پروگرام منیجر وجود داشت ویرایش کن if (pmRoleResult != null) @@ -146,8 +148,8 @@ public class RoleApplication : IRoleApplication try { var pmpermissionsData = pmPermissions.Where(x => x > 0).Select(x => new PmPermission(x)).ToList(); - pmRoleResult.Edit(command.Name, pmpermissionsData); - await _pmRoleRepository.SaveChangesAsync(); + //pmRoleResult.Edit(command.Name, pmpermissionsData); + // await _pmRoleRepository.SaveChangesAsync(); } catch (System.Exception) { @@ -254,7 +256,7 @@ public class RoleApplication : IRoleApplication public async Task GetPmRoleList(long? gozareshgirRoleId) { - var rolse = await _pmRoleRepository.GetPmRoleList(gozareshgirRoleId); + var rolse = await _pmRoleQueryService.GetPmRoleList(gozareshgirRoleId); return new SelectList(rolse, "Id", "RoleName"); @@ -262,7 +264,7 @@ public class RoleApplication : IRoleApplication public async Task> GetPmRoleListToEdit(long? gozareshgirRoleId) { - return await _pmRoleRepository.GetPmRoleList(gozareshgirRoleId); + return await _pmRoleQueryService.GetPmRoleList(gozareshgirRoleId); } diff --git a/AccountManagement.Domain/AccountAgg/Account.cs b/AccountManagement.Domain/AccountAgg/Account.cs index 2b797142..253297ba 100644 --- a/AccountManagement.Domain/AccountAgg/Account.cs +++ b/AccountManagement.Domain/AccountAgg/Account.cs @@ -25,11 +25,6 @@ namespace AccountManagement.Domain.AccountAgg public string VerifyCode { get; set; } public string IsActiveString { get; private set; } - /// - /// آیا کاربر در پروگرام منیجر فعالیت می کند - /// - public bool IsProgramManagerUser { get; private set; } - #region Mahan public string PositionIsActive { get; private set; } public long? PositionId { get; private set; } @@ -40,7 +35,7 @@ namespace AccountManagement.Domain.AccountAgg public List CameraAccounts { get; private set; } public List AccountLeftWorkList { get; set; } public Account(string fullname, string username, string password, string mobile, - long roleId, string profilePhoto, string roleName, string adminAreaPermission, string clientAriaPermission, bool isProgramManagerUser) + long roleId, string profilePhoto, string roleName, string adminAreaPermission, string clientAriaPermission) { Fullname = fullname; Username = username; @@ -55,7 +50,6 @@ namespace AccountManagement.Domain.AccountAgg RoleName = roleName; AdminAreaPermission = adminAreaPermission; ClientAriaPermission = clientAriaPermission; - IsProgramManagerUser = isProgramManagerUser; IsActiveString = "true"; } @@ -76,20 +70,18 @@ namespace AccountManagement.Domain.AccountAgg public Account() { - ProfilePhoto = " "; } public void Edit(string fullname, string username, string mobile, - long roleId, string profilePhoto, string roleName, bool isProgramManagerUser) + long roleId, string profilePhoto, string roleName) { Fullname = fullname; Username = username; Mobile = mobile; RoleId = roleId; RoleName = roleName; - IsProgramManagerUser = isProgramManagerUser; if (!string.IsNullOrWhiteSpace(profilePhoto)) ProfilePhoto = profilePhoto; } diff --git a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj index 9d4d7e2c..7949f7dc 100644 --- a/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj +++ b/AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj @@ -20,4 +20,8 @@ + + + +
diff --git a/AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.Designer.cs b/AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.Designer.cs new file mode 100644 index 00000000..52bca3e8 --- /dev/null +++ b/AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.Designer.cs @@ -0,0 +1,1449 @@ +// +using System; +using AccountMangement.Infrastructure.EFCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace AccountMangement.Infrastructure.EFCore.Migrations +{ + [DbContext(typeof(AccountContext))] + [Migration("20251213143102_romoveIsProgramManagerUserFromAccount")] + partial class romoveIsProgramManagerUserFromAccount + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("AccountManagement.Domain.AccountAgg.Account", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AdminAreaPermission") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("ClientAriaPermission") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("Fullname") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActiveString") + .HasMaxLength(6) + .HasColumnType("nvarchar(6)"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("NationalCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("PositionId") + .HasMaxLength(10) + .HasColumnType("bigint"); + + b.Property("PositionIsActive") + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("ProfilePhoto") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("RoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("id"); + + b.HasIndex("PositionId"); + + b.HasIndex("RoleId"); + + b.ToTable("Accounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountLeftWorkAgg.AccountLeftWork", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("LeftWorkGr") + .HasColumnType("datetime2"); + + b.Property("RoleId") + .HasColumnType("bigint"); + + b.Property("StartWorkGr") + .HasColumnType("datetime2"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("AccountId"); + + b.ToTable("AccountLeftWork", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseAgg.AdminResponse", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AdminAccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActiveString") + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("Response") + .HasColumnType("ntext"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("TicketId"); + + b.ToTable("AdminResponses", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseMediaAgg.AdminResponseMedia", b => + { + b.Property("AdminResponseId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("AdminResponseId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("AdminResponseMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AssignAgg.Assign", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AcceptedTimeRequest") + .HasColumnType("int"); + + b.Property("AssignedId") + .HasColumnType("bigint"); + + b.Property("AssignedName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("AssignedPositionValue") + .HasColumnType("int"); + + b.Property("AssignerId") + .HasColumnType("bigint"); + + b.Property("AssignerPositionValue") + .HasColumnType("int"); + + b.Property("CancelDescription") + .HasColumnType("ntext"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DoneDescription") + .HasColumnType("ntext"); + + b.Property("EndTaskDate") + .HasColumnType("datetime2"); + + b.Property("FirstTimeCreation") + .HasColumnType("bit"); + + b.Property("IsCancel") + .HasColumnType("bit"); + + b.Property("IsCanceledRequest") + .HasColumnType("bit"); + + b.Property("IsDone") + .HasColumnType("bit"); + + b.Property("IsDoneRequest") + .HasColumnType("bit"); + + b.Property("RequestDate") + .HasColumnType("datetime2"); + + b.Property("TaskId") + .HasColumnType("bigint"); + + b.Property("TimeRequest") + .HasColumnType("bit"); + + b.Property("TimeRequestDescription") + .HasColumnType("ntext"); + + b.HasKey("id"); + + b.HasIndex("TaskId"); + + b.ToTable("Assigns", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.CameraAccountAgg.CameraAccount", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActiveSting") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("Mobile") + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.Property("WorkshopName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.HasIndex("AccountId"); + + b.ToTable("CameraAccounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseAgg.ClientResponse", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Response") + .HasColumnType("ntext"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("TicketId"); + + b.ToTable("ClientResponses", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseMediaAgg.ClientResponseMedia", b => + { + b.Property("ClientResponseId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("ClientResponseId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("ClientResponseMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.MediaAgg.Media", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Category") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Path") + .HasColumnType("ntext"); + + b.Property("ServiceName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Type") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("Medias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("GozareshgirRoleId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("PmRoles", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("Mobile") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("PositionName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PositionValue") + .HasMaxLength(2) + .HasColumnType("int"); + + b.HasKey("id"); + + b.ToTable("Positions", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountAgg.SubAccount", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("FName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsActive") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("LName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("NationalCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("ProfilePhoto") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("SubAccountRoleId") + .HasColumnType("bigint"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("VerifyCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.HasIndex("SubAccountRoleId"); + + b.ToTable("SubAccounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle1Agg.SubAccountPermissionSubtitle1", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.ToTable("SubAccountPermissionSubtitle1", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.HasIndex("ParentId"); + + b.ToTable("SubAccountPermissionSubtitle2", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.HasIndex("ParentId"); + + b.ToTable("SubAccountPermissionSubtitle3", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle4Agg.SubAccountPermissionSubtitle4", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Code") + .HasMaxLength(15) + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("id"); + + b.HasIndex("ParentId"); + + b.ToTable("SubAccountPermissionSubtitle4", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Title") + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("id"); + + b.ToTable("SubAccountRoles", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskAgg.Tasks", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("ContractingPartyName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("ntext"); + + b.Property("IsActiveString") + .HasMaxLength(7) + .HasColumnType("nvarchar(7)"); + + b.Property("SenderId") + .HasColumnType("bigint"); + + b.Property("StartTaskDate") + .HasColumnType("datetime2"); + + b.Property("TaskScheduleId") + .HasColumnType("bigint"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.HasIndex("TaskScheduleId"); + + b.ToTable("TasksManager", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMediaAgg.TaskMedia", b => + { + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("TaskId") + .HasColumnType("bigint"); + + b.HasKey("MediaId", "TaskId"); + + b.HasIndex("TaskId"); + + b.ToTable("TasksMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageAgg.TaskMessage", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AssignId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Message") + .HasColumnType("ntext"); + + b.Property("RequestedDateFa") + .HasMaxLength(25) + .HasColumnType("nvarchar(25)"); + + b.Property("TypeOfMessage") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.HasKey("id"); + + b.HasIndex("AssignId"); + + b.ToTable("TaskMessages", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageItemsAgg.TaskMessageItems", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ReceiverAccountId") + .HasColumnType("bigint"); + + b.Property("SenderAccountId") + .HasColumnType("bigint"); + + b.Property("TaskMessageId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.HasIndex("TaskMessageId"); + + b.ToTable("TaskMessageItems", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskScheduleAgg.TaskSchedule", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("Count") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("IsActive") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("LastEndTaskDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("UnitNumber") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("UnitType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("id"); + + b.ToTable("TaskSchedules", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskSubjectAgg.TaskSubject", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("id"); + + b.ToTable("TaskSubjects", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketAccessAccountAgg.TicketAccessAccount", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.HasKey("id"); + + b.ToTable("TicketAccessAccounts", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketAgg.Ticket", b => + { + b.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("id")); + + b.Property("ContractingPartyName") + .HasMaxLength(155) + .HasColumnType("nvarchar(155)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("ntext"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("SenderId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("SubAccountSenderId") + .HasColumnType("bigint"); + + b.Property("TicketNumber") + .HasMaxLength(12) + .HasColumnType("nvarchar(12)"); + + b.Property("TicketType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("WorkshopId") + .HasColumnType("bigint"); + + b.HasKey("id"); + + b.ToTable("Tickets", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketMediasAgg.TicketMedia", b => + { + b.Property("TicketId") + .HasColumnType("bigint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("TicketId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("TicketMedias", (string)null); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountAgg.Account", b => + { + b.HasOne("AccountManagement.Domain.PositionAgg.Position", "Position") + .WithMany("Accounts") + .HasForeignKey("PositionId"); + + b.HasOne("AccountManagement.Domain.RoleAgg.Role", "Role") + .WithMany("Accounts") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Position"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountLeftWorkAgg.AccountLeftWork", b => + { + b.HasOne("AccountManagement.Domain.AccountAgg.Account", "Account") + .WithMany("AccountLeftWorkList") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseAgg.AdminResponse", b => + { + b.HasOne("AccountManagement.Domain.TicketAgg.Ticket", "Ticket") + .WithMany("AdminResponses") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseMediaAgg.AdminResponseMedia", b => + { + b.HasOne("AccountManagement.Domain.AdminResponseAgg.AdminResponse", "AdminResponse") + .WithMany("AdminResponseMedias") + .HasForeignKey("AdminResponseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("AdminResponseMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AdminResponse"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AssignAgg.Assign", b => + { + b.HasOne("AccountManagement.Domain.TaskAgg.Tasks", "Task") + .WithMany("Assigns") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Task"); + }); + + modelBuilder.Entity("AccountManagement.Domain.CameraAccountAgg.CameraAccount", b => + { + b.HasOne("AccountManagement.Domain.AccountAgg.Account", "Account") + .WithMany("CameraAccounts") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseAgg.ClientResponse", b => + { + b.HasOne("AccountManagement.Domain.TicketAgg.Ticket", "Ticket") + .WithMany("ClientResponses") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseMediaAgg.ClientResponseMedia", b => + { + b.HasOne("AccountManagement.Domain.ClientResponseAgg.ClientResponse", "ClientResponse") + .WithMany("ClientResponseMedias") + .HasForeignKey("ClientResponseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("ClientResponseMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ClientResponse"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmRoleAgg.PmRole", b => + { + b.OwnsMany("AccountManagement.Domain.PmDomains.PmPermissionAgg.PmPermission", "PmPermission", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("Roleid") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("Roleid"); + + b1.ToTable("PmRolePermissions", null, t => + { + t.ExcludeFromMigrations(); + }); + + b1.WithOwner("Role") + .HasForeignKey("Roleid"); + + b1.Navigation("Role"); + }); + + b.Navigation("PmPermission"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PmDomains.PmUserAgg.PmUser", b => + { + b.OwnsMany("AccountManagement.Domain.PmDomains.PmRoleUserAgg.PmRoleUser", "RoleUser", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.Property("Userid") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("Userid"); + + b1.ToTable("RoleUsers", (string)null); + + b1.WithOwner("User") + .HasForeignKey("Userid"); + + b1.Navigation("User"); + }); + + b.Navigation("RoleUser"); + }); + + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => + { + b.OwnsMany("AccountManagement.Domain.RoleAgg.Permission", "Permissions", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("Code") + .HasColumnType("int"); + + b1.Property("RoleId") + .HasColumnType("bigint"); + + b1.HasKey("Id"); + + b1.HasIndex("RoleId"); + + b1.ToTable("RolePermissions", (string)null); + + b1.WithOwner("Role") + .HasForeignKey("RoleId"); + + b1.Navigation("Role"); + }); + + b.Navigation("Permissions"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountAgg.SubAccount", b => + { + b.HasOne("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", "SubAccountRole") + .WithMany("SubAccounts") + .HasForeignKey("SubAccountRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("SubAccountRole"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", b => + { + b.HasOne("AccountManagement.Domain.SubAccountPermissionSubtitle1Agg.SubAccountPermissionSubtitle1", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", b => + { + b.HasOne("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle4Agg.SubAccountPermissionSubtitle4", b => + { + b.HasOne("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", b => + { + b.OwnsMany("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRoleWorkshop", "RoleWorkshops", b1 => + { + b1.Property("SubAccountId") + .HasColumnType("bigint"); + + b1.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("id")); + + b1.Property("CreationDate") + .HasColumnType("datetime2"); + + b1.Property("WorkshopId") + .HasColumnType("bigint"); + + b1.HasKey("SubAccountId", "id"); + + b1.ToTable("SubAccountRoleWorkshop"); + + b1.WithOwner("SubAccountRole") + .HasForeignKey("SubAccountId"); + + b1.Navigation("SubAccountRole"); + }); + + b.OwnsMany("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRolePermission", "RolePermissions", b1 => + { + b1.Property("id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("id")); + + b1.Property("PermissionCode") + .HasColumnType("int"); + + b1.Property("SubAccountRoleId") + .HasColumnType("bigint"); + + b1.HasKey("id"); + + b1.HasIndex("SubAccountRoleId"); + + b1.ToTable("SubAccountRolePermissions", (string)null); + + b1.WithOwner("SubAccountRole") + .HasForeignKey("SubAccountRoleId"); + + b1.Navigation("SubAccountRole"); + }); + + b.Navigation("RolePermissions"); + + b.Navigation("RoleWorkshops"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskAgg.Tasks", b => + { + b.HasOne("AccountManagement.Domain.TaskScheduleAgg.TaskSchedule", "TaskSchedule") + .WithMany("TasksList") + .HasForeignKey("TaskScheduleId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("TaskSchedule"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMediaAgg.TaskMedia", b => + { + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("TaskMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.TaskAgg.Tasks", "Tasks") + .WithMany("TaskMedias") + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Tasks"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageAgg.TaskMessage", b => + { + b.HasOne("AccountManagement.Domain.AssignAgg.Assign", "Assign") + .WithMany("TaskMessageList") + .HasForeignKey("AssignId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assign"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageItemsAgg.TaskMessageItems", b => + { + b.HasOne("AccountManagement.Domain.TaskMessageAgg.TaskMessage", "TaskMessage") + .WithMany("TaskMessageItemsList") + .HasForeignKey("TaskMessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskMessage"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketMediasAgg.TicketMedia", b => + { + b.HasOne("AccountManagement.Domain.MediaAgg.Media", "Media") + .WithMany("TicketMedias") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AccountManagement.Domain.TicketAgg.Ticket", "Ticket") + .WithMany("TicketMedias") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AccountAgg.Account", b => + { + b.Navigation("AccountLeftWorkList"); + + b.Navigation("CameraAccounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AdminResponseAgg.AdminResponse", b => + { + b.Navigation("AdminResponseMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.AssignAgg.Assign", b => + { + b.Navigation("TaskMessageList"); + }); + + modelBuilder.Entity("AccountManagement.Domain.ClientResponseAgg.ClientResponse", b => + { + b.Navigation("ClientResponseMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.MediaAgg.Media", b => + { + b.Navigation("AdminResponseMedias"); + + b.Navigation("ClientResponseMedias"); + + b.Navigation("TaskMedias"); + + b.Navigation("TicketMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.PositionAgg.Position", b => + { + b.Navigation("Accounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.RoleAgg.Role", b => + { + b.Navigation("Accounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle1Agg.SubAccountPermissionSubtitle1", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle2Agg.SubAccountPermissionSubtitle2", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountPermissionSubtitle3Agg.SubAccountPermissionSubtitle3", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("AccountManagement.Domain.SubAccountRoleAgg.SubAccountRole", b => + { + b.Navigation("SubAccounts"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskAgg.Tasks", b => + { + b.Navigation("Assigns"); + + b.Navigation("TaskMedias"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskMessageAgg.TaskMessage", b => + { + b.Navigation("TaskMessageItemsList"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TaskScheduleAgg.TaskSchedule", b => + { + b.Navigation("TasksList"); + }); + + modelBuilder.Entity("AccountManagement.Domain.TicketAgg.Ticket", b => + { + b.Navigation("AdminResponses"); + + b.Navigation("ClientResponses"); + + b.Navigation("TicketMedias"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.cs b/AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.cs new file mode 100644 index 00000000..2a3a5929 --- /dev/null +++ b/AccountMangement.Infrastructure.EFCore/Migrations/20251213143102_romoveIsProgramManagerUserFromAccount.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AccountMangement.Infrastructure.EFCore.Migrations +{ + /// + public partial class romoveIsProgramManagerUserFromAccount : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsProgramManagerUser", + table: "Accounts"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsProgramManagerUser", + table: "Accounts", + type: "bit", + nullable: false, + defaultValue: false); + } + } +} diff --git a/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs b/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs index ca6c5c8d..800be041 100644 --- a/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs +++ b/AccountMangement.Infrastructure.EFCore/Migrations/AccountContextModelSnapshot.cs @@ -54,9 +54,6 @@ namespace AccountMangement.Infrastructure.EFCore.Migrations .HasMaxLength(6) .HasColumnType("nvarchar(6)"); - b.Property("IsProgramManagerUser") - .HasColumnType("bit"); - b.Property("Mobile") .IsRequired() .HasMaxLength(20) diff --git a/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs b/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs index 4e0a4dc4..1947a65b 100644 --- a/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs +++ b/AccountMangement.Infrastructure.EFCore/Repository/AccountRepository.cs @@ -46,8 +46,7 @@ public class AccountRepository : RepositoryBase, IAccountReposito Mobile = x.Mobile, RoleId = x.RoleId, Username = x.Username, - IsActiveString = x.IsActiveString, - IsProgramManagerUser = x.IsProgramManagerUser, + IsActiveString = x.IsActiveString }).FirstOrDefault(x => x.Id == id); } diff --git a/CompanyManagment.EFCore/Services/HolidayQueryService.cs b/CompanyManagment.EFCore/Services/HolidayQueryService.cs new file mode 100644 index 00000000..4b8aa51c --- /dev/null +++ b/CompanyManagment.EFCore/Services/HolidayQueryService.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Shared.Contracts.Holidays; + +namespace CompanyManagment.EFCore.Services; + +public class HolidayQueryService : IHolidayQueryService +{ + public Task> GetHolidaysInDates(DateTime startDate, DateTime endDate) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/PersonalContractingParty.Config/PersonalBootstrapper.cs b/PersonalContractingParty.Config/PersonalBootstrapper.cs index a9ee5eae..3988ea58 100644 --- a/PersonalContractingParty.Config/PersonalBootstrapper.cs +++ b/PersonalContractingParty.Config/PersonalBootstrapper.cs @@ -1,18 +1,44 @@ -using System; +using _0_Framework.Application.FaceEmbedding; using _0_Framework.Application.UID; +using _0_Framework.Infrastructure; +using _0_Framework.InfraStructure; using Company.Application.Contracts.AuthorizedBankDetails; +using Company.Domain._common; +using Company.Domain.AdminMonthlyOverviewAgg; +using Company.Domain.AndroidApkVersionAgg; +using Company.Domain.AuthorizedBankDetailsAgg; +using Company.Domain.AuthorizedPersonAgg; +using Company.Domain.BankAgg; using Company.Domain.BillAgg; using Company.Domain.Board; using Company.Domain.ChapterAgg; using Company.Domain.CheckoutAgg; using Company.Domain.ClassifiedSalaryAgg; using Company.Domain.Contact2Agg; -using Company.Domain.CrossJobAgg; -using Company.Domain.CrossJobGuildAgg; +using Company.Domain.ContactUsAgg; using Company.Domain.ContarctingPartyAgg; using Company.Domain.ContractAgg; +using Company.Domain.ContractingPartyBankAccountsAgg; +using Company.Domain.CrossJobAgg; +using Company.Domain.CrossJobGuildAgg; +using Company.Domain.CrossJobItemsAgg; +using Company.Domain.CustomizeCheckoutAgg; +using Company.Domain.CustomizeCheckoutTempAgg; +using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg; +using Company.Domain.CustomizeWorkshopGroupSettingsAgg; +using Company.Domain.CustomizeWorkshopSettingsAgg; +using Company.Domain.DateSalaryAgg; +using Company.Domain.DateSalaryItemAgg; using Company.Domain.EmployeeAgg; +using Company.Domain.EmployeeAuthorizeTempAgg; +using Company.Domain.EmployeeBankInformationAgg; using Company.Domain.EmployeeChildrenAgg; +using Company.Domain.EmployeeClientTempAgg; +using Company.Domain.EmployeeComputeOptionsAgg; +using Company.Domain.EmployeeDocumentItemAgg; +using Company.Domain.EmployeeDocumentsAdminSelectionAgg; +using Company.Domain.EmployeeDocumentsAgg; +using Company.Domain.EmployeeFaceEmbeddingAgg; using Company.Domain.empolyerAgg; using Company.Domain.Evidence; using Company.Domain.EvidenceDetail; @@ -23,38 +49,108 @@ using Company.Domain.FileEmployerAgg; using Company.Domain.FileState; using Company.Domain.FileTiming; using Company.Domain.FileTitle; +using Company.Domain.FinancialInvoiceAgg; +using Company.Domain.FinancialStatmentAgg; +using Company.Domain.FinancialTransactionAgg; +using Company.Domain.FineAgg; +using Company.Domain.FineSubjectAgg; +using Company.Domain.GroupPlanAgg; +using Company.Domain.GroupPlanJobItemAgg; using Company.Domain.HolidayAgg; using Company.Domain.HolidayItemAgg; +using Company.Domain.InstitutionContractAgg; +using Company.Domain.InstitutionContractContactInfoAgg; +using Company.Domain.InstitutionContractExtensionTempAgg; +using Company.Domain.InstitutionPlanAgg; +using Company.Domain.InsuranceAgg; +using Company.Domain.InsuranceEmployeeInfoAgg; +using Company.Domain.InsuranceJobItemAgg; +using Company.Domain.InsuranceListAgg; +using Company.Domain.InsuranceYearlySalaryAgg; +using Company.Domain.InsurancJobAgg; +using Company.Domain.InsurancWorkshopInfoAgg; using Company.Domain.JobAgg; +using Company.Domain.LawAgg; using Company.Domain.LeaveAgg; using Company.Domain.LeftWorkAgg; +using Company.Domain.LeftWorkInsuranceAgg; +using Company.Domain.LeftWorkTempAgg; +using Company.Domain.LoanAgg; using Company.Domain.MandatoryHoursAgg; using Company.Domain.MasterPenaltyTitle; using Company.Domain.MasterPetition; using Company.Domain.MasterWorkHistory; using Company.Domain.ModuleAgg; using Company.Domain.OriginalTitleAgg; +using Company.Domain.PaymentInstrumentAgg; +using Company.Domain.PaymentToEmployeeAgg; +using Company.Domain.PaymentToEmployeeItemAgg; +using Company.Domain.PaymentTransactionAgg; using Company.Domain.PenaltyTitle; +using Company.Domain.PercentageAgg; +using Company.Domain.PersonnelCodeAgg; using Company.Domain.Petition; using Company.Domain.ProceedingSession; +using Company.Domain.ReportAgg; +using Company.Domain.ReportClientAgg; using Company.Domain.RepresentativeAgg; +using Company.Domain.RewardAgg; +using Company.Domain.RollCallAgg; +using Company.Domain.RollCallAgg.DomainService; +using Company.Domain.RollCallEmployeeAgg; +using Company.Domain.RollCallEmployeeStatusAgg; +using Company.Domain.RollCallPlanAgg; +using Company.Domain.RollCallServiceAgg; +using Company.Domain.SalaryAidAgg; +using Company.Domain.SmsResultAgg; using Company.Domain.SubtitleAgg; +using Company.Domain.TaxJobCategoryAgg; +using Company.Domain.TemporaryClientRegistrationAgg; using Company.Domain.WorkHistory; using Company.Domain.WorkingHoursAgg; using Company.Domain.WorkingHoursItemsAgg; +using Company.Domain.WorkingHoursTempAgg; +using Company.Domain.WorkingHoursTempItemAgg; +using Company.Domain.WorkshopAccountAgg; using Company.Domain.WorkshopAgg; +using Company.Domain.WorkshopPlanAgg; +using Company.Domain.WorkshopPlanEmployeeAgg; +using Company.Domain.WorkshopSubAccountAgg; using Company.Domain.YearlySalaryAgg; using Company.Domain.YearlySalaryItemsAgg; using Company.Domain.YearlysSalaryTitleAgg; +using Company.Domain.ZoneAgg; +using CompanyManagement.Infrastructure.Excel.SalaryAid; +using CompanyManagement.Infrastructure.Mongo.EmployeeFaceEmbeddingRepo; +using CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo; +using CompanyManagment.App.Contracts.AdminMonthlyOverview; +using CompanyManagment.App.Contracts.AndroidApkVersion; +using CompanyManagment.App.Contracts.AuthorizedPerson; +using CompanyManagment.App.Contracts.Bank; using CompanyManagment.App.Contracts.Board; using CompanyManagment.App.Contracts.Chapter; using CompanyManagment.App.Contracts.Checkout; +using CompanyManagment.App.Contracts.ClassifiedSalary; using CompanyManagment.App.Contracts.Contact2; +using CompanyManagment.App.Contracts.ContactUs; using CompanyManagment.App.Contracts.Contract; +using CompanyManagment.App.Contracts.ContractingPartyBankAccounts; using CompanyManagment.App.Contracts.CrossJob; using CompanyManagment.App.Contracts.CrossJobGuild; +using CompanyManagment.App.Contracts.CrossJobItems; +using CompanyManagment.App.Contracts.CustomizeCheckout; +using CompanyManagment.App.Contracts.CustomizeWorkshopSettings; +using CompanyManagment.App.Contracts.DateSalary; +using CompanyManagment.App.Contracts.DateSalaryItem; using CompanyManagment.App.Contracts.Employee; +using CompanyManagment.App.Contracts.EmployeeBankInformation; using CompanyManagment.App.Contracts.EmployeeChildren; +using CompanyManagment.App.Contracts.EmployeeClientTemp; +using CompanyManagment.App.Contracts.EmployeeComputeOptions; +using CompanyManagment.App.Contracts.EmployeeDocuments; +using CompanyManagment.App.Contracts.EmployeeDocumentsAdminSelection; +using CompanyManagment.App.Contracts.EmployeeFaceEmbedding; +using CompanyManagment.App.Contracts.EmployeeInsurancListData; using CompanyManagment.App.Contracts.Employer; using CompanyManagment.App.Contracts.Evidence; using CompanyManagment.App.Contracts.EvidenceDetail; @@ -65,176 +161,82 @@ using CompanyManagment.App.Contracts.FileEmployer; using CompanyManagment.App.Contracts.FileState; using CompanyManagment.App.Contracts.FileTiming; using CompanyManagment.App.Contracts.FileTitle; +using CompanyManagment.App.Contracts.FinancialInvoice; +using CompanyManagment.App.Contracts.FinancialStatment; +using CompanyManagment.App.Contracts.FinancilTransaction; +using CompanyManagment.App.Contracts.Fine; +using CompanyManagment.App.Contracts.FineSubject; using CompanyManagment.App.Contracts.Holiday; using CompanyManagment.App.Contracts.HolidayItem; +using CompanyManagment.App.Contracts.InstitutionContract; +using CompanyManagment.App.Contracts.InstitutionContractContactinfo; +using CompanyManagment.App.Contracts.InstitutionPlan; +using CompanyManagment.App.Contracts.Insurance; +using CompanyManagment.App.Contracts.InsuranceEmployeeInfo; +using CompanyManagment.App.Contracts.InsuranceJob; +using CompanyManagment.App.Contracts.InsuranceList; +using CompanyManagment.App.Contracts.InsuranceWorkshopInfo; +using CompanyManagment.App.Contracts.InsuranceYearlySalary; using CompanyManagment.App.Contracts.Job; +using CompanyManagment.App.Contracts.Law; using CompanyManagment.App.Contracts.Leave; using CompanyManagment.App.Contracts.LeftWork; +using CompanyManagment.App.Contracts.LeftWorkInsurance; +using CompanyManagment.App.Contracts.LeftWorkTemp; +using CompanyManagment.App.Contracts.Loan; using CompanyManagment.App.Contracts.MandantoryHours; using CompanyManagment.App.Contracts.MasterPenaltyTitle; using CompanyManagment.App.Contracts.MasterPetition; using CompanyManagment.App.Contracts.MasterWorkHistory; using CompanyManagment.App.Contracts.Module; using CompanyManagment.App.Contracts.OriginalTitle; +using CompanyManagment.App.Contracts.PaymentInstrument; +using CompanyManagment.App.Contracts.PaymentToEmployee; +using CompanyManagment.App.Contracts.PaymentTransaction; using CompanyManagment.App.Contracts.PenaltyTitle; +using CompanyManagment.App.Contracts.Percentage; using CompanyManagment.App.Contracts.PersonalContractingParty; +using CompanyManagment.App.Contracts.PersonnleCode; using CompanyManagment.App.Contracts.Petition; using CompanyManagment.App.Contracts.ProceedingSession; +using CompanyManagment.App.Contracts.Report; +using CompanyManagment.App.Contracts.ReportClient; using CompanyManagment.App.Contracts.Representative; +using CompanyManagment.App.Contracts.Reward; +using CompanyManagment.App.Contracts.RollCall; +using CompanyManagment.App.Contracts.RollCallEmployee; +using CompanyManagment.App.Contracts.RollCallEmployeeStatus; +using CompanyManagment.App.Contracts.RollCallPlan; +using CompanyManagment.App.Contracts.RollCallService; +using CompanyManagment.App.Contracts.SalaryAid; +using CompanyManagment.App.Contracts.SmsResult; using CompanyManagment.App.Contracts.Subtitle; +using CompanyManagment.App.Contracts.TaxJobCategory; +using CompanyManagment.App.Contracts.TemporaryClientRegistration; using CompanyManagment.App.Contracts.TextManager; using CompanyManagment.App.Contracts.WorkHistory; using CompanyManagment.App.Contracts.WorkingHours; using CompanyManagment.App.Contracts.WorkingHoursItems; +using CompanyManagment.App.Contracts.WorkingHoursTemp; +using CompanyManagment.App.Contracts.WorkingHoursTempItem; using CompanyManagment.App.Contracts.Workshop; +using CompanyManagment.App.Contracts.WorkshopPlan; using CompanyManagment.App.Contracts.YearlySalary; using CompanyManagment.App.Contracts.YearlySalaryItems; using CompanyManagment.App.Contracts.YearlySalaryTitles; +using CompanyManagment.App.Contracts.Zone; using CompanyManagment.Application; using CompanyManagment.EFCore; +using CompanyManagment.EFCore._common; +using CompanyManagment.EFCore.Repository; using CompanyManagment.EFCore.Repository; using File.EfCore.Repository; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using P_TextManager.Domin.TextManagerAgg; -using CompanyManagment.App.Contracts.CrossJobItems; -using Company.Domain.CrossJobItemsAgg; -using Company.Domain.DateSalaryAgg; -using Company.Domain.DateSalaryItemAgg; -using Company.Domain.FinancialStatmentAgg; -using Company.Domain.FinancialTransactionAgg; -using Company.Domain.GroupPlanAgg; -using Company.Domain.GroupPlanJobItemAgg; -using Company.Domain.InstitutionContractAgg; -using Company.Domain.InstitutionContractContactInfoAgg; -using CompanyManagment.App.Contracts.Insurance; -using Company.Domain.InsuranceAgg; -using Company.Domain.InsuranceEmployeeInfoAgg; -using Company.Domain.InsuranceJobItemAgg; -using Company.Domain.InsuranceListAgg; -using Company.Domain.InsurancJobAgg; -using Company.Domain.InsurancWorkshopInfoAgg; -using Company.Domain.LeftWorkInsuranceAgg; -using Company.Domain.PaymentToEmployeeAgg; -using Company.Domain.PaymentToEmployeeItemAgg; -using Company.Domain.PercentageAgg; -using Company.Domain.PersonnelCodeAgg; -using Company.Domain.SmsResultAgg; -using Company.Domain.WorkingHoursTempAgg; -using Company.Domain.WorkingHoursTempItemAgg; -using Company.Domain.WorkshopPlanAgg; -using Company.Domain.WorkshopPlanEmployeeAgg; -using Company.Domain.ZoneAgg; -using CompanyManagment.App.Contracts.ClassifiedSalary; -using CompanyManagment.App.Contracts.DateSalary; -using CompanyManagment.App.Contracts.DateSalaryItem; -using CompanyManagment.App.Contracts.EmployeeInsurancListData; -using CompanyManagment.App.Contracts.FinancialStatment; -using CompanyManagment.App.Contracts.FinancilTransaction; -using CompanyManagment.App.Contracts.InstitutionContract; -using CompanyManagment.App.Contracts.InstitutionContractContactinfo; -using CompanyManagment.App.Contracts.InsuranceEmployeeInfo; -using CompanyManagment.App.Contracts.InsuranceJob; -using CompanyManagment.App.Contracts.InsuranceList; -using CompanyManagment.App.Contracts.InsuranceWorkshopInfo; -using CompanyManagment.App.Contracts.LeftWorkInsurance; -using CompanyManagment.App.Contracts.PaymentToEmployee; -using CompanyManagment.App.Contracts.Percentage; -using CompanyManagment.App.Contracts.PersonnleCode; -using CompanyManagment.App.Contracts.SmsResult; -using CompanyManagment.App.Contracts.WorkingHoursTemp; -using CompanyManagment.App.Contracts.WorkingHoursTempItem; -using CompanyManagment.App.Contracts.WorkshopPlan; -using CompanyManagment.App.Contracts.Zone; -using CompanyManagment.App.Contracts.EmployeeComputeOptions; -using Company.Domain.EmployeeComputeOptionsAgg; -using Company.Domain.InsuranceYearlySalaryAgg; -using Company.Domain.ReportAgg; -using Company.Domain.RollCallAgg; -using Company.Domain.RollCallEmployeeAgg; -using Company.Domain.RollCallPlanAgg; -using Company.Domain.RollCallServiceAgg; -using CompanyManagment.App.Contracts.InsuranceYearlySalary; -using CompanyManagment.App.Contracts.Report; -using CompanyManagment.App.Contracts.RollCall; -using CompanyManagment.App.Contracts.RollCallEmployee; -using CompanyManagment.App.Contracts.RollCallService; -using CompanyManagment.App.Contracts.RollCallPlan; -using Company.Domain.ReportClientAgg; -using Company.Domain.TaxJobCategoryAgg; -using Company.Domain.WorkshopAccountAgg; -using CompanyManagment.App.Contracts.ReportClient; -using CompanyManagment.App.Contracts.TaxJobCategory; -using Company.Domain.RollCallEmployeeStatusAgg; -using CompanyManagment.App.Contracts.RollCallEmployeeStatus; -using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg; -using Company.Domain.CustomizeWorkshopGroupSettingsAgg; -using Company.Domain.CustomizeWorkshopSettingsAgg; -using Company.Domain.FineAgg; -using Company.Domain.LoanAgg; -using Company.Domain.RewardAgg; -using Company.Domain.SalaryAidAgg; -using CompanyManagment.App.Contracts.CustomizeWorkshopSettings; -using CompanyManagment.App.Contracts.Fine; -using CompanyManagment.App.Contracts.Loan; -using CompanyManagment.App.Contracts.Reward; -using CompanyManagment.App.Contracts.SalaryAid; -using Company.Domain.AndroidApkVersionAgg; -using Company.Domain.BankAgg; -using CompanyManagment.App.Contracts.AndroidApkVersion; -using Company.Domain.FineSubjectAgg; -using CompanyManagment.App.Contracts.FineSubject; -using Company.Domain.CustomizeCheckoutAgg; -using CompanyManagment.App.Contracts.CustomizeCheckout; -using Company.Domain.WorkshopSubAccountAgg; -using Company.Domain.CustomizeCheckoutTempAgg; -using Company.Domain.EmployeeBankInformationAgg; -using Company.Domain.RollCallAgg.DomainService; -using CompanyManagment.App.Contracts.Bank; -using CompanyManagment.App.Contracts.EmployeeBankInformation; -using Company.Domain.EmployeeDocumentItemAgg; -using Company.Domain.EmployeeDocumentsAdminSelectionAgg; -using Company.Domain.EmployeeDocumentsAgg; -using CompanyManagement.Infrastructure.Excel.SalaryAid; -using CompanyManagment.App.Contracts.EmployeeDocuments; -using CompanyManagment.App.Contracts.EmployeeDocumentsAdminSelection; -using Company.Domain.EmployeeClientTempAgg; -using Company.Domain.InstitutionPlanAgg; -using Company.Domain.LeftWorkTempAgg; -using Company.Domain.TemporaryClientRegistrationAgg; -using CompanyManagment.App.Contracts.EmployeeClientTemp; -using CompanyManagment.App.Contracts.InstitutionPlan; -using CompanyManagment.App.Contracts.LeftWorkTemp; -using CompanyManagment.App.Contracts.TemporaryClientRegistration; -using Company.Domain.ContactUsAgg; -using CompanyManagment.App.Contracts.ContactUs; -using Company.Domain.EmployeeAuthorizeTempAgg; -using Company.Domain.AdminMonthlyOverviewAgg; -using Company.Domain.AuthorizedBankDetailsAgg; -using Company.Domain.ContractingPartyBankAccountsAgg; -using Company.Domain.PaymentInstrumentAgg; -using Company.Domain.PaymentTransactionAgg; -using Company.Domain.FinancialInvoiceAgg; -using CompanyManagment.App.Contracts.AdminMonthlyOverview; -using CompanyManagment.App.Contracts.ContractingPartyBankAccounts; -using CompanyManagment.App.Contracts.PaymentInstrument; -using CompanyManagment.App.Contracts.PaymentTransaction; -using CompanyManagment.App.Contracts.AuthorizedPerson; -using Company.Domain.AuthorizedPersonAgg; -using Company.Domain.EmployeeFaceEmbeddingAgg; -using Company.Domain.InstitutionContractExtensionTempAgg; -using Company.Domain.LawAgg; -using CompanyManagement.Infrastructure.Mongo.EmployeeFaceEmbeddingRepo; -using CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo; -using CompanyManagment.App.Contracts.EmployeeFaceEmbedding; -using CompanyManagment.App.Contracts.Law; -using CompanyManagment.EFCore.Repository; -using CompanyManagment.App.Contracts.FinancialInvoice; -using _0_Framework.Application.FaceEmbedding; -using _0_Framework.Infrastructure; -using _0_Framework.InfraStructure; -using Company.Domain._common; -using CompanyManagment.EFCore._common; +using Shared.Contracts.Holidays; +using System; +using CompanyManagment.EFCore.Services; namespace PersonalContractingParty.Config; @@ -242,6 +244,12 @@ public class PersonalBootstrapper { public static void Configure(IServiceCollection services, string connectionString) { + + #region Services + + services.AddTransient(); + + #endregion //----Task-Manager-Project--------------------------------- //services.AddTransient(); diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs index 5d73a0b3..ae816e1a 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -1,29 +1,31 @@ +using FluentValidation; using GozareshgirProgramManager.Application._Common.Behaviors; using GozareshgirProgramManager.Application._Common.Interfaces; using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.CheckoutAgg.Repositories; using GozareshgirProgramManager.Domain.CustomerAgg.Repositories; using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; using GozareshgirProgramManager.Domain.RoleAgg.Repositories; +using GozareshgirProgramManager.Domain.RoleAgg.Repositories; using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; +using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories; +using GozareshgirProgramManager.Domain.SkillAgg.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 GozareshgirProgramManager.Infrastructure.Services.Role; 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; +using Shared.Contracts.PmRole.Commands; +using Shared.Contracts.PmRole.Queries; namespace GozareshgirProgramManager.Infrastructure; @@ -83,9 +85,17 @@ public static class DependencyInjection // Authentication Services services.AddScoped(); services.AddScoped(); - - - + + + + #region ServicesInjection + + services.AddTransient(); + + services.AddTransient(); + + #endregion + // MediatR Validation Behavior services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs new file mode 100644 index 00000000..09d551f4 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs @@ -0,0 +1,28 @@ +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Application.Modules.Roles.Commands.CreateRole; +using MediatR; +using Shared.Contracts.PmRole.Commands; + +namespace GozareshgirProgramManager.Infrastructure.Services.Role; + +public class PmRoleCommandService: IPmRoleCommandService +{ + private readonly IMediator _mediator; + + public PmRoleCommandService(IMediator mediator) + { + _mediator = mediator; + } + + + + public async Task<(bool, string)> Create(CreatePmRoleDto command) + { + var request = new CreateRoleCommand + { + RoleName = command.RoleName, Permissions = command.Permissions, GozareshgirRoleId = command.GozareshgirRoleId + }; + var res = await _mediator.Send(request); + return (res.IsSuccess, res.ErrorMessage); + } +} \ No newline at end of file diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleQueryService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleQueryService.cs new file mode 100644 index 00000000..1f863f27 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleQueryService.cs @@ -0,0 +1,34 @@ +using GozareshgirProgramManager.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using Shared.Contracts.PmRole.Queries; + +namespace GozareshgirProgramManager.Infrastructure.Services.Role; + +public class PmRoleQueryService : IPmRoleQueryService +{ + private readonly ProgramManagerDbContext _programManagerDbContext; + + public PmRoleQueryService(ProgramManagerDbContext programManagerDbContext) + { + _programManagerDbContext = programManagerDbContext; + } + + public async Task> GetPmRoleList(long? gozareshgirRoleId) + { + var query = _programManagerDbContext.Roles.AsQueryable(); + if (gozareshgirRoleId != null && gozareshgirRoleId > 0) + query = query.Where(x => x.GozareshgirRoleId == gozareshgirRoleId); + var res = await query + .Select(p => new GetPmRolesDto() + { + Id = p.Id, + RoleName = p.RoleName, + GozareshgirRoleId = p.GozareshgirRoleId, + Permissions = p.Permissions.Select(x => x.Code).ToList() + + }) + .ToListAsync(); + + return res; + } +} \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml index 23e201b4..4819c826 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Create.cshtml @@ -142,7 +142,7 @@
- @*
+
+ `); + pmIndex++; + } else { $("#hiddenInput").append(` `); normalIndex++; - // const isPm = chk.hasAttribute("data-pm"); - - // if (isPm) { - // $("#hiddenInput").append(` - // - // `); - // pmIndex++; - // } else { - // $("#hiddenInput").append(` - // - // `); - // normalIndex++; - // } + } }); diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml index c3918b66..cfcf1bab 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Edit.cshtml @@ -146,7 +146,7 @@
-@*
+
@if (Model.IsProgramManagerUser) @@ -165,7 +165,7 @@ -
*@ +
diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml index 8f0688a9..da948964 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/EditRole.cshtml @@ -1363,35 +1363,30 @@ function saveRole() { const checks = document.querySelectorAll("input.check-btn"); - //let pmIndex = 0; + let pmIndex = 0; let normalIndex = 0; $("#hiddenInput").empty(); // مهم!! قبل از اضافه‌کردن، خالی کن checks.forEach(chk => { - $("#hiddenInput").append(` + + const isPm = chk.hasAttribute("data-pm"); + + if (isPm) { + $("#hiddenInput").append(` + + `); + pmIndex++; + } else { + $("#hiddenInput").append(` `); normalIndex++; - // const isPm = chk.hasAttribute("data-pm"); - - // if (isPm) { - // $("#hiddenInput").append(` - // - // `); - // pmIndex++; - // } else { - // $("#hiddenInput").append(` - // - // `); - // normalIndex++; - // } + } }); diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml index 900be1d3..92dca681 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml @@ -1,4 +1,6 @@ @page +@using CompanyManagment.App.Contracts.PersonalContractingParty +@using Microsoft.EntityFrameworkCore @using _0_Framework.Application @model ServiceHost.Areas.Admin.Pages.Accounts.Account.IndexModel @inject IAuthHelper _AuthHelper; diff --git a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs index f7f192db..e4597d4f 100644 --- a/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs +++ b/ServiceHost/Areas/Admin/Pages/Accounts/Account/Index.cshtml.cs @@ -121,22 +121,22 @@ public class IndexModel : PageModel //); - //var result = _accountApplication.GetPmUserByAccountId(account.Id).GetAwaiter().GetResult(); + var result = _accountApplication.GetPmUserByAccountId(account.Id).GetAwaiter().GetResult(); - //// مثل قبل: - //if (result != null) - //{ - // account.IsProgramManagerUser = (result.AccountId== account.Id && result.IsActive); - // account.UserRoles = result.Roles; - //} - //else - //{ - // account.IsProgramManagerUser = false; - //} + // مثل قبل: + if (result != null) + { + account.IsProgramManagerUser = (result.AccountId== account.Id && result.IsActive); + account.UserRoles = result.Roles; + } + else + { + account.IsProgramManagerUser = false; + } - //var pmRolseSelectList = _roleApplication.GetPmRoleList(null).GetAwaiter().GetResult(); - //account.RoleList = pmRolseSelectList; + var pmRolseSelectList = _roleApplication.GetPmRoleList(null).GetAwaiter().GetResult(); + account.RoleList = pmRolseSelectList; //var response = InternalApiCaller.GetAsync( // "api/role", diff --git a/Shared.Contracts/PmRole/Commands/CreatePmRoleDto.cs b/Shared.Contracts/PmRole/Commands/CreatePmRoleDto.cs new file mode 100644 index 00000000..62edf3b6 --- /dev/null +++ b/Shared.Contracts/PmRole/Commands/CreatePmRoleDto.cs @@ -0,0 +1,9 @@ +namespace Shared.Contracts.PmRole.Commands; + +public record CreatePmRoleDto +{ + public string RoleName { get; set; } + public List Permissions { get; set; } + + public long? GozareshgirRoleId { get; set; } +}; \ No newline at end of file diff --git a/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs b/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs new file mode 100644 index 00000000..3bd9e586 --- /dev/null +++ b/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs @@ -0,0 +1,6 @@ +namespace Shared.Contracts.PmRole.Commands; + +public interface IPmRoleCommandService +{ + Task<(bool, string)> Create(CreatePmRoleDto command); +} \ No newline at end of file diff --git a/Shared.Contracts/PmRole/Queries/GetPmRolesDto.cs b/Shared.Contracts/PmRole/Queries/GetPmRolesDto.cs new file mode 100644 index 00000000..2bd131a2 --- /dev/null +++ b/Shared.Contracts/PmRole/Queries/GetPmRolesDto.cs @@ -0,0 +1,24 @@ +namespace Shared.Contracts.PmRole.Queries; + +public record GetPmRolesDto +{ + /// + /// آی دی نقش + /// + public long Id { get; set; } + + /// + /// نام نقش + /// + public string RoleName { get; set; } + + /// + /// آی دی نقش در گزارشگیر + /// + public long? GozareshgirRoleId { get; set; } + + /// + /// لیست کدهای دسترسی + /// + public List Permissions { get; set; } +}; \ No newline at end of file diff --git a/Shared.Contracts/PmRole/Queries/IPmRoleQueryService.cs b/Shared.Contracts/PmRole/Queries/IPmRoleQueryService.cs new file mode 100644 index 00000000..fef7ad2e --- /dev/null +++ b/Shared.Contracts/PmRole/Queries/IPmRoleQueryService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Shared.Contracts.PmRole.Queries; + +public interface IPmRoleQueryService +{ + Task> GetPmRoleList(long? gozareshgirRoleId); +} + + From 58816ca38374347bf92103f48a3aca2ca170176a Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 18:38:08 +0330 Subject: [PATCH 11/15] feat: implement PmUserQueryService and integrate into AccountApplication for user ID retrieval --- 0_Framework/Application/AuthHelper.cs | 3 ++- 0_Framework/Application/AuthViewModel.cs | 5 ++++- .../AccountApplication.cs | 10 +++++++-- .../Services/User/PmUserQueryService.cs | 22 +++++++++++++++++++ .../PmUser/IPmUserQueryService.cs | 6 +++++ 5 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs create mode 100644 Shared.Contracts/PmUser/IPmUserQueryService.cs diff --git a/0_Framework/Application/AuthHelper.cs b/0_Framework/Application/AuthHelper.cs index ef510830..12f820f8 100644 --- a/0_Framework/Application/AuthHelper.cs +++ b/0_Framework/Application/AuthHelper.cs @@ -198,7 +198,8 @@ public class AuthHelper : IAuthHelper new("workshopList",workshopBson), new("WorkshopSlug",slug), new("WorkshopId", account.WorkshopId.ToString()), - new("WorkshopName",account.WorkshopName??"") + new("WorkshopName",account.WorkshopName??""), + new("pm.userId", account.PmUserId?.ToString() ?? "0"), }; diff --git a/0_Framework/Application/AuthViewModel.cs b/0_Framework/Application/AuthViewModel.cs index d419bd67..aebda696 100644 --- a/0_Framework/Application/AuthViewModel.cs +++ b/0_Framework/Application/AuthViewModel.cs @@ -27,10 +27,12 @@ public class AuthViewModel #endregion public long SubAccountId { get; set; } + public long? PmUserId { get; set; } public AuthViewModel(long id, long roleId, string fullname, string username, string mobile,string profilePhoto, - List permissions, string roleName, string adminAreaPermission, string clientAriaPermission, int? positionValue, long subAccountId = 0) + List permissions, string roleName, string adminAreaPermission, string clientAriaPermission, int? positionValue, + long subAccountId = 0,long? pmUserId = null) { Id = id; RoleId = roleId; @@ -44,6 +46,7 @@ public class AuthViewModel ClientAriaPermission = clientAriaPermission; PositionValue = positionValue; SubAccountId = subAccountId; + PmUserId = pmUserId; } public AuthViewModel() diff --git a/AccountManagement.Application/AccountApplication.cs b/AccountManagement.Application/AccountApplication.cs index bba09128..8676a795 100644 --- a/AccountManagement.Application/AccountApplication.cs +++ b/AccountManagement.Application/AccountApplication.cs @@ -34,6 +34,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using AccountManagement.Application.Contracts.ProgramManager; +using Shared.Contracts.PmUser; using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; //using AccountManagement.Domain.RoleAgg; @@ -58,9 +59,10 @@ public class AccountApplication : IAccountApplication private readonly ISubAccountPermissionSubtitle1Repository _accountPermissionSubtitle1Repository; private readonly IPmUserRepository _pmUserRepository; private readonly IUnitOfWork _unitOfWork; + private readonly IPmUserQueryService _pmUserQueryService; public AccountApplication(IAccountRepository accountRepository, IPasswordHasher passwordHasher, - IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserRepository pmUserRepository) + IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserRepository pmUserRepository, IPmUserQueryService pmUserQueryService) { _authHelper = authHelper; _roleRepository = roleRepository; @@ -75,6 +77,7 @@ public class AccountApplication : IAccountApplication _accountPermissionSubtitle1Repository = accountPermissionSubtitle1Repository; _unitOfWork = unitOfWork; _pmUserRepository = pmUserRepository; + _pmUserQueryService = pmUserQueryService; _fileUploader = fileUploader; _passwordHasher = passwordHasher; _accountRepository = accountRepository; @@ -463,8 +466,11 @@ public class AccountApplication : IAccountApplication { positionValue = null; } + var pmUserId = _pmUserQueryService.GetCurrentPmUserIdFromAccountId(account.id).GetAwaiter().GetResult(); var authViewModel = new AuthViewModel(account.id, account.RoleId, account.Fullname - , account.Username, account.Mobile, account.ProfilePhoto, permissions, account.RoleName, account.AdminAreaPermission, account.ClientAriaPermission, positionValue); + , account.Username, account.Mobile, account.ProfilePhoto, + permissions, account.RoleName, account.AdminAreaPermission, + account.ClientAriaPermission, positionValue,0,pmUserId); if (account.ClientAriaPermission == "true" && account.AdminAreaPermission == "false" && account.IsActiveString == "true") diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs new file mode 100644 index 00000000..80e43524 --- /dev/null +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs @@ -0,0 +1,22 @@ +using GozareshgirProgramManager.Application.Modules.Users.Queries.GetSingleUser; +using MediatR; +using Shared.Contracts.PmUser; + +namespace GozareshgirProgramManager.Infrastructure.Services.User; + +public class PmUserQueryService : IPmUserQueryService +{ + public readonly IMediator _mediator; + + public PmUserQueryService(IMediator mediator) + { + _mediator = mediator; + } + + public async Task GetCurrentPmUserIdFromAccountId(long accountId) + { + var query = new GetSingleUserQuery(accountId.ToString()); + var result = await _mediator.Send(query); + return result.Data?.AccountId ?? null; + } +} \ No newline at end of file diff --git a/Shared.Contracts/PmUser/IPmUserQueryService.cs b/Shared.Contracts/PmUser/IPmUserQueryService.cs new file mode 100644 index 00000000..479355de --- /dev/null +++ b/Shared.Contracts/PmUser/IPmUserQueryService.cs @@ -0,0 +1,6 @@ +namespace Shared.Contracts.PmUser; + +public interface IPmUserQueryService +{ + Task GetCurrentPmUserIdFromAccountId(long accountId); +} \ No newline at end of file From a52e31398478e1220e63295dc04e351d845029ca Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 18:50:39 +0330 Subject: [PATCH 12/15] feat: register PmUserQueryService in Dependency Injection for user queries --- .../DependencyInjection.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs index ae816e1a..8451e848 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/DependencyInjection.cs @@ -20,12 +20,14 @@ using GozareshgirProgramManager.Infrastructure.Persistence.Context; using GozareshgirProgramManager.Infrastructure.Persistence.Repositories; using GozareshgirProgramManager.Infrastructure.Services.Authentication; using GozareshgirProgramManager.Infrastructure.Services.Role; +using GozareshgirProgramManager.Infrastructure.Services.User; using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Shared.Contracts.PmRole.Commands; using Shared.Contracts.PmRole.Queries; +using Shared.Contracts.PmUser; namespace GozareshgirProgramManager.Infrastructure; @@ -93,6 +95,7 @@ public static class DependencyInjection services.AddTransient(); services.AddTransient(); + services.AddTransient(); #endregion From 955a6a3d218743348205c107a4fd867c94a818e1 Mon Sep 17 00:00:00 2001 From: SamSys Date: Sat, 13 Dec 2025 18:51:08 +0330 Subject: [PATCH 13/15] edit pmRole completed --- AccountManagement.Application/RoleApplication.cs | 12 ++++-------- .../Services/Role/PmRoleCommandService.cs | 13 +++++++++++++ .../PmRole/Commands/IPmRoleCommandService.cs | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/AccountManagement.Application/RoleApplication.cs b/AccountManagement.Application/RoleApplication.cs index 80a1af83..02d027c0 100644 --- a/AccountManagement.Application/RoleApplication.cs +++ b/AccountManagement.Application/RoleApplication.cs @@ -144,18 +144,14 @@ public class RoleApplication : IRoleApplication //اگر این نقش در پروگرام منیجر وجود داشت ویرایش کن if (pmRoleResult != null) { - - try - { - var pmpermissionsData = pmPermissions.Where(x => x > 0).Select(x => new PmPermission(x)).ToList(); - //pmRoleResult.Edit(command.Name, pmpermissionsData); - // await _pmRoleRepository.SaveChangesAsync(); - } - catch (System.Exception) + var edit = new CreatePmRoleDto { RoleName = command.Name, Permissions = pmPermissions, GozareshgirRoleId = role.id }; + var res = await _pmRoleCommandService.Edit(edit); + if (!res.Item1) { _unitOfWork.RollbackAccountContext(); return operation.Failed("خطا در ویرایش دسترسی ها در پروگرام منیجر"); } + //var parameters = new CreateProgramManagerRole diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs index 09d551f4..9ac4a2a8 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/Role/PmRoleCommandService.cs @@ -1,5 +1,6 @@ using GozareshgirProgramManager.Application._Common.Models; using GozareshgirProgramManager.Application.Modules.Roles.Commands.CreateRole; +using GozareshgirProgramManager.Application.Modules.Roles.Commands.EditRole; using MediatR; using Shared.Contracts.PmRole.Commands; @@ -25,4 +26,16 @@ public class PmRoleCommandService: IPmRoleCommandService var res = await _mediator.Send(request); return (res.IsSuccess, res.ErrorMessage); } + + public async Task<(bool, string)> Edit(CreatePmRoleDto command) + { + var request = new EditRoleCommand + { + RoleName = command.RoleName, + Permissions = command.Permissions, + GozareshgirRoleId = command.GozareshgirRoleId + }; + var res = await _mediator.Send(request); + return (res.IsSuccess, res.ErrorMessage); + } } \ No newline at end of file diff --git a/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs b/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs index 3bd9e586..8be0cd83 100644 --- a/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs +++ b/Shared.Contracts/PmRole/Commands/IPmRoleCommandService.cs @@ -3,4 +3,5 @@ public interface IPmRoleCommandService { Task<(bool, string)> Create(CreatePmRoleDto command); + Task<(bool, string)> Edit(CreatePmRoleDto command); } \ No newline at end of file From 5be44432b10b24e56df801d296cb4e1f07e7f94a Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 18:55:50 +0330 Subject: [PATCH 14/15] feat: add user ID to GetSingleUserResponse and update PmUserQueryService for ID retrieval --- .../Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs | 2 ++ .../Services/User/PmUserQueryService.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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 index 2d79108e..39fd66b3 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs @@ -40,6 +40,7 @@ public class GetSingleUserQueryHandler : IBaseQueryHandler roles = user.RoleUser.Select(x => x.RoleId).ToList(); var response = new GetSingleUserResponse { + Id = user.Id, FullName = user.FullName, UserName = user.UserName, ProfilePhotoPath = user.ProfilePhotoPath, @@ -71,6 +72,7 @@ public class GetSingleUserQueryHandler : IBaseQueryHandler /// نام و نام خانوادگی /// diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs index 80e43524..1d6f9f04 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/User/PmUserQueryService.cs @@ -17,6 +17,6 @@ public class PmUserQueryService : IPmUserQueryService { var query = new GetSingleUserQuery(accountId.ToString()); var result = await _mediator.Send(query); - return result.Data?.AccountId ?? null; + return result.Data?.Id ?? null; } } \ No newline at end of file From a1e52ca48a7376f6801ba01cc7632ff3625bea39 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 13 Dec 2025 19:25:18 +0330 Subject: [PATCH 15/15] feat: add ProgramManagerDbServer configuration and simplify OperationResult usage in GetSingleUserQueryHandler --- .../Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs | 4 ++-- ServiceHost/appsettings.Development.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) 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 index 39fd66b3..41b7d4e8 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Users/Queries/GetSingleUser/GetSingleUserQueryHandler.cs @@ -60,12 +60,12 @@ public class GetSingleUserQueryHandler : IBaseQueryHandler)OperationResult.NotFound("کاربر یافت نشد"); + return OperationResult.NotFound("کاربر یافت نشد"); } } } - return (OperationResult)OperationResult.Failure("آی دی اکانت گزارشگیر پر نشده است"); + return OperationResult.Failure("آی دی اکانت گزارشگیر پر نشده است"); } } diff --git a/ServiceHost/appsettings.Development.json b/ServiceHost/appsettings.Development.json index b17b29c3..9fc1d34d 100644 --- a/ServiceHost/appsettings.Development.json +++ b/ServiceHost/appsettings.Development.json @@ -26,7 +26,8 @@ "TestDb": "Data Source=.;Initial Catalog=TestDb;Integrated Security=True;TrustServerCertificate=true;", //program_manager_db - "ProgramManagerDb": "Data Source=.;Initial Catalog=program_manager_db;Integrated Security=True;TrustServerCertificate=true;" + "ProgramManagerDb": "Data Source=.;Initial Catalog=program_manager_db;Integrated Security=True;TrustServerCertificate=true;", + "ProgramManagerDbServer": "Data Source=171.22.24.15;Initial Catalog=program_manager_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;" //mahan Docker //"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;" },