From 16b11a8bb8783c9e90469921ec55f8aa62dba406 Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 6 Jan 2026 10:51:56 +0330 Subject: [PATCH 1/7] feat: add ChangePriority method to ProjectController for task priority updates --- .../Admin/Controllers/ProgramManager/ProjectController.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index 95d6da94..c3e0441b 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -165,4 +165,11 @@ public class ProjectController : ProgramManagerBaseController var res = await _mediator.Send(command); return res; } + + public async Task> ChangePriority(ChangeTaskPriorityCommand command) + { + var res = await _mediator.Send(command); + return res; + } + } \ No newline at end of file From a9789023ac85b1ab5ba3fb962aa2392f00ad308f Mon Sep 17 00:00:00 2001 From: mahan Date: Tue, 6 Jan 2026 13:46:45 +0330 Subject: [PATCH 2/7] feat: add HTTP POST endpoint for ChangePriority method in ProjectController --- .../Admin/Controllers/ProgramManager/ProjectController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index c3e0441b..290c5cab 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -166,7 +166,8 @@ public class ProjectController : ProgramManagerBaseController return res; } - public async Task> ChangePriority(ChangeTaskPriorityCommand command) + [HttpPost("change-priority")] + public async Task> ChangePriority([FromBody] ChangeTaskPriorityCommand command) { var res = await _mediator.Send(command); return res; From 2bea2659895fffce4709202c5b4d686ef1defd73 Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 7 Jan 2026 12:11:24 +0330 Subject: [PATCH 3/7] feat: implement task priority change command and update project/task DTOs --- .../ChangeTaskPriorityCommand.cs | 41 +++++++++++++++++++ .../GetProjectsListQueryHandler.cs | 1 + .../Queries/GetProjectsList/GetTaskListDto.cs | 1 + .../ProgramManager/ProjectController.cs | 1 + 4 files changed, 44 insertions(+) create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeTaskPriority/ChangeTaskPriorityCommand.cs diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeTaskPriority/ChangeTaskPriorityCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeTaskPriority/ChangeTaskPriorityCommand.cs new file mode 100644 index 00000000..23d23830 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/ChangeTaskPriority/ChangeTaskPriorityCommand.cs @@ -0,0 +1,41 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeTaskPriority; + +/// +/// Command to change a task priority. +/// +public record ChangeTaskPriorityCommand(Guid TaskId, TaskPriority Priority) : IBaseCommand; + +public class ChangeTaskPriorityCommandHandler : IBaseCommandHandler +{ + private readonly IProjectTaskRepository _taskRepository; + private readonly IUnitOfWork _unitOfWork; + + public ChangeTaskPriorityCommandHandler(IProjectTaskRepository taskRepository, IUnitOfWork unitOfWork) + { + _taskRepository = taskRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(ChangeTaskPriorityCommand request, CancellationToken cancellationToken) + { + var task = await _taskRepository.GetByIdAsync(request.TaskId, cancellationToken); + if (task is null) + return OperationResult.NotFound("تسک یافت نشد"); + + // Idempotent: if already same priority, skip extra work + if (task.Priority != request.Priority) + { + task.SetPriority(request.Priority); + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } +} + 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 index d26a06b1..a982caf3 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/GetProjectsList/GetProjectsListQueryHandler.cs @@ -189,6 +189,7 @@ public class GetProjectsListQueryHandler : IBaseQueryHandler Sections { get; init; } } diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index 290c5cab..fe3dbb6f 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -22,6 +22,7 @@ using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectH using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeTaskPriority; namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; From 572f66f905a139eb25f4e5b63058763868eda22c Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 7 Jan 2026 16:52:50 +0330 Subject: [PATCH 4/7] feat: implement auto-pending for task sections reaching estimated time --- .../AutoPendingFullTimeTaskSectionsCommand.cs | 62 +++++++++++++++++++ .../ProjectAgg/Entities/TaskSection.cs | 2 +- .../Repositories/ITaskSectionRepository.cs | 3 + .../Repositories/TaskSectionRepository.cs | 9 +++ .../ProgramManager/ProjectController.cs | 3 + 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AutoPendingFullTimeTaskSections/AutoPendingFullTimeTaskSectionsCommand.cs diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AutoPendingFullTimeTaskSections/AutoPendingFullTimeTaskSectionsCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AutoPendingFullTimeTaskSections/AutoPendingFullTimeTaskSectionsCommand.cs new file mode 100644 index 00000000..6e1e9802 --- /dev/null +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/AutoPendingFullTimeTaskSections/AutoPendingFullTimeTaskSectionsCommand.cs @@ -0,0 +1,62 @@ +using GozareshgirProgramManager.Application._Common.Interfaces; +using GozareshgirProgramManager.Application._Common.Models; +using GozareshgirProgramManager.Domain._Common; +using GozareshgirProgramManager.Domain.ProjectAgg.Repositories; +using GozareshgirProgramManager.Domain.ProjectAgg.Enums; + +namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoPendingFullTimeTaskSections; + +public record AutoPendingFullTimeTaskSectionsCommand : IBaseCommand; + +public class AutoPendingFullTimeTaskSectionsCommandHandler : IBaseCommandHandler +{ + private readonly ITaskSectionRepository _taskSectionRepository; + private readonly IUnitOfWork _unitOfWork; + + public AutoPendingFullTimeTaskSectionsCommandHandler( + ITaskSectionRepository taskSectionRepository, + IUnitOfWork unitOfWork) + { + _taskSectionRepository = taskSectionRepository; + _unitOfWork = unitOfWork; + } + + public async Task Handle(AutoPendingFullTimeTaskSectionsCommand request, CancellationToken cancellationToken) + { + try + { + // تمام سکشن‌هایی که هنوز Pending یا Completed نشده‌اند را دریافت کن + var taskSections = await _taskSectionRepository.GetAllNotCompletedOrPendingIncludeAllAsync(cancellationToken); + + foreach (var section in taskSections) + { + var totalSpent = section.GetTotalTimeSpent(); + var estimate = section.FinalEstimatedHours; + + if (estimate.TotalMinutes <= 0) + continue; // تسک بدون تخمین را نادیده بگیر + + if (totalSpent >= estimate) + { + // مهم: وضعیت را مستقل از فعال/غیرفعال بودن فعالیت‌ها PendingForCompletion کنیم + if (section.IsInProgress()) + { + // اگر فعالیت فعال دارد، با وضعیت جدید متوقف شود + section.StopWork(TaskSectionStatus.PendingForCompletion, "اتمام خودکار - رسیدن به ۱۰۰٪ زمان تخمینی"); + } + else + { + section.UpdateStatus(TaskSectionStatus.PendingForCompletion); + } + } + } + + await _unitOfWork.SaveChangesAsync(cancellationToken); + return OperationResult.Success(); + } + catch (Exception ex) + { + return OperationResult.Failure($"خطا در در انتظار تکمیل قرار دادن خودکار تسک‌ها: {ex.Message}"); + } + } +} diff --git a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs index 072422fe..83b86c23 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Entities/TaskSection.cs @@ -270,7 +270,7 @@ public class TaskSection : EntityBase // متوقف کردن فعالیت با EndDate دقیق شده activeActivity.StopWorkWithSpecificTime(adjustedEndDate, "متوقف خودکار - بیش از تایم تعیین شده"); - UpdateStatus(TaskSectionStatus.Incomplete); + UpdateStatus(TaskSectionStatus.PendingForCompletion); } } } \ 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 index 487991a8..50e1a2b0 100644 --- a/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs +++ b/ProgramManager/src/Domain/GozareshgirProgramManager.Domain/ProjectAgg/Repositories/ITaskSectionRepository.cs @@ -14,4 +14,7 @@ public interface ITaskSectionRepository: IRepository Task> GetAssignedToUserAsync(long userId); Task> GetActiveSectionsIncludeAllAsync(CancellationToken cancellationToken); Task HasUserAnyInProgressSectionAsync(long userId, CancellationToken cancellationToken = default); + + // جدید: دریافت سکشن‌هایی که هنوز Completed یا PendingForCompletion نشده‌اند با اطلاعات کامل + Task> GetAllNotCompletedOrPendingIncludeAllAsync(CancellationToken cancellationToken); } \ 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 index d6d60b69..ce590dc7 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Persistence/Repositories/TaskSectionRepository.cs @@ -53,4 +53,13 @@ public class TaskSectionRepository:RepositoryBase,ITaskSection .AnyAsync(x => x.CurrentAssignedUserId == userId && x.Status == TaskSectionStatus.InProgress, cancellationToken); } + + public Task> GetAllNotCompletedOrPendingIncludeAllAsync(CancellationToken cancellationToken) + { + return _context.TaskSections + .Where(x => x.Status != TaskSectionStatus.Completed && x.Status != TaskSectionStatus.PendingForCompletion) + .Include(x => x.Activities) + .Include(x => x.AdditionalTimes) + .ToListAsync(cancellationToken); + } } \ No newline at end of file diff --git a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs index 95d6da94..b2841335 100644 --- a/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs +++ b/ServiceHost/Areas/Admin/Controllers/ProgramManager/ProjectController.cs @@ -22,6 +22,7 @@ using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectH using MediatR; using Microsoft.AspNetCore.Mvc; using ServiceHost.BaseControllers; +using GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoPendingFullTimeTaskSections; namespace ServiceHost.Areas.Admin.Controllers.ProgramManager; @@ -122,6 +123,8 @@ public class ProjectController : ProgramManagerBaseController { // اجرای Command برای متوقف کردن تسک‌های overtime قبل از نمایش await _mediator.Send(new AutoStopOverTimeTaskSectionsCommand()); + // سپس تسک‌هایی که به 100% زمان تخمینی رسیده‌اند را به حالت PendingForCompletion ببریم + await _mediator.Send(new AutoPendingFullTimeTaskSectionsCommand()); var res = await _mediator.Send(query); return res; From 380ed8f6b1b42bf222dca953caa26c4253accbb9 Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 7 Jan 2026 18:34:37 +0330 Subject: [PATCH 5/7] feat: update SetTimeProjectCommandHandler to set status to Incomplete when additional time is added --- .../SetTimeProjectCommandHandler.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 index fdbadc28..a9ca3a61 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Commands/SetTimeProject/SetTimeProjectCommandHandler.cs @@ -365,10 +365,26 @@ public class SetTimeProjectCommandHandler : IBaseCommandHandler Date: Thu, 8 Jan 2026 10:46:04 +0330 Subject: [PATCH 6/7] feat: update application URL in launchSettings and enhance task sorting by priority in ProjectBoardListQueryHandler --- .../Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs | 4 +++- ServiceHost/Properties/launchSettings.json | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) 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 index 1157a932..a082f648 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Projects/Queries/ProjectBoardList/ProjectBoardListQueryHandler.cs @@ -53,7 +53,9 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler x.Id, x => x.FullName, cancellationToken); - var result = data .OrderByDescending(x => x.CurrentAssignedUserId == currentUserId) + var result = data + .OrderByDescending(x => x.CurrentAssignedUserId == currentUserId) + .ThenByDescending(x=>x.Task.Priority) .ThenBy(x => GetStatusOrder(x.Status)) .Select(x => { diff --git a/ServiceHost/Properties/launchSettings.json b/ServiceHost/Properties/launchSettings.json index f5214c2b..788962e4 100644 --- a/ServiceHost/Properties/launchSettings.json +++ b/ServiceHost/Properties/launchSettings.json @@ -19,7 +19,7 @@ "sqlDebugging": true, "dotnetRunMessages": "true", "nativeDebugging": true, - "applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5006", + "applicationUrl": "https://localhost:5004;http://localhost:5003;", "jsWebView2Debugging": false, "hotReloadEnabled": true }, @@ -44,7 +44,7 @@ "sqlDebugging": true, "dotnetRunMessages": "true", "nativeDebugging": true, - "applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5006;", + "applicationUrl": "https://localhost:5004;http://localhost:5003;", "jsWebView2Debugging": false, "hotReloadEnabled": true } From a1ed3ad648c8271bdad494eb553018a88c503aa3 Mon Sep 17 00:00:00 2001 From: SamSys Date: Thu, 8 Jan 2026 11:35:03 +0330 Subject: [PATCH 7/7] logeer change --- ServiceHost/Program.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 012f1a0a..ee563bb8 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -63,10 +63,17 @@ if (!Directory.Exists(logDirectory)) Directory.CreateDirectory(logDirectory); } -// فقط برای فایل از Serilog استفاده می‌شود -// تنظیمات MinimumLevel از appsettings.json خوانده می‌شود Log.Logger = new LoggerConfiguration() - .Enrich.FromLogContext() + //NO EF Core log + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + + //NO DbCommand log + .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning) + + //NO Microsoft Public log + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + + //.MinimumLevel.Information() .WriteTo.File( path: Path.Combine(logDirectory, "gozareshgir_log.txt"), rollingInterval: RollingInterval.Day,