Added an API to get list service project allocation
This commit is contained in:
parent
e7a21e9e2f
commit
c61ef92f6e
@ -98,11 +98,11 @@ namespace Marco.Pms.Services.Controllers
|
||||
|
||||
#region =================================================================== Service Project Allocation Functions ===================================================================
|
||||
|
||||
[HttpPost("get/allocation/list")]
|
||||
public async Task<IActionResult> GetServiceProjectAllocationList([FromQuery] Guid? projectId, [FromQuery] Guid? employeeId)
|
||||
[HttpGet("get/allocation/list")]
|
||||
public async Task<IActionResult> GetServiceProjectAllocationList([FromQuery] Guid? projectId, [FromQuery] Guid? employeeId, [FromQuery] bool isActive = true)
|
||||
{
|
||||
Employee loggedInEmploee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _serviceProject.GetServiceProjectAllocationListAsync(projectId, employeeId, loggedInEmploee, tenantId);
|
||||
var response = await _serviceProject.GetServiceProjectAllocationListAsync(projectId, employeeId, true, loggedInEmploee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Service Project Allocation Functions ===================================================================
|
||||
Task<ApiResponse<object>> GetServiceProjectAllocationListAsync(Guid? projectId, Guid? employeeId, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> GetServiceProjectAllocationListAsync(Guid? projectId, Guid? employeeId, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> ManageServiceProjectAllocationAsync(List<ServiceProjectAllocationDto> model, Employee loggedInEmployee, Guid tenantId);
|
||||
#endregion
|
||||
#region =================================================================== Job Tickets Functions ===================================================================
|
||||
|
||||
@ -363,10 +363,74 @@ namespace Marco.Pms.Services.Service
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Service Project Allocation Functions ===================================================================
|
||||
public async Task<ApiResponse<object>> GetServiceProjectAllocationListAsync(Guid? projectId, Guid? employeeId, Employee loggedInEmployee, Guid tenantId)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a list of service project allocations filtered by project ID or employee ID and active status within the tenant context.
|
||||
/// </summary>
|
||||
/// <param name="projectId">Optional project ID filter.</param>
|
||||
/// <param name="employeeId">Optional employee ID filter.</param>
|
||||
/// <param name="isActive">Filter for active/inactive allocations.</param>
|
||||
/// <param name="loggedInEmployee">Employee making the request (for audit/logging).</param>
|
||||
/// <param name="tenantId">Tenant identifier for multi-tenant data isolation.</param>
|
||||
/// <returns>ApiResponse with the list of matching service project allocations or error details.</returns>
|
||||
public async Task<ApiResponse<object>> GetServiceProjectAllocationListAsync(Guid? projectId, Guid? employeeId, bool isActive, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
return ApiResponse<object>.SuccessResponse(projectId, "Service project allocation fetched successfully", 200);
|
||||
if (tenantId == Guid.Empty)
|
||||
{
|
||||
_logger.LogWarning("GetServiceProjectAllocationListAsync called with invalid tenant context by employee {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied", "Invalid tenant context.", 403);
|
||||
}
|
||||
|
||||
if (!projectId.HasValue && !employeeId.HasValue)
|
||||
{
|
||||
_logger.LogInfo("GetServiceProjectAllocationListAsync missing required filters by employee {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Bad Request", "Provide at least one of (ProjectId or EmployeeId).", 400);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInfo("Fetching service project allocations for tenant {TenantId} by employee {EmployeeId} " +
|
||||
"with filters - ProjectId: {ProjectId}, EmployeeId: {EmployeeId}, IsActive: {IsActive}",
|
||||
tenantId, loggedInEmployee.Id, projectId ?? Guid.Empty, employeeId ?? Guid.Empty, isActive);
|
||||
|
||||
// Base query with includes for related navigation properties
|
||||
var allocationQuery = _context.ServiceProjectAllocations
|
||||
.Include(spa => spa.Project)
|
||||
.Include(spa => spa.TeamRole)
|
||||
.Include(spa => spa.Employee).ThenInclude(e => e!.JobRole)
|
||||
.Include(spa => spa.AssignedBy).ThenInclude(e => e!.JobRole)
|
||||
.Include(spa => spa.ReAssignedBy).ThenInclude(e => e!.JobRole)
|
||||
.Where(spa => spa.IsActive == isActive && spa.TenantId == tenantId);
|
||||
|
||||
// Apply filtering by either project or employee (mutually exclusive)
|
||||
if (projectId.HasValue)
|
||||
{
|
||||
allocationQuery = allocationQuery.Where(spa => spa.ProjectId == projectId.Value);
|
||||
}
|
||||
else if (employeeId.HasValue)
|
||||
{
|
||||
allocationQuery = allocationQuery.Where(spa => spa.EmployeeId == employeeId.Value);
|
||||
}
|
||||
|
||||
// Execute query and sort results by most recent assignment
|
||||
var allocations = await allocationQuery
|
||||
.OrderByDescending(spa => spa.AssignedAt)
|
||||
.ToListAsync();
|
||||
|
||||
var response = _mapper.Map<List<ServiceProjectAllocationVM>>(allocations);
|
||||
|
||||
_logger.LogInfo("{Count} service project allocations fetched successfully for tenant {TenantId}", response.Count, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, "Service project allocations fetched successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching service project allocations for tenant {TenantId} by employee {EmployeeId}", tenantId, loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Internal Server Error", "Failed to fetch service project allocations. Please try again later.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Manages service project allocations by adding new active allocations and removing inactive ones.
|
||||
/// Validates projects, employees, and team roles exist before applying changes.
|
||||
@ -400,22 +464,22 @@ namespace Marco.Pms.Services.Service
|
||||
var projectTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.ServiceProjects.Where(sp => projectIds.Contains(sp.Id) && sp.TenantId == tenantId && sp.IsActive).ToListAsync();
|
||||
return await context.ServiceProjects.AsNoTracking().Where(sp => projectIds.Contains(sp.Id) && sp.TenantId == tenantId && sp.IsActive).ToListAsync();
|
||||
});
|
||||
var employeeTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.Employees.Where(e => employeeIds.Contains(e.Id) && e.IsActive).ToListAsync();
|
||||
return await context.Employees.AsNoTracking().Where(e => employeeIds.Contains(e.Id) && e.IsActive).ToListAsync();
|
||||
});
|
||||
var teamRoleTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.TeamRoleMasters.Where(trm => teamRoleIds.Contains(trm.Id)).ToListAsync();
|
||||
return await context.TeamRoleMasters.AsNoTracking().Where(trm => teamRoleIds.Contains(trm.Id)).ToListAsync();
|
||||
});
|
||||
var allocationTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.ServiceProjectAllocations.Where(spa => projectIds.Contains(spa.ProjectId) && spa.TenantId == tenantId && spa.IsActive).ToListAsync();
|
||||
return await context.ServiceProjectAllocations.AsNoTracking().Where(spa => projectIds.Contains(spa.ProjectId) && spa.TenantId == tenantId && spa.IsActive).ToListAsync();
|
||||
});
|
||||
|
||||
await Task.WhenAll(projectTask, employeeTask, teamRoleTask, allocationTask);
|
||||
@ -463,13 +527,16 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
else if (!dto.IsActive && existingAllocation != null)
|
||||
{
|
||||
existingAllocation.IsActive = false;
|
||||
existingAllocation.ReAssignedAt = DateTime.UtcNow;
|
||||
existingAllocation.ReAssignedById = loggedInEmployee.Id;
|
||||
allocationsToRemove.Add(existingAllocation);
|
||||
}
|
||||
}
|
||||
|
||||
// Batch changes for efficiency
|
||||
if (newAllocations.Any()) _context.ServiceProjectAllocations.AddRange(newAllocations);
|
||||
if (allocationsToRemove.Any()) _context.ServiceProjectAllocations.RemoveRange(allocationsToRemove);
|
||||
if (allocationsToRemove.Any()) _context.ServiceProjectAllocations.UpdateRange(allocationsToRemove);
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user