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 ===================================================================
|
#region =================================================================== Service Project Allocation Functions ===================================================================
|
||||||
|
|
||||||
[HttpPost("get/allocation/list")]
|
[HttpGet("get/allocation/list")]
|
||||||
public async Task<IActionResult> GetServiceProjectAllocationList([FromQuery] Guid? projectId, [FromQuery] Guid? employeeId)
|
public async Task<IActionResult> GetServiceProjectAllocationList([FromQuery] Guid? projectId, [FromQuery] Guid? employeeId, [FromQuery] bool isActive = true)
|
||||||
{
|
{
|
||||||
Employee loggedInEmploee = await _userHelper.GetCurrentEmployeeAsync();
|
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);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Service Project Allocation Functions ===================================================================
|
#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);
|
Task<ApiResponse<object>> ManageServiceProjectAllocationAsync(List<ServiceProjectAllocationDto> model, Employee loggedInEmployee, Guid tenantId);
|
||||||
#endregion
|
#endregion
|
||||||
#region =================================================================== Job Tickets Functions ===================================================================
|
#region =================================================================== Job Tickets Functions ===================================================================
|
||||||
|
|||||||
@ -363,10 +363,74 @@ namespace Marco.Pms.Services.Service
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Service Project Allocation Functions ===================================================================
|
#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>
|
/// <summary>
|
||||||
/// Manages service project allocations by adding new active allocations and removing inactive ones.
|
/// Manages service project allocations by adding new active allocations and removing inactive ones.
|
||||||
/// Validates projects, employees, and team roles exist before applying changes.
|
/// Validates projects, employees, and team roles exist before applying changes.
|
||||||
@ -400,22 +464,22 @@ namespace Marco.Pms.Services.Service
|
|||||||
var projectTask = Task.Run(async () =>
|
var projectTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
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 () =>
|
var employeeTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
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 () =>
|
var teamRoleTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
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 () =>
|
var allocationTask = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
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);
|
await Task.WhenAll(projectTask, employeeTask, teamRoleTask, allocationTask);
|
||||||
@ -463,13 +527,16 @@ namespace Marco.Pms.Services.Service
|
|||||||
}
|
}
|
||||||
else if (!dto.IsActive && existingAllocation != null)
|
else if (!dto.IsActive && existingAllocation != null)
|
||||||
{
|
{
|
||||||
|
existingAllocation.IsActive = false;
|
||||||
|
existingAllocation.ReAssignedAt = DateTime.UtcNow;
|
||||||
|
existingAllocation.ReAssignedById = loggedInEmployee.Id;
|
||||||
allocationsToRemove.Add(existingAllocation);
|
allocationsToRemove.Add(existingAllocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Batch changes for efficiency
|
// Batch changes for efficiency
|
||||||
if (newAllocations.Any()) _context.ServiceProjectAllocations.AddRange(newAllocations);
|
if (newAllocations.Any()) _context.ServiceProjectAllocations.AddRange(newAllocations);
|
||||||
if (allocationsToRemove.Any()) _context.ServiceProjectAllocations.RemoveRange(allocationsToRemove);
|
if (allocationsToRemove.Any()) _context.ServiceProjectAllocations.UpdateRange(allocationsToRemove);
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user