From 5369bbae297e424bf97e0f9faad274cf2c674727 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Tue, 15 Jul 2025 13:09:27 +0530 Subject: [PATCH] Solved the issue of project is not updating properly --- Marco.Pms.CacheHelper/ProjectCache.cs | 4 +- .../Controllers/ProjectController.cs | 101 +++-------- Marco.Pms.Services/Service/ProjectServices.cs | 158 ++++++++++-------- 3 files changed, 111 insertions(+), 152 deletions(-) diff --git a/Marco.Pms.CacheHelper/ProjectCache.cs b/Marco.Pms.CacheHelper/ProjectCache.cs index 183bbc4..c7d7e84 100644 --- a/Marco.Pms.CacheHelper/ProjectCache.cs +++ b/Marco.Pms.CacheHelper/ProjectCache.cs @@ -42,8 +42,8 @@ namespace Marco.Pms.CacheHelper Builders.Update.Set(r => r.ShortName, project.ShortName), Builders.Update.Set(r => r.ProjectStatus, new StatusMasterMongoDB { - Id = projectStatus?.Id.ToString(), - Status = projectStatus?.Status + Id = projectStatus.Id.ToString(), + Status = projectStatus.Status }), Builders.Update.Set(r => r.StartDate, project.StartDate), Builders.Update.Set(r => r.EndDate, project.EndDate), diff --git a/Marco.Pms.Services/Controllers/ProjectController.cs b/Marco.Pms.Services/Controllers/ProjectController.cs index 236e0cb..0122003 100644 --- a/Marco.Pms.Services/Controllers/ProjectController.cs +++ b/Marco.Pms.Services/Controllers/ProjectController.cs @@ -252,89 +252,28 @@ namespace MarcoBMS.Services.Controllers return StatusCode(response.StatusCode, response); } - [HttpPost("allocation")] - public async Task ManageAllocation(List projectAllocationDot) - { - if (projectAllocationDot != null) - { - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + //[HttpPost("allocation")] + //public async Task ManageAllocation(List projectAllocationDot) + //{ + // // --- Step 1: Input Validation --- + // if (!ModelState.IsValid) + // { + // var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList(); + // _logger.LogWarning("Update project called with invalid model state for ID {ProjectId}. Errors: {Errors}", id, string.Join(", ", errors)); + // return BadRequest(ApiResponse.ErrorResponse("Invalid request data provided.", errors, 400)); + // } - List? result = new List(); - List employeeIds = new List(); - List projectIds = new List(); + // // --- Step 2: Prepare data without I/O --- + // Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + // var response = await _projectServices.UpdateProjectAsync(id, updateProjectDto, tenantId, loggedInEmployee); + // if (response.Success) + // { + // var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Assign_Project", ProjectIds = projectIds, EmployeeList = employeeIds }; + // await _signalR.SendNotificationAsync(notification); + // } + // return StatusCode(response.StatusCode, response); - foreach (var item in projectAllocationDot) - { - try - { - ProjectAllocation projectAllocation = item.ToProjectAllocationFromProjectAllocationDto(tenantId); - ProjectAllocation? projectAllocationFromDb = await _context.ProjectAllocations.Where(c => c.EmployeeId == projectAllocation.EmployeeId - && c.ProjectId == projectAllocation.ProjectId - && c.ReAllocationDate == null - && c.TenantId == tenantId).SingleOrDefaultAsync(); - - if (projectAllocationFromDb != null) - { - _context.ProjectAllocations.Attach(projectAllocationFromDb); - - if (item.Status) - { - projectAllocationFromDb.JobRoleId = projectAllocation.JobRoleId; ; - projectAllocationFromDb.IsActive = true; - _context.Entry(projectAllocationFromDb).Property(e => e.JobRoleId).IsModified = true; - _context.Entry(projectAllocationFromDb).Property(e => e.IsActive).IsModified = true; - } - else - { - projectAllocationFromDb.ReAllocationDate = DateTime.Now; - projectAllocationFromDb.IsActive = false; - _context.Entry(projectAllocationFromDb).Property(e => e.ReAllocationDate).IsModified = true; - _context.Entry(projectAllocationFromDb).Property(e => e.IsActive).IsModified = true; - - employeeIds.Add(projectAllocation.EmployeeId); - projectIds.Add(projectAllocation.ProjectId); - } - await _context.SaveChangesAsync(); - var result1 = new - { - Id = projectAllocationFromDb.Id, - EmployeeId = projectAllocation.EmployeeId, - JobRoleId = projectAllocation.JobRoleId, - IsActive = projectAllocation.IsActive, - ProjectId = projectAllocation.ProjectId, - AllocationDate = projectAllocation.AllocationDate, - ReAllocationDate = projectAllocation.ReAllocationDate, - TenantId = projectAllocation.TenantId - }; - result.Add(result1); - } - else - { - projectAllocation.AllocationDate = DateTime.Now; - projectAllocation.IsActive = true; - _context.ProjectAllocations.Add(projectAllocation); - await _context.SaveChangesAsync(); - - employeeIds.Add(projectAllocation.EmployeeId); - projectIds.Add(projectAllocation.ProjectId); - } - await _cache.ClearAllProjectIds(item.EmpID); - - } - catch (Exception ex) - { - return Ok(ApiResponse.ErrorResponse(ex.Message, ex, 400)); - } - } - var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Assign_Project", ProjectIds = projectIds, EmployeeList = employeeIds }; - - await _signalR.SendNotificationAsync(notification); - return Ok(ApiResponse.SuccessResponse(result, "Data saved successfully", 200)); - - } - return BadRequest(ApiResponse.ErrorResponse("Invalid details.", "Work Item Details are not valid.", 400)); - - } + //} [HttpGet("assigned-projects/{employeeId}")] public async Task GetProjectsByEmployee([FromRoute] Guid employeeId) diff --git a/Marco.Pms.Services/Service/ProjectServices.cs b/Marco.Pms.Services/Service/ProjectServices.cs index dcaf20e..7717584 100644 --- a/Marco.Pms.Services/Service/ProjectServices.cs +++ b/Marco.Pms.Services/Service/ProjectServices.cs @@ -443,21 +443,16 @@ namespace Marco.Pms.Services.Service return ApiResponse.ErrorResponse("Conflict occurred.", "This project has been modified by someone else. Please refresh and try again.", 409); } - // --- Step 4: Perform Side-Effects in the Background (Fire and Forget) --- - // The core database operation is done. Now, we perform non-blocking cache and notification updates. - _ = Task.Run(async () => - { - // Create a DTO of the updated project to pass to background tasks. - var projectDto = _mapper.Map(existingProject); + // --- Step 4: Perform Side-Effects (Fire and Forget) --- + // Create a DTO of the updated project to pass to background tasks. + var projectDto = _mapper.Map(existingProject); - // 4a. Update Cache - await UpdateCacheInBackground(existingProject); - - }); + // 4a. Update Cache + await UpdateCacheInBackground(existingProject); // --- Step 5: Return Success Response Immediately --- // The client gets a fast response without waiting for caching or SignalR. - return ApiResponse.SuccessResponse(_mapper.Map(existingProject), "Project updated successfully.", 200); + return ApiResponse.SuccessResponse(projectDto, "Project updated successfully.", 200); } catch (Exception ex) { @@ -471,41 +466,6 @@ namespace Marco.Pms.Services.Service #region =================================================================== Project Allocation APIs =================================================================== - public async Task> GetEmployeeByProjectID(Guid? projectid, bool includeInactive, Guid tenantId, Employee loggedInEmployee) - { - if (projectid == null) - { - return ApiResponse.ErrorResponse("Invalid Input Parameter", 404); - } - // Fetch assigned project - List result = new List(); - - var employeeQuery = _context.ProjectAllocations - .Include(pa => pa.Employee) - .Where(pa => pa.ProjectId == projectid && pa.TenantId == tenantId && pa.Employee != null); - - if (includeInactive) - { - - result = await employeeQuery.Select(pa => pa.Employee ?? new Employee()).ToListAsync(); - } - else - { - result = await employeeQuery - .Where(pa => pa.IsActive) - .Select(pa => pa.Employee ?? new Employee()).ToListAsync(); - } - - List resultVM = new List(); - foreach (Employee employee in result) - { - EmployeeVM vm = _mapper.Map(employee); - resultVM.Add(vm); - } - - return ApiResponse.SuccessResponse(resultVM, "Successfully fetched the list of employees for seleted project", 200); - } - /// /// Retrieves a list of employees for a specific project. /// This method is optimized to perform all filtering and mapping on the database server. @@ -578,28 +538,6 @@ namespace Marco.Pms.Services.Service } } - public async Task> GetProjectAllocation(Guid? projectId, Guid tenantId, Employee loggedInEmployee) - { - var employees = await _context.ProjectAllocations - .Where(c => c.TenantId == tenantId && c.ProjectId == projectId && c.Employee != null) - .Include(e => e.Employee) - .Select(e => new - { - ID = e.Id, - EmployeeId = e.EmployeeId, - ProjectId = e.ProjectId, - AllocationDate = e.AllocationDate, - ReAllocationDate = e.ReAllocationDate, - FirstName = e.Employee != null ? e.Employee.FirstName : string.Empty, - LastName = e.Employee != null ? e.Employee.LastName : string.Empty, - MiddleName = e.Employee != null ? e.Employee.MiddleName : string.Empty, - IsActive = e.IsActive, - JobRoleId = (e.JobRoleId != null ? e.JobRoleId : e.Employee != null ? e.Employee.JobRoleId : null) - }).ToListAsync(); - - return ApiResponse.SuccessResponse(employees, "Success.", 200); - } - /// /// Retrieves project allocation details for a specific project. /// This method is optimized for performance and includes security checks. @@ -670,6 +608,87 @@ namespace Marco.Pms.Services.Service return ApiResponse.ErrorResponse("An internal server error occurred.", "Database query failed.", 500); } } + + //public async Task> ManageAllocation(List projectAllocationDot, Guid tenantId, Employee loggedInEmployee) + //{ + // if (projectAllocationDot != null) + // { + // List? result = new List(); + // List employeeIds = new List(); + // List projectIds = new List(); + + // foreach (var item in projectAllocationDot) + // { + // try + // { + // //ProjectAllocation projectAllocation = item.ToProjectAllocationFromProjectAllocationDto(tenantId); + // ProjectAllocation projectAllocation = item.ToProjectAllocationFromProjectAllocationDto(tenantId); + // ProjectAllocation? projectAllocationFromDb = await _context.ProjectAllocations.Where(c => c.EmployeeId == projectAllocation.EmployeeId + // && c.ProjectId == projectAllocation.ProjectId + // && c.ReAllocationDate == null + // && c.TenantId == tenantId).SingleOrDefaultAsync(); + + // if (projectAllocationFromDb != null) + // { + // _context.ProjectAllocations.Attach(projectAllocationFromDb); + + // if (item.Status) + // { + // projectAllocationFromDb.JobRoleId = projectAllocation.JobRoleId; ; + // projectAllocationFromDb.IsActive = true; + // _context.Entry(projectAllocationFromDb).Property(e => e.JobRoleId).IsModified = true; + // _context.Entry(projectAllocationFromDb).Property(e => e.IsActive).IsModified = true; + // } + // else + // { + // projectAllocationFromDb.ReAllocationDate = DateTime.Now; + // projectAllocationFromDb.IsActive = false; + // _context.Entry(projectAllocationFromDb).Property(e => e.ReAllocationDate).IsModified = true; + // _context.Entry(projectAllocationFromDb).Property(e => e.IsActive).IsModified = true; + + // employeeIds.Add(projectAllocation.EmployeeId); + // projectIds.Add(projectAllocation.ProjectId); + // } + // await _context.SaveChangesAsync(); + // var result1 = new + // { + // Id = projectAllocationFromDb.Id, + // EmployeeId = projectAllocation.EmployeeId, + // JobRoleId = projectAllocation.JobRoleId, + // IsActive = projectAllocation.IsActive, + // ProjectId = projectAllocation.ProjectId, + // AllocationDate = projectAllocation.AllocationDate, + // ReAllocationDate = projectAllocation.ReAllocationDate, + // TenantId = projectAllocation.TenantId + // }; + // result.Add(result1); + // } + // else + // { + // projectAllocation.AllocationDate = DateTime.Now; + // projectAllocation.IsActive = true; + // _context.ProjectAllocations.Add(projectAllocation); + // await _context.SaveChangesAsync(); + + // employeeIds.Add(projectAllocation.EmployeeId); + // projectIds.Add(projectAllocation.ProjectId); + // } + // await _cache.ClearAllProjectIds(item.EmpID); + + // } + // catch (Exception ex) + // { + // return ApiResponse.ErrorResponse(ex.Message, ex, 400); + // } + // } + + // return ApiResponse.SuccessResponse(result, "Data saved successfully", 200); + + // } + // return ApiResponse.ErrorResponse("Invalid details.", "Work Item Details are not valid.", 400); + + //} + #endregion #region =================================================================== Helper Functions =================================================================== @@ -881,7 +900,8 @@ namespace Marco.Pms.Services.Service try { // This logic can be more complex, but the idea is to update or add. - if (!await _cache.UpdateProjectDetailsOnly(project)) + var demo = await _cache.UpdateProjectDetailsOnly(project); + if (!demo) { await _cache.AddProjectDetails(project); }