Solved the issue of project is not updating properly

This commit is contained in:
ashutosh.nehete 2025-07-15 13:09:27 +05:30
parent 560d2f2d4d
commit 80149f05f7
3 changed files with 111 additions and 152 deletions

View File

@ -42,8 +42,8 @@ namespace Marco.Pms.CacheHelper
Builders<ProjectMongoDB>.Update.Set(r => r.ShortName, project.ShortName),
Builders<ProjectMongoDB>.Update.Set(r => r.ProjectStatus, new StatusMasterMongoDB
{
Id = projectStatus?.Id.ToString(),
Status = projectStatus?.Status
Id = projectStatus.Id.ToString(),
Status = projectStatus.Status
}),
Builders<ProjectMongoDB>.Update.Set(r => r.StartDate, project.StartDate),
Builders<ProjectMongoDB>.Update.Set(r => r.EndDate, project.EndDate),

View File

@ -252,89 +252,28 @@ namespace MarcoBMS.Services.Controllers
return StatusCode(response.StatusCode, response);
}
[HttpPost("allocation")]
public async Task<IActionResult> ManageAllocation(List<ProjectAllocationDot> projectAllocationDot)
{
if (projectAllocationDot != null)
{
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
//[HttpPost("allocation")]
//public async Task<IActionResult> ManageAllocation(List<ProjectAllocationDot> 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<object>.ErrorResponse("Invalid request data provided.", errors, 400));
// }
List<object>? result = new List<object>();
List<Guid> employeeIds = new List<Guid>();
List<Guid> projectIds = new List<Guid>();
// // --- 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<object>.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<object>.SuccessResponse(result, "Data saved successfully", 200));
}
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid details.", "Work Item Details are not valid.", 400));
}
//}
[HttpGet("assigned-projects/{employeeId}")]
public async Task<IActionResult> GetProjectsByEmployee([FromRoute] Guid employeeId)

View File

@ -443,21 +443,16 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.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 () =>
{
// --- Step 4: Perform Side-Effects (Fire and Forget) ---
// Create a DTO of the updated project to pass to background tasks.
var projectDto = _mapper.Map<ProjectDto>(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<object>.SuccessResponse(_mapper.Map<ProjectDto>(existingProject), "Project updated successfully.", 200);
return ApiResponse<object>.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<ApiResponse<object>> GetEmployeeByProjectID(Guid? projectid, bool includeInactive, Guid tenantId, Employee loggedInEmployee)
{
if (projectid == null)
{
return ApiResponse<object>.ErrorResponse("Invalid Input Parameter", 404);
}
// Fetch assigned project
List<Employee> result = new List<Employee>();
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<EmployeeVM> resultVM = new List<EmployeeVM>();
foreach (Employee employee in result)
{
EmployeeVM vm = _mapper.Map<EmployeeVM>(employee);
resultVM.Add(vm);
}
return ApiResponse<object>.SuccessResponse(resultVM, "Successfully fetched the list of employees for seleted project", 200);
}
/// <summary>
/// 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<ApiResponse<object>> 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<object>.SuccessResponse(employees, "Success.", 200);
}
/// <summary>
/// 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<object>.ErrorResponse("An internal server error occurred.", "Database query failed.", 500);
}
}
//public async Task<ApiResponse<object>> ManageAllocation(List<ProjectAllocationDot> projectAllocationDot, Guid tenantId, Employee loggedInEmployee)
//{
// if (projectAllocationDot != null)
// {
// List<object>? result = new List<object>();
// List<Guid> employeeIds = new List<Guid>();
// List<Guid> projectIds = new List<Guid>();
// 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<object>.ErrorResponse(ex.Message, ex, 400);
// }
// }
// return ApiResponse<object>.SuccessResponse(result, "Data saved successfully", 200);
// }
// return ApiResponse<object>.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);
}