Organization_Management #142
@ -407,10 +407,19 @@ namespace Marco.Pms.Helpers
|
|||||||
|
|
||||||
#region=================================================================== WorkItem Cache Helper ===================================================================
|
#region=================================================================== WorkItem Cache Helper ===================================================================
|
||||||
|
|
||||||
public async Task<List<WorkItemMongoDB>> GetWorkItemsByWorkAreaIdsFromCache(List<Guid> workAreaIds)
|
public async Task<List<WorkItemMongoDB>> GetWorkItemsByWorkAreaIdsFromCache(List<Guid> workAreaIds, List<Guid> serviceIds)
|
||||||
{
|
{
|
||||||
var stringWorkAreaIds = workAreaIds.Select(wa => wa.ToString()).ToList();
|
var stringWorkAreaIds = workAreaIds.Select(wa => wa.ToString()).ToList();
|
||||||
var filter = Builders<WorkItemMongoDB>.Filter.In(w => w.WorkAreaId, stringWorkAreaIds);
|
|
||||||
|
var filterBuilder = Builders<WorkItemMongoDB>.Filter;
|
||||||
|
var filter = filterBuilder.Empty;
|
||||||
|
|
||||||
|
filter &= filterBuilder.In(w => w.WorkAreaId, stringWorkAreaIds);
|
||||||
|
if (serviceIds.Any())
|
||||||
|
{
|
||||||
|
var stringServiceIds = serviceIds.Select(s => s.ToString()).ToList();
|
||||||
|
filter &= filterBuilder.In(w => w.ActivityMaster!.ActivityGroupMaster!.Service!.Id, stringServiceIds);
|
||||||
|
}
|
||||||
|
|
||||||
var workItems = await _taskCollection // replace with your actual collection name
|
var workItems = await _taskCollection // replace with your actual collection name
|
||||||
.Find(filter)
|
.Find(filter)
|
||||||
@ -449,9 +458,17 @@ namespace Marco.Pms.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<List<WorkItemMongoDB>> GetWorkItemDetailsByWorkAreaFromCache(Guid workAreaId)
|
public async Task<List<WorkItemMongoDB>> GetWorkItemDetailsByWorkAreaFromCache(Guid workAreaId, List<Guid> serviceIds)
|
||||||
{
|
{
|
||||||
var filter = Builders<WorkItemMongoDB>.Filter.Eq(p => p.WorkAreaId, workAreaId.ToString());
|
var filterBuilder = Builders<WorkItemMongoDB>.Filter;
|
||||||
|
var filter = filterBuilder.Empty;
|
||||||
|
|
||||||
|
filter &= filterBuilder.Eq(p => p.WorkAreaId, workAreaId.ToString());
|
||||||
|
if (serviceIds.Any())
|
||||||
|
{
|
||||||
|
var stringServiceIds = serviceIds.Select(s => s.ToString()).ToList();
|
||||||
|
filter &= filterBuilder.In(w => w.ActivityMaster!.ActivityGroupMaster!.Service!.Id, stringServiceIds);
|
||||||
|
}
|
||||||
|
|
||||||
var options = new UpdateOptions { IsUpsert = true };
|
var options = new UpdateOptions { IsUpsert = true };
|
||||||
var workItems = await _taskCollection
|
var workItems = await _taskCollection
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
namespace Marco.Pms.Model.MongoDBModels.Masters
|
||||||
|
{
|
||||||
|
public class ActivityGroupMasterMongoDB
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = string.Empty;
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public ServiceMasterMongoDB? Service { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.MongoDBModels.Masters
|
||||||
|
{
|
||||||
|
public class ServiceMasterMongoDB
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = string.Empty;
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
namespace Marco.Pms.Model.MongoDBModels.Project
|
using Marco.Pms.Model.MongoDBModels.Masters;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.MongoDBModels.Project
|
||||||
{
|
{
|
||||||
public class ActivityMasterMongoDB
|
public class ActivityMasterMongoDB
|
||||||
{
|
{
|
||||||
public string Id { get; set; } = string.Empty;
|
public string Id { get; set; } = string.Empty;
|
||||||
public string? ActivityName { get; set; }
|
public string? ActivityName { get; set; }
|
||||||
public string? UnitOfMeasurement { get; set; }
|
public string? UnitOfMeasurement { get; set; }
|
||||||
|
public ActivityGroupMasterMongoDB? ActivityGroupMaster { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Master
|
||||||
|
{
|
||||||
|
public class ActivityGroupDetailsListVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsSystem { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public List<ActivityVM>? Activities { get; set; }
|
||||||
|
}
|
||||||
|
}
|
12
Marco.Pms.Model/ViewModels/Master/ServiceDetailsListVM.cs
Normal file
12
Marco.Pms.Model/ViewModels/Master/ServiceDetailsListVM.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Marco.Pms.Model.ViewModels.Master
|
||||||
|
{
|
||||||
|
public class ServiceDetailsListVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsSystem { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public List<ActivityGroupDetailsListVM>? ActivityGroups { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -2,12 +2,10 @@
|
|||||||
using Marco.Pms.Model.Dtos.Activities;
|
using Marco.Pms.Model.Dtos.Activities;
|
||||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||||
using Marco.Pms.Model.Dtos.Master;
|
using Marco.Pms.Model.Dtos.Master;
|
||||||
using Marco.Pms.Model.Entitlements;
|
|
||||||
using Marco.Pms.Model.Forum;
|
using Marco.Pms.Model.Forum;
|
||||||
using Marco.Pms.Model.Mapper;
|
using Marco.Pms.Model.Mapper;
|
||||||
using Marco.Pms.Model.Master;
|
using Marco.Pms.Model.Master;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Marco.Pms.Model.ViewModels.Activities;
|
|
||||||
using Marco.Pms.Model.ViewModels.Forum;
|
using Marco.Pms.Model.ViewModels.Forum;
|
||||||
using Marco.Pms.Model.ViewModels.Master;
|
using Marco.Pms.Model.ViewModels.Master;
|
||||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||||
@ -96,6 +94,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("service/all/list")]
|
||||||
|
public async Task<IActionResult> GetServiceDetailsList([FromQuery] Guid? serviceId)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _masterService.GetServiceDetailsListAsync(serviceId, loggedInEmployee, tenantId);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("service/create")]
|
[HttpPost("service/create")]
|
||||||
public async Task<IActionResult> CreateService([FromBody] ServiceMasterDto serviceMasterDto)
|
public async Task<IActionResult> CreateService([FromBody] ServiceMasterDto serviceMasterDto)
|
||||||
{
|
{
|
||||||
@ -125,10 +131,10 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
#region =================================================================== Activity Group APIs ===================================================================
|
#region =================================================================== Activity Group APIs ===================================================================
|
||||||
|
|
||||||
[HttpGet("activity-group/list")]
|
[HttpGet("activity-group/list")]
|
||||||
public async Task<IActionResult> GetActivityGroups()
|
public async Task<IActionResult> GetActivityGroups([FromQuery] Guid? serviceId)
|
||||||
{
|
{
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var response = await _masterService.GetActivityGroupsAsync(loggedInEmployee, tenantId);
|
var response = await _masterService.GetActivityGroupsAsync(serviceId, loggedInEmployee, tenantId);
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,152 +168,35 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("activities")]
|
[Route("activities")]
|
||||||
public async Task<IActionResult> GetActivitiesMaster()
|
public async Task<IActionResult> GetActivitiesMaster([FromQuery] Guid? activityGroupId)
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var activities = await _context.ActivityMasters.Where(c => c.TenantId == tenantId && c.IsActive == true).ToListAsync();
|
var response = await _masterService.GetActivitiesMasterAsync(activityGroupId, loggedInEmployee, tenantId);
|
||||||
List<ActivityVM> activitiesVM = new List<ActivityVM>();
|
return StatusCode(response.StatusCode, response);
|
||||||
foreach (var activity in activities)
|
|
||||||
{
|
|
||||||
var checkList = await _context.ActivityCheckLists.Where(c => c.TenantId == tenantId && c.ActivityId == activity.Id).ToListAsync();
|
|
||||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
|
||||||
if (checkList != null)
|
|
||||||
{
|
|
||||||
foreach (ActivityCheckList check in checkList)
|
|
||||||
{
|
|
||||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id, false);
|
|
||||||
checkListVM.Add(checkVM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivityVM activityVM = activity.ToActivityVMFromActivityMaster(checkListVM);
|
|
||||||
activitiesVM.Add(activityVM);
|
|
||||||
}
|
|
||||||
_logger.LogInfo("{count} activity records fetched successfully from tenant {tenantId}", activitiesVM.Count, tenantId);
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(activitiesVM, System.String.Format("{0} activity records fetched successfully", activitiesVM.Count), 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("activity")]
|
[HttpPost("activity")]
|
||||||
public async Task<IActionResult> CreateActivity([FromBody] CreateActivityMasterDto createActivity)
|
public async Task<IActionResult> CreateActivity([FromBody] CreateActivityMasterDto createActivity)
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var employee = await _userHelper.GetCurrentEmployeeAsync();
|
var response = await _masterService.CreateActivityAsync(createActivity, loggedInEmployee, tenantId);
|
||||||
if (employee.TenantId != tenantId)
|
return StatusCode(response.StatusCode, response);
|
||||||
{
|
|
||||||
_logger.LogWarning("User from tenant {employeeTenantId} tries to access data from tenant {tenantId}", employee.TenantId ?? Guid.Empty, tenantId);
|
|
||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("Current tenant did not match with user's tenant", "Current tenant did not match with user's tenant", 401));
|
|
||||||
}
|
|
||||||
var activityMaster = createActivity.ToActivityMasterFromCreateActivityMasterDto(tenantId);
|
|
||||||
_context.ActivityMasters.Add(activityMaster);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
|
||||||
|
|
||||||
if (createActivity.CheckList != null)
|
|
||||||
{
|
|
||||||
List<ActivityCheckList> activityCheckList = new List<ActivityCheckList>();
|
|
||||||
foreach (var check in createActivity.CheckList)
|
|
||||||
{
|
|
||||||
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId, activityMaster.Id);
|
|
||||||
activityCheckList.Add(checkList);
|
|
||||||
}
|
|
||||||
_context.ActivityCheckLists.AddRange(activityCheckList);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
foreach (ActivityCheckList check in activityCheckList)
|
|
||||||
{
|
|
||||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activityMaster.Id, false);
|
|
||||||
checkListVM.Add(checkVM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ActivityVM activityVM = activityMaster.ToActivityVMFromActivityMaster(checkListVM);
|
|
||||||
|
|
||||||
_logger.LogInfo("activity created successfully from tenant {tenantId}", tenantId);
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity created successfully", 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("activity/edit/{id}")]
|
[HttpPost("activity/edit/{id}")]
|
||||||
public async Task<IActionResult> UpdateActivity(Guid id, [FromBody] CreateActivityMasterDto createActivity)
|
public async Task<IActionResult> UpdateActivity(Guid id, [FromBody] CreateActivityMasterDto createActivity)
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var employee = await _userHelper.GetCurrentEmployeeAsync();
|
var response = await _masterService.UpdateActivityAsync(id, createActivity, loggedInEmployee, tenantId);
|
||||||
ActivityMaster? activity = await _context.ActivityMasters.FirstOrDefaultAsync(x => x.Id == id && x.IsActive == true && x.TenantId == tenantId);
|
return StatusCode(response.StatusCode, response);
|
||||||
if (activity != null && createActivity.UnitOfMeasurement != null && createActivity.ActivityName != null)
|
|
||||||
{
|
|
||||||
|
|
||||||
activity.ActivityName = createActivity.ActivityName;
|
|
||||||
activity.UnitOfMeasurement = createActivity.UnitOfMeasurement;
|
|
||||||
List<ActivityCheckList> activityCheckLists = await _context.ActivityCheckLists.AsNoTracking().Where(c => c.ActivityId == activity.Id).ToListAsync();
|
|
||||||
List<CheckListVM> checkListVM = new List<CheckListVM>();
|
|
||||||
|
|
||||||
if (createActivity.CheckList != null)
|
|
||||||
{
|
|
||||||
|
|
||||||
var newCheckIds = createActivity.CheckList.Select(c => c.Id);
|
|
||||||
|
|
||||||
List<ActivityCheckList> updateCheckList = new List<ActivityCheckList>();
|
|
||||||
List<ActivityCheckList> deleteCheckList = new List<ActivityCheckList>();
|
|
||||||
if (newCheckIds.Contains(null))
|
|
||||||
{
|
|
||||||
foreach (var check in createActivity.CheckList)
|
|
||||||
{
|
|
||||||
if (check.Id == null)
|
|
||||||
{
|
|
||||||
ActivityCheckList checkList = check.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id);
|
|
||||||
updateCheckList.Add(checkList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var check in activityCheckLists)
|
|
||||||
{
|
|
||||||
if (newCheckIds.Contains(check.Id))
|
|
||||||
{
|
|
||||||
var updatedCheck = createActivity.CheckList.Find(c => c.Id == check.Id);
|
|
||||||
ActivityCheckList checkList = updatedCheck != null ? updatedCheck.ToActivityCheckListFromCreateCheckListDto(tenantId, activity.Id) : new ActivityCheckList();
|
|
||||||
updateCheckList.Add(checkList);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
deleteCheckList.Add(check);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_context.ActivityCheckLists.UpdateRange(updateCheckList);
|
|
||||||
if (deleteCheckList != null)
|
|
||||||
{
|
|
||||||
_context.ActivityCheckLists.RemoveRange(deleteCheckList);
|
|
||||||
}
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
foreach (ActivityCheckList check in updateCheckList)
|
|
||||||
{
|
|
||||||
var checkVM = check.ToCheckListVMFromActivityCheckList(activity.Id, false);
|
|
||||||
checkListVM.Add(checkVM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (activityCheckLists != null)
|
|
||||||
{
|
|
||||||
_context.ActivityCheckLists.RemoveRange(activityCheckLists);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
ActivityVM activityVM = activity.ToActivityVMFromActivityMaster(checkListVM);
|
|
||||||
_logger.LogInfo("activity updated successfully from tenant {tenantId}", tenantId);
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(activityVM, "activity updated successfully", 200));
|
|
||||||
}
|
|
||||||
_logger.LogWarning("Activity {ActivityId} not found", id);
|
|
||||||
return NotFound(ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("activity/delete/{id}")]
|
[HttpDelete("activity/delete/{id}")]
|
||||||
public async Task<IActionResult> DeleteActivity(Guid Id)
|
public async Task<IActionResult> DeleteActivity(Guid id, [FromQuery] bool active = false)
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var activity = await _context.ActivityMasters.FirstOrDefaultAsync(a => a.Id == Id && a.TenantId == tenantId);
|
var response = await _masterService.DeleteActivityAsync(id, active, loggedInEmployee, tenantId);
|
||||||
if (activity != null)
|
return StatusCode(response.StatusCode, response);
|
||||||
{
|
|
||||||
activity.IsActive = false;
|
|
||||||
}
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
_logger.LogInfo("Activity Deleted Successfully from tenant {tenantId}", tenantId);
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Activity Deleted Successfully", 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -342,7 +342,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("tasks/{workAreaId}")]
|
[HttpGet("tasks/{workAreaId}")]
|
||||||
public async Task<IActionResult> GetWorkItems(Guid workAreaId)
|
public async Task<IActionResult> GetWorkItems(Guid workAreaId, [FromQuery] Guid? serviceId)
|
||||||
{
|
{
|
||||||
// --- Step 1: Input Validation ---
|
// --- Step 1: Input Validation ---
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
@ -354,7 +354,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
// --- Step 2: Prepare data without I/O ---
|
// --- Step 2: Prepare data without I/O ---
|
||||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var response = await _projectServices.GetWorkItemsAsync(workAreaId, tenantId, loggedInEmployee);
|
var response = await _projectServices.GetWorkItemsAsync(workAreaId, serviceId, tenantId, loggedInEmployee);
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
[HttpGet("tasks-employee/{employeeId}")]
|
[HttpGet("tasks-employee/{employeeId}")]
|
||||||
|
@ -599,11 +599,11 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
|
|
||||||
#region ======================================================= WorkItem Cache =======================================================
|
#region ======================================================= WorkItem Cache =======================================================
|
||||||
|
|
||||||
public async Task<List<WorkItemMongoDB>?> GetWorkItemsByWorkAreaIds(List<Guid> workAreaIds)
|
public async Task<List<WorkItemMongoDB>?> GetWorkItemsByWorkAreaIds(List<Guid> workAreaIds, List<Guid> serviceIds)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await _projectCache.GetWorkItemsByWorkAreaIdsFromCache(workAreaIds);
|
var response = await _projectCache.GetWorkItemsByWorkAreaIdsFromCache(workAreaIds, serviceIds);
|
||||||
if (response.Count > 0)
|
if (response.Count > 0)
|
||||||
{
|
{
|
||||||
return response;
|
return response;
|
||||||
@ -640,11 +640,11 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
_logger.LogWarning("Error occured while saving workItems form Cache: {Error}", ex.Message);
|
_logger.LogWarning("Error occured while saving workItems form Cache: {Error}", ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<List<WorkItemMongoDB>?> GetWorkItemDetailsByWorkArea(Guid workAreaId)
|
public async Task<List<WorkItemMongoDB>?> GetWorkItemDetailsByWorkArea(Guid workAreaId, List<Guid> serviceIds)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var workItems = await _projectCache.GetWorkItemDetailsByWorkAreaFromCache(workAreaId);
|
var workItems = await _projectCache.GetWorkItemDetailsByWorkAreaFromCache(workAreaId, serviceIds);
|
||||||
if (workItems.Count > 0)
|
if (workItems.Count > 0)
|
||||||
{
|
{
|
||||||
return workItems;
|
return workItems;
|
||||||
|
@ -141,8 +141,11 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
// Task 1: Fetch the WorkItem entities and their related data.
|
// Task 1: Fetch the WorkItem entities and their related data.
|
||||||
var workItemsTask = _context.WorkItems
|
var workItemsTask = _context.WorkItems
|
||||||
.Include(wi => wi.ActivityMaster)
|
.Include(wi => wi.ActivityMaster)
|
||||||
|
.ThenInclude(am => am!.ActivityGroup)
|
||||||
|
.ThenInclude(ag => ag!.Service)
|
||||||
.Include(wi => wi.WorkCategoryMaster)
|
.Include(wi => wi.WorkCategoryMaster)
|
||||||
.Where(wi => wi.WorkAreaId == workAreaId)
|
.Where(wi => wi.WorkAreaId == workAreaId && wi.ActivityMaster != null && wi.ActivityMaster.ActivityGroup != null
|
||||||
|
&& wi.ActivityMaster.ActivityGroup.Service != null && wi.WorkCategoryMaster != null)
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -189,7 +192,19 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
{
|
{
|
||||||
Id = wi.ActivityMaster.Id.ToString(),
|
Id = wi.ActivityMaster.Id.ToString(),
|
||||||
ActivityName = wi.ActivityMaster.ActivityName,
|
ActivityName = wi.ActivityMaster.ActivityName,
|
||||||
UnitOfMeasurement = wi.ActivityMaster.UnitOfMeasurement
|
UnitOfMeasurement = wi.ActivityMaster.UnitOfMeasurement,
|
||||||
|
ActivityGroupMaster = new ActivityGroupMasterMongoDB
|
||||||
|
{
|
||||||
|
Id = wi.ActivityMaster.ActivityGroup!.Id.ToString(),
|
||||||
|
Name = wi.ActivityMaster.ActivityGroup.Name,
|
||||||
|
Description = wi.ActivityMaster.ActivityGroup.Description,
|
||||||
|
Service = new ServiceMasterMongoDB
|
||||||
|
{
|
||||||
|
Id = wi.ActivityMaster.ActivityGroup.Service!.Id.ToString(),
|
||||||
|
Name = wi.ActivityMaster.ActivityGroup.Service.Name,
|
||||||
|
Description = wi.ActivityMaster.ActivityGroup.Service.Description
|
||||||
|
}
|
||||||
|
}
|
||||||
} : null,
|
} : null,
|
||||||
WorkCategoryMaster = wi.WorkCategoryMaster != null ? new WorkCategoryMasterMongoDB
|
WorkCategoryMaster = wi.WorkCategoryMaster != null ? new WorkCategoryMasterMongoDB
|
||||||
{
|
{
|
||||||
|
@ -148,7 +148,7 @@ namespace Marco.Pms.Services.Helpers
|
|||||||
var areaIds = areas.Select(a => Guid.Parse(a.Id)).ToList();
|
var areaIds = areas.Select(a => Guid.Parse(a.Id)).ToList();
|
||||||
|
|
||||||
// fetch Work Items
|
// fetch Work Items
|
||||||
workItems = await _cache.GetWorkItemsByWorkAreaIds(areaIds);
|
workItems = await _cache.GetWorkItemsByWorkAreaIds(areaIds, new List<Guid>());
|
||||||
if (workItems == null || !workItems.Any())
|
if (workItems == null || !workItems.Any())
|
||||||
{
|
{
|
||||||
workItems = await _context.WorkItems
|
workItems = await _context.WorkItems
|
||||||
|
@ -269,7 +269,7 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
|
|
||||||
#region ======================================================= Activity Group Master =======================================================
|
#region ======================================================= Activity Group Master =======================================================
|
||||||
|
|
||||||
CreateMap<ServiceMasterDto, ActivityGroupMaster>()
|
CreateMap<ActivityGroupDto, ActivityGroupMaster>()
|
||||||
.ForMember(
|
.ForMember(
|
||||||
dest => dest.Id,
|
dest => dest.Id,
|
||||||
// Explicitly and safely convert nullable Guid to non-nullable Guid
|
// Explicitly and safely convert nullable Guid to non-nullable Guid
|
||||||
|
@ -261,6 +261,118 @@ namespace Marco.Pms.Services.Service
|
|||||||
return ApiResponse<object>.ErrorResponse("An error occurred while fetching services", ex.Message, 500);
|
return ApiResponse<object>.ErrorResponse("An error occurred while fetching services", ex.Message, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously retrieves a structured list of services, their activity groups, activities, and associated checklists for a specific tenant.
|
||||||
|
/// This method fetches data in multiple steps and processes it in-memory, preserving the original business logic.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="loggedInEmployee">The employee currently logged in. This parameter is available for future authorization or logging extensions.</param>
|
||||||
|
/// <param name="tenantId">The unique identifier of the tenant for which to retrieve the data.</param>
|
||||||
|
/// <returns>An ApiResponse containing a list of ServiceDetailsListVM or an error message in case of failure.</returns>
|
||||||
|
public async Task<ApiResponse<object>> GetServiceDetailsListAsync(Guid? serviceId, Employee loggedInEmployee, Guid tenantId)
|
||||||
|
{
|
||||||
|
// Log the initiation of the request with structured parameters for better traceability.
|
||||||
|
_logger.LogInfo("Attempting to fetch service details list for TenantId: {TenantId}", tenantId);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// --- Step 1: Fetch all relevant activities for the tenant ---
|
||||||
|
// This query retrieves all active 'ActivityMaster' records for the given tenant that are properly linked to an ActivityGroup and a Service.
|
||||||
|
// Eager loading (.Include/.ThenInclude) is used to bring in related ActivityGroup and Service entities to prevent N+1 query problems later.
|
||||||
|
var activityQuery = _context.ActivityMasters
|
||||||
|
.Include(a => a.ActivityGroup)
|
||||||
|
.ThenInclude(ag => ag!.Service)
|
||||||
|
.Where(a => a.TenantId == tenantId && a.IsActive);
|
||||||
|
|
||||||
|
if (serviceId.HasValue)
|
||||||
|
{
|
||||||
|
activityQuery = activityQuery.Where(a => a.ActivityGroup != null && a.ActivityGroup.Service != null && a.ActivityGroup.Service.Id == serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var activities = await activityQuery
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
_logger.LogInfo("Step 1 complete: Fetched {ActivityCount} activities for TenantId: {TenantId}", activities.Count, tenantId);
|
||||||
|
|
||||||
|
// --- Step 2: Fetch all checklists related to the retrieved activities ---
|
||||||
|
// To avoid fetching all checklists in the database, we first collect the IDs of the activities from the previous step.
|
||||||
|
var activityIds = activities.Select(a => a.Id).ToList();
|
||||||
|
|
||||||
|
// This second database query fetches only the 'ActivityCheckList' records associated with the relevant activities.
|
||||||
|
var checkLists = await _context.ActivityCheckLists
|
||||||
|
.Where(c => c.TenantId == tenantId && activityIds.Contains(c.ActivityId))
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
_logger.LogInfo("Step 2 complete: Fetched {ChecklistCount} checklists for TenantId: {TenantId}", checkLists.Count, tenantId);
|
||||||
|
|
||||||
|
// --- Step 3: Group checklists by activity in memory for efficient lookup ---
|
||||||
|
// To quickly find all checklists for a given activity, we group the flat list of checklists into a dictionary.
|
||||||
|
// The key is the ActivityId, and the value is the list of associated checklists.
|
||||||
|
var groupedChecklists = checkLists
|
||||||
|
.GroupBy(c => c.ActivityId)
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
|
// --- Step 4: Build the hierarchical ViewModel structure in memory ---
|
||||||
|
// First, get distinct lists of services and activity groups from the already fetched 'activities' collection.
|
||||||
|
var services = activities.Select(a => a.ActivityGroup!.Service!).Distinct().ToList();
|
||||||
|
var activityGroupList = activities.Select(a => a.ActivityGroup!).Distinct().ToList();
|
||||||
|
|
||||||
|
// Now, construct the final nested ViewModel.
|
||||||
|
// This part iterates through the distinct services and builds the response object by filtering the in-memory collections.
|
||||||
|
List<ServiceDetailsListVM> Vm = services.Select(s =>
|
||||||
|
{
|
||||||
|
var response = new ServiceDetailsListVM
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
Name = s.Name,
|
||||||
|
Description = s.Description,
|
||||||
|
IsActive = s.IsActive,
|
||||||
|
IsSystem = s.IsSystem,
|
||||||
|
ActivityGroups = activityGroupList
|
||||||
|
.Where(ag => ag.ServiceId == s.Id) // Find groups for the current service
|
||||||
|
.Select(ag => new ActivityGroupDetailsListVM
|
||||||
|
{
|
||||||
|
Id = ag.Id,
|
||||||
|
Name = ag.Name,
|
||||||
|
Description = ag.Description,
|
||||||
|
IsActive = ag.IsActive,
|
||||||
|
IsSystem = ag.IsSystem,
|
||||||
|
Activities = activities
|
||||||
|
.Where(a => a.ActivityGroupId == ag.Id) // Find activities for the current group
|
||||||
|
.Select(a =>
|
||||||
|
{
|
||||||
|
// Retrieve the checklists for the current activity from our dictionary lookup.
|
||||||
|
var checklistForActivity = groupedChecklists.ContainsKey(a.Id)
|
||||||
|
? groupedChecklists[a.Id]
|
||||||
|
: new List<ActivityCheckList>();
|
||||||
|
|
||||||
|
return new ActivityVM
|
||||||
|
{
|
||||||
|
Id = a.Id,
|
||||||
|
ActivityName = a.ActivityName,
|
||||||
|
UnitOfMeasurement = a.UnitOfMeasurement,
|
||||||
|
// BUG FIX: Correctly mapping properties from the activity ('a') itself, not the parent service ('s').
|
||||||
|
IsActive = a.IsActive,
|
||||||
|
IsSystem = a.IsSystem,
|
||||||
|
CheckLists = _mapper.Map<List<CheckListVM>>(checklistForActivity)
|
||||||
|
};
|
||||||
|
}).ToList()
|
||||||
|
}).ToList()
|
||||||
|
};
|
||||||
|
return response;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
_logger.LogInfo("Successfully processed and mapped {ServiceCount} services for TenantId: {TenantId}", Vm.Count, tenantId);
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(Vm, "Service details list fetched successfully", 200);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// If any part of the process fails, log the detailed exception and return a standardized error response.
|
||||||
|
_logger.LogError(ex, "An error occurred while fetching service details for TenantId: {TenantId}", tenantId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("An internal server error occurred while fetching service details.", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
public async Task<ApiResponse<object>> CreateServiceAsync(ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId)
|
public async Task<ApiResponse<object>> CreateServiceAsync(ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("CreateService called with Name: {ServiceName}", serviceMasterDto.Name);
|
_logger.LogInfo("CreateService called with Name: {ServiceName}", serviceMasterDto.Name);
|
||||||
@ -407,16 +519,23 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
#region =================================================================== Activity Group APIs ===================================================================
|
#region =================================================================== Activity Group APIs ===================================================================
|
||||||
|
|
||||||
public async Task<ApiResponse<object>> GetActivityGroupsAsync(Employee loggedInEmployee, Guid tenantId)
|
public async Task<ApiResponse<object>> GetActivityGroupsAsync(Guid? serviceId, Employee loggedInEmployee, Guid tenantId)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("GetActivityGroups called");
|
_logger.LogInfo("GetActivityGroups called");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Step 1: Fetch all activity groups for the tenant
|
// Step 1: Fetch all activity groups for the tenant
|
||||||
var activityGroups = await _context.ActivityGroupMasters
|
var activityGroupQuery = _context.ActivityGroupMasters
|
||||||
.Include(ag => ag.Service)
|
.Include(ag => ag.Service)
|
||||||
.Where(ag => ag.TenantId == tenantId && ag.IsActive)
|
.Where(ag => ag.TenantId == tenantId && ag.IsActive);
|
||||||
|
|
||||||
|
if (serviceId.HasValue)
|
||||||
|
{
|
||||||
|
activityGroupQuery = activityGroupQuery.Where(ag => ag.ServiceId == serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var activityGroups = await activityGroupQuery
|
||||||
.Select(ag => _mapper.Map<ActivityGroupMasterVM>(ag))
|
.Select(ag => _mapper.Map<ActivityGroupMasterVM>(ag))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -586,17 +705,25 @@ namespace Marco.Pms.Services.Service
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Activity APIs ===================================================================
|
#region =================================================================== Activity APIs ===================================================================
|
||||||
public async Task<ApiResponse<object>> GetActivitiesMasterAsync(Employee loggedInEmployee, Guid tenantId)
|
public async Task<ApiResponse<object>> GetActivitiesMasterAsync(Guid? activityGroupId, Employee loggedInEmployee, Guid tenantId)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("GetActivitiesMaster called");
|
_logger.LogInfo("GetActivitiesMaster called");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Step 1: Fetch all active activities for the tenant
|
// Step 1: Fetch all active activities for the tenant
|
||||||
var activities = await _context.ActivityMasters
|
|
||||||
|
var activityQuery = _context.ActivityMasters
|
||||||
.Include(c => c.ActivityGroup)
|
.Include(c => c.ActivityGroup)
|
||||||
.ThenInclude(ag => ag!.Service)
|
.ThenInclude(ag => ag!.Service)
|
||||||
.Where(c => c.TenantId == tenantId && c.IsActive)
|
.Where(c => c.TenantId == tenantId && c.IsActive);
|
||||||
|
|
||||||
|
if (activityGroupId.HasValue)
|
||||||
|
{
|
||||||
|
activityQuery = activityQuery.Where(a => a.ActivityGroupId == activityGroupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var activities = await activityQuery
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (activities.Count == 0)
|
if (activities.Count == 0)
|
||||||
|
@ -1160,7 +1160,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
/// <param name="tenantId">The ID of the current tenant.</param>
|
/// <param name="tenantId">The ID of the current tenant.</param>
|
||||||
/// <param name="loggedInEmployee">The current authenticated employee for permission checks.</param>
|
/// <param name="loggedInEmployee">The current authenticated employee for permission checks.</param>
|
||||||
/// <returns>An ApiResponse containing a list of work items or an error.</returns>
|
/// <returns>An ApiResponse containing a list of work items or an error.</returns>
|
||||||
public async Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid tenantId, Employee loggedInEmployee)
|
public async Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid? serviceId, Guid tenantId, Employee loggedInEmployee)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("GetWorkItems called for WorkAreaId: {WorkAreaId} by User: {UserId}", workAreaId, loggedInEmployee.Id);
|
_logger.LogInfo("GetWorkItems called for WorkAreaId: {WorkAreaId} by User: {UserId}", workAreaId, loggedInEmployee.Id);
|
||||||
|
|
||||||
@ -1170,8 +1170,78 @@ namespace Marco.Pms.Services.Service
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
|
||||||
|
var projectId = await _context.WorkAreas
|
||||||
|
.Where(wa => wa.Id == workAreaId && wa.TenantId == tenantId && wa.Floor != null && wa.Floor.Building != null)
|
||||||
|
.Select(wa => wa.Floor!.Building!.ProjectId)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (projectId == Guid.Empty)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Work Area not found for WorkAreaId: {WorkAreaId}", workAreaId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Not Found", $"Work Area with ID {workAreaId} not found.", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
var project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
||||||
|
if (project == null)
|
||||||
|
{
|
||||||
|
return ApiResponse<object>.ErrorResponse("Project not found", "Project not found in database", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasProjectAccessTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
using var taskScope = _serviceScopeFactory.CreateScope();
|
||||||
|
var permission = taskScope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await permission.HasProjectPermission(loggedInEmployee, projectId);
|
||||||
|
});
|
||||||
|
var hasGenericViewInfraPermissionTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
using var taskScope = _serviceScopeFactory.CreateScope();
|
||||||
|
var permission = taskScope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
return await permission.HasPermission(PermissionsMaster.ViewProjectInfra, loggedInEmployee.Id, projectId);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(hasProjectAccessTask, hasGenericViewInfraPermissionTask);
|
||||||
|
|
||||||
|
var hasProjectAccess = hasProjectAccessTask.Result;
|
||||||
|
var hasGenericViewInfraPermission = hasGenericViewInfraPermissionTask.Result;
|
||||||
|
|
||||||
|
if (!hasProjectAccess || !hasGenericViewInfraPermission)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Access DENIED for user {UserId} on WorkAreaId {WorkAreaId}.", loggedInEmployee.Id, workAreaId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Access Denied", "You do not have sufficient permissions to view these work items.", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Guid> serviceIds = new List<Guid>();
|
||||||
|
if (!serviceId.HasValue)
|
||||||
|
{
|
||||||
|
if (project.PromoterId == loggedInEmployee.OrganizationId && project.PMCId == loggedInEmployee.OrganizationId)
|
||||||
|
{
|
||||||
|
var projectServices = await _context.ProjectServiceMappings
|
||||||
|
.Include(ps => ps.Service)
|
||||||
|
.Where(ps => ps.ProjectId == projectId && ps.Service != null && ps.TenantId == tenantId && ps.IsActive)
|
||||||
|
.ToListAsync();
|
||||||
|
serviceIds = projectServices.Select(ps => ps.ServiceId).Distinct().ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var orgProjectMapping = await _context.ProjectOrgMappings
|
||||||
|
.Include(po => po.ProjectService)
|
||||||
|
.ThenInclude(ps => ps!.Service)
|
||||||
|
.Where(po => po.OrganizationId == loggedInEmployee.OrganizationId && po.ProjectService != null
|
||||||
|
&& po.ProjectService.IsActive && po.ProjectService.ProjectId == projectId && po.ProjectService.Service != null)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
serviceIds = orgProjectMapping.Select(po => po.ProjectService!.ServiceId).Distinct().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serviceIds.Add(serviceId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
// --- Step 1: Cache-First Strategy ---
|
// --- Step 1: Cache-First Strategy ---
|
||||||
var cachedWorkItems = await _cache.GetWorkItemDetailsByWorkArea(workAreaId);
|
var cachedWorkItems = await _cache.GetWorkItemDetailsByWorkArea(workAreaId, serviceIds);
|
||||||
if (cachedWorkItems != null)
|
if (cachedWorkItems != null)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Cache HIT for WorkAreaId: {WorkAreaId}. Returning {Count} items from cache.", workAreaId, cachedWorkItems.Count);
|
_logger.LogInfo("Cache HIT for WorkAreaId: {WorkAreaId}. Returning {Count} items from cache.", workAreaId, cachedWorkItems.Count);
|
||||||
@ -1180,28 +1250,6 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
_logger.LogInfo("Cache MISS for WorkAreaId: {WorkAreaId}. Fetching from database.", workAreaId);
|
_logger.LogInfo("Cache MISS for WorkAreaId: {WorkAreaId}. Fetching from database.", workAreaId);
|
||||||
|
|
||||||
// --- Step 2: Security Check First ---
|
|
||||||
// This pattern remains the most robust: verify permissions before fetching a large list.
|
|
||||||
var projectInfo = await _context.WorkAreas
|
|
||||||
.Where(wa => wa.Id == workAreaId && wa.TenantId == tenantId && wa.Floor != null && wa.Floor.Building != null)
|
|
||||||
.Select(wa => new { wa.Floor!.Building!.ProjectId })
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
if (projectInfo == null)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Work Area not found for WorkAreaId: {WorkAreaId}", workAreaId);
|
|
||||||
return ApiResponse<object>.ErrorResponse("Not Found", $"Work Area with ID {workAreaId} not found.", 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasProjectAccess = await _permission.HasProjectPermission(loggedInEmployee, projectInfo.ProjectId);
|
|
||||||
var hasGenericViewInfraPermission = await _permission.HasPermission(PermissionsMaster.ViewProjectInfra, loggedInEmployee.Id, projectInfo.ProjectId);
|
|
||||||
|
|
||||||
if (!hasProjectAccess || !hasGenericViewInfraPermission)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Access DENIED for user {UserId} on WorkAreaId {WorkAreaId}.", loggedInEmployee.Id, workAreaId);
|
|
||||||
return ApiResponse<object>.ErrorResponse("Access Denied", "You do not have sufficient permissions to view these work items.", 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Step 3: Fetch Full Entities for Caching and Mapping ---
|
// --- Step 3: Fetch Full Entities for Caching and Mapping ---
|
||||||
var workItemVMs = await _generalHelper.GetWorkItemsListFromDB(workAreaId);
|
var workItemVMs = await _generalHelper.GetWorkItemsListFromDB(workAreaId);
|
||||||
|
|
||||||
@ -1218,6 +1266,8 @@ namespace Marco.Pms.Services.Service
|
|||||||
_logger.LogError(ex, "Background cache update failed for WorkAreaId: {WorkAreaId}", workAreaId);
|
_logger.LogError(ex, "Background cache update failed for WorkAreaId: {WorkAreaId}", workAreaId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stringServiceIds = serviceIds.Select(s => s.ToString()).ToList();
|
||||||
|
workItemVMs = workItemVMs.Where(wi => stringServiceIds.Contains(wi.ActivityMaster!.ActivityGroupMaster!.Service!.Id)).ToList();
|
||||||
|
|
||||||
_logger.LogInfo("{Count} work items fetched successfully for WorkAreaId: {WorkAreaId}", workItemVMs.Count, workAreaId);
|
_logger.LogInfo("{Count} work items fetched successfully for WorkAreaId: {WorkAreaId}", workItemVMs.Count, workAreaId);
|
||||||
return ApiResponse<object>.SuccessResponse(workItemVMs, $"{workItemVMs.Count} tasks fetched successfully.", 200);
|
return ApiResponse<object>.SuccessResponse(workItemVMs, $"{workItemVMs.Count} tasks fetched successfully.", 200);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
using Marco.Pms.Model.Dtos.Activities;
|
||||||
|
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||||
using Marco.Pms.Model.Dtos.Master;
|
using Marco.Pms.Model.Dtos.Master;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
@ -20,15 +21,26 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
//Task<ApiResponse<object>> DeleteGlobalServiceAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId);
|
//Task<ApiResponse<object>> DeleteGlobalServiceAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Service Master APIs ===================================================================
|
#region =================================================================== Service Master APIs ===================================================================
|
||||||
Task<ApiResponse<object>> GetServicesAsync(Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> GetServicesAsync(Employee loggedInEmployee, Guid tenantId);
|
||||||
|
Task<ApiResponse<object>> GetServiceDetailsListAsync(Guid? serviceId, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> CreateServiceAsync(ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> CreateServiceAsync(ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> UpdateServiceAsync(Guid id, ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> UpdateServiceAsync(Guid id, ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> DeleteServiceAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> DeleteServiceAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region =================================================================== Activity APIs ===================================================================
|
||||||
|
Task<ApiResponse<object>> GetActivitiesMasterAsync(Guid? activityGroupId, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
Task<ApiResponse<object>> CreateActivityAsync(CreateActivityMasterDto createActivity, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
Task<ApiResponse<object>> UpdateActivityAsync(Guid id, CreateActivityMasterDto createActivity, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
Task<ApiResponse<object>> DeleteActivityAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Activity Group Master APIs ===================================================================
|
#region =================================================================== Activity Group Master APIs ===================================================================
|
||||||
Task<ApiResponse<object>> GetActivityGroupsAsync(Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> GetActivityGroupsAsync(Guid? serviceId, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> CreateActivityGroupAsync(ActivityGroupDto activityGroupDto, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> CreateActivityGroupAsync(ActivityGroupDto activityGroupDto, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> UpdateActivityGroupAsync(Guid id, ActivityGroupDto activityGroupDto, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> UpdateActivityGroupAsync(Guid id, ActivityGroupDto activityGroupDto, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> DeleteActivityGroupAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> DeleteActivityGroupAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||||
|
@ -25,7 +25,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
Task<ApiResponse<object>> GetProjectByEmployeeBasicAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetProjectByEmployeeBasicAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
|
||||||
Task<ApiResponse<object>> GetInfraDetailsAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetInfraDetailsAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid? serviceId, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<object>> GetTasksByEmployeeAsync(Guid employeeId, DateTime fromDate, DateTime toDate, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetTasksByEmployeeAsync(Guid employeeId, DateTime fromDate, DateTime toDate, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ServiceResponse> ManageProjectInfraAsync(List<InfraDto> infraDtos, Guid tenantId, Employee loggedInEmployee);
|
Task<ServiceResponse> ManageProjectInfraAsync(List<InfraDto> infraDtos, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<List<WorkItemVM>>> CreateProjectTaskAsync(List<WorkItemDto> workItemDtos, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<List<WorkItemVM>>> CreateProjectTaskAsync(List<WorkItemDto> workItemDtos, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user