Organization_Management #142
@ -38,6 +38,78 @@ namespace Marco.Pms.Services.Controllers
|
||||
tenantId = userHelper.GetTenantId();
|
||||
}
|
||||
|
||||
#region =================================================================== Services APIs ===================================================================
|
||||
|
||||
[HttpGet("service/list")]
|
||||
public async Task<IActionResult> GetServices()
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.GetServicesAsync(loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPost("service/create")]
|
||||
public async Task<IActionResult> CreateService([FromBody] ServiceMasterDto serviceMasterDto)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.CreateServiceAsync(serviceMasterDto, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPut("service/edit/{id}")]
|
||||
public async Task<IActionResult> UpdateService(Guid id, [FromBody] ServiceMasterDto serviceMasterDto)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.UpdateServiceAsync(id, serviceMasterDto, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpDelete("service/delete/{id}")]
|
||||
public async Task<IActionResult> DeleteService(Guid id, [FromQuery] bool active = false)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.DeleteServiceAsync(id, active, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Activity Group APIs ===================================================================
|
||||
|
||||
[HttpGet("activity-group/list")]
|
||||
public async Task<IActionResult> GetActivityGroups()
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.GetActivityGroupsAsync(loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPost("activity-group/create")]
|
||||
public async Task<IActionResult> CreateActivityGroup([FromBody] ActivityGroupDto activityGroupDto)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.CreateActivityGroupAsync(activityGroupDto, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPut("activity-group/edit/{id}")]
|
||||
public async Task<IActionResult> UpdateActivityGroup(Guid id, [FromBody] ActivityGroupDto activityGroupDto)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.UpdateActivityGroupAsync(id, activityGroupDto, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
|
||||
}
|
||||
|
||||
[HttpDelete("activity-group/delete/{id}")]
|
||||
public async Task<IActionResult> DeleteActivityGroup(Guid id, [FromQuery] bool active = false)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.DeleteActivityGroupAsync(id, active, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Activity APIs ===================================================================
|
||||
|
||||
[HttpGet]
|
||||
|
@ -3,6 +3,7 @@ using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Helpers.Utility;
|
||||
using Marco.Pms.Model.Directory;
|
||||
using Marco.Pms.Model.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Activities;
|
||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Master;
|
||||
using Marco.Pms.Model.Employees;
|
||||
@ -11,6 +12,7 @@ using Marco.Pms.Model.Mapper;
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.MongoDBModels.Utility;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.DocumentManager;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
@ -49,6 +51,645 @@ namespace Marco.Pms.Services.Service
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
#region =================================================================== Services APIs ===================================================================
|
||||
public async Task<ApiResponse<object>> GetServicesAsync(Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("GetServices called");
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Fetch services for the tenant
|
||||
var services = await _context.ServiceMasters
|
||||
.Where(s => s.TenantId == tenantId && s.IsActive)
|
||||
.Select(s => _mapper.Map<ServiceMasterVM>(s))
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogInfo("Fetched {Count} service records for tenantId: {TenantId}", services.Count, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(services, $"{services.Count} record(s) of services fetched successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching services");
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred while fetching services", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> CreateServiceAsync(ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("CreateService called with Name: {ServiceName}", serviceMasterDto.Name);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Permission check
|
||||
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasManagePermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("You don't have access", "You don't have permission to take this action", 403);
|
||||
}
|
||||
|
||||
// Step 2: Check for duplicate name
|
||||
bool isExist = await _context.ServiceMasters
|
||||
.AnyAsync(s => s.TenantId == tenantId && s.Name == serviceMasterDto.Name);
|
||||
|
||||
if (isExist)
|
||||
{
|
||||
_logger.LogWarning("Duplicate service name '{ServiceName}' attempted by employeeId: {EmployeeId}", serviceMasterDto.Name, loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse(
|
||||
$"Service with name '{serviceMasterDto.Name}' already exists",
|
||||
$"Service with name '{serviceMasterDto.Name}' already exists", 400);
|
||||
}
|
||||
|
||||
// Step 3: Save new service
|
||||
ServiceMaster service = _mapper.Map<ServiceMaster>(serviceMasterDto);
|
||||
service.TenantId = tenantId;
|
||||
service.IsActive = true;
|
||||
service.IsSystem = false;
|
||||
_context.ServiceMasters.Add(service);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var response = _mapper.Map<ServiceMasterVM>(service);
|
||||
|
||||
_logger.LogInfo("New service '{ServiceName}' created successfully by employeeId: {EmployeeId}", service.Name, loggedInEmployee.Id);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, "New service created successfully", 201);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error creating service");
|
||||
return ApiResponse<object>.ErrorResponse("Failed to create service", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> UpdateServiceAsync(Guid id, ServiceMasterDto serviceMasterDto, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("UpdateService called for Id: {Id}", id);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Step 1: Permission check
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to take this action", 403);
|
||||
}
|
||||
|
||||
// Step 2: Input validation
|
||||
if (serviceMasterDto.Id != id)
|
||||
{
|
||||
_logger.LogWarning("Invalid input data provided for UpdateService. Id: {Id}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Invalid input", "Please provide valid service data", 400);
|
||||
}
|
||||
|
||||
// Step 3: Retrieve service
|
||||
var service = await _context.ServiceMasters
|
||||
.FirstOrDefaultAsync(s => s.Id == id && s.TenantId == tenantId && s.IsActive);
|
||||
|
||||
if (service == null)
|
||||
{
|
||||
_logger.LogWarning("Service not found for Id: {Id}, Tenant: {TenantId}", id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Service not found", "The requested service does not exist", 404);
|
||||
}
|
||||
|
||||
// Step 4: Update and save
|
||||
service.Name = serviceMasterDto.Name.Trim();
|
||||
service.Description = serviceMasterDto.Description.Trim();
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var response = _mapper.Map<ServiceMasterVM>(service);
|
||||
|
||||
_logger.LogInfo("Service updated successfully. Id: {Id}, TenantId: {TenantId}", service.Id, tenantId);
|
||||
return ApiResponse<object>.SuccessResponse(response, "Service updated successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while updating service Id: {Id}.", id);
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred while updating the service", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> DeleteServiceAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("DeleteService called with ServiceId: {ServiceId}, IsActive: {IsActive}", id, active);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Get validate permission
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to delete services", 403);
|
||||
}
|
||||
|
||||
// Step 2: Check if the service exists
|
||||
var service = await _context.ServiceMasters
|
||||
.FirstOrDefaultAsync(s => s.Id == id && s.TenantId == tenantId);
|
||||
|
||||
if (service == null)
|
||||
{
|
||||
_logger.LogWarning("Service not found. ServiceId: {ServiceId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Service not found", "Service not found or already deleted", 404);
|
||||
}
|
||||
|
||||
// Protect system-defined service
|
||||
if (service.IsSystem)
|
||||
{
|
||||
_logger.LogWarning("Attempt to delete system-defined service. ServiceId: {ServiceId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Cannot delete system-defined service", "This service is system-defined and cannot be deleted", 400);
|
||||
}
|
||||
|
||||
// Step 3: Soft delete or restore
|
||||
service.IsActive = active;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var status = active ? "restored" : "deactivated";
|
||||
_logger.LogInfo("Service {ServiceId} has been {Status} successfully by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(new { }, $"Service {status} successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unexpected error occurred while deleting service {ServiceId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Error deleting service", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Activity Group APIs ===================================================================
|
||||
|
||||
public async Task<ApiResponse<object>> GetActivityGroupsAsync(Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("GetActivityGroups called");
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Fetch all activity groups for the tenant
|
||||
var activityGroups = await _context.ActivityGroupMasters
|
||||
.Include(ag => ag.Service)
|
||||
.Where(ag => ag.TenantId == tenantId && ag.IsActive)
|
||||
.Select(ag => _mapper.Map<ActivityGroupMasterVM>(ag))
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogInfo("{Count} activity group(s) fetched for tenantId: {TenantId}", activityGroups.Count, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(activityGroups, $"{activityGroups.Count} record(s) of activity groups fetched successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching activity groups");
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred while fetching activity groups", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> CreateActivityGroupAsync(ActivityGroupDto activityGroupDto, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("CreateActivityGroup called with Name: {Name}", activityGroupDto.Name);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Check Manage Master permission
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to take this action", 403);
|
||||
}
|
||||
|
||||
// Step 2: Check for duplicate name within ActivityGroupMasters
|
||||
bool isExist = await _context.ActivityGroupMasters
|
||||
.AnyAsync(ag => ag.TenantId == tenantId && ag.Name.ToLower() == activityGroupDto.Name.ToLower());
|
||||
|
||||
if (isExist)
|
||||
{
|
||||
_logger.LogWarning("Duplicate activity group name '{Name}' attempted by employeeId: {EmployeeId}", activityGroupDto.Name, loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse(
|
||||
$"Activity group with name '{activityGroupDto.Name}' already exists",
|
||||
$"Activity group with name '{activityGroupDto.Name}' already exists", 400);
|
||||
}
|
||||
|
||||
// Step 3: Map and persist
|
||||
var activityGroup = _mapper.Map<ActivityGroupMaster>(activityGroupDto);
|
||||
activityGroup.TenantId = tenantId;
|
||||
activityGroup.IsActive = true;
|
||||
activityGroup.IsSystem = false;
|
||||
|
||||
_context.ActivityGroupMasters.Add(activityGroup);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var service = await _context.ServiceMasters.FirstOrDefaultAsync(s => s.Id == activityGroup.ServiceId);
|
||||
|
||||
var response = _mapper.Map<ActivityGroupMasterVM>(activityGroup);
|
||||
|
||||
_logger.LogInfo("New activity group '{Name}' created successfully by employeeId: {EmployeeId}", activityGroup.Name, loggedInEmployee.Id);
|
||||
return ApiResponse<object>.SuccessResponse(response, "New activity group created successfully", 201);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error creating activity group");
|
||||
return ApiResponse<object>.ErrorResponse("Failed to create activity group", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> UpdateActivityGroupAsync(Guid id, ActivityGroupDto activityGroupDto, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("UpdateActivityGroup called for Id: {Id}", id);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Permission check
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to take this action", 403);
|
||||
}
|
||||
|
||||
// Step 2: Input validation
|
||||
if (activityGroupDto.Id != id)
|
||||
{
|
||||
_logger.LogWarning("Invalid input for activity group update. Id: {Id}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Invalid input", "Please provide valid data to update activity group", 400);
|
||||
}
|
||||
|
||||
var service = await _context.ServiceMasters.FirstOrDefaultAsync(s => s.Id == activityGroupDto.ServiceId && s.IsActive);
|
||||
|
||||
if (service == null)
|
||||
{
|
||||
_logger.LogWarning("User tries to update activity group, but service not found");
|
||||
return ApiResponse<object>.ErrorResponse("Invalid service ID", "Please provide valid service ID to update activity group", 400);
|
||||
}
|
||||
|
||||
// Step 3: Retrieve existing activity group
|
||||
var activityGroup = await _context.ActivityGroupMasters
|
||||
.Include(ag => ag.Service)
|
||||
.FirstOrDefaultAsync(ag => ag.Id == id && ag.TenantId == tenantId && ag.IsActive);
|
||||
|
||||
if (activityGroup == null)
|
||||
{
|
||||
_logger.LogWarning("Activity group not found. Id: {Id}, TenantId: {TenantId}", id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Activity group not found", "No such activity group exists", 404);
|
||||
}
|
||||
|
||||
// Step 4: Update and save
|
||||
activityGroup.Name = activityGroupDto.Name.Trim();
|
||||
activityGroup.Description = activityGroupDto.Description.Trim();
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var response = _mapper.Map<ActivityGroupMasterVM>(activityGroup);
|
||||
|
||||
_logger.LogInfo("Activity group updated successfully. Id: {Id}, TenantId: {TenantId}", activityGroup.Id, tenantId);
|
||||
return ApiResponse<object>.SuccessResponse(response, "Activity group updated successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while updating activity group Id: {Id}", id);
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred while updating the activity group", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> DeleteActivityGroupAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("DeleteActivityGroup called with ActivityGroupId: {ActivityGroupId}, IsActive: {IsActive}", id, isActive);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Permission check
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to delete activity groups", 403);
|
||||
}
|
||||
|
||||
// Step 2: Fetch the activity group
|
||||
var activityGroup = await _context.ActivityGroupMasters
|
||||
.FirstOrDefaultAsync(ag => ag.Id == id && ag.TenantId == tenantId);
|
||||
|
||||
if (activityGroup == null)
|
||||
{
|
||||
_logger.LogWarning("ActivityGroup not found. Id: {ActivityGroupId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Activity group not found", "Activity group not found or already deleted", 404);
|
||||
}
|
||||
|
||||
//Protect system-defined activity group
|
||||
if (activityGroup.IsSystem)
|
||||
{
|
||||
_logger.LogWarning("Attempt to delete system-defined activity group. Id: {ActivityGroupId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Cannot delete system-defined activity group", "This activity group is system-defined and cannot be deleted", 400);
|
||||
}
|
||||
|
||||
// Step 3: Perform soft delete or restore
|
||||
activityGroup.IsActive = isActive;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var status = isActive ? "restored" : "deactivated";
|
||||
_logger.LogInfo("ActivityGroup {ActivityGroupId} has been {Status} by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(new { }, $"Activity group {status} successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unexpected error occurred while deleting ActivityGroup {ActivityGroupId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Error deleting activity group", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Activity APIs ===================================================================
|
||||
public async Task<ApiResponse<object>> GetActivitiesMasterAsync(Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("GetActivitiesMaster called");
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Fetch all active activities for the tenant
|
||||
var activities = await _context.ActivityMasters
|
||||
.Include(c => c.ActivityGroup)
|
||||
.ThenInclude(ag => ag!.Service)
|
||||
.Where(c => c.TenantId == tenantId && c.IsActive)
|
||||
.ToListAsync();
|
||||
|
||||
if (activities.Count == 0)
|
||||
{
|
||||
_logger.LogWarning("No active activities found for tenantId: {TenantId}", tenantId);
|
||||
return ApiResponse<object>.SuccessResponse(new List<ActivityVM>(), "No activity records found", 200);
|
||||
}
|
||||
|
||||
// Step 2: Fetch all checklists for those activities in a single query to avoid N+1
|
||||
var activityIds = activities.Select(a => a.Id).ToList();
|
||||
var checkLists = await _context.ActivityCheckLists
|
||||
.Where(c => c.TenantId == tenantId && activityIds.Contains(c.ActivityId))
|
||||
.ToListAsync();
|
||||
|
||||
// Step 3: Group checklists by activity
|
||||
var groupedChecklists = checkLists
|
||||
.GroupBy(c => c.ActivityId)
|
||||
.ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
// Step 4: Map to ViewModel
|
||||
var activityVMs = activities.Select(activity =>
|
||||
{
|
||||
var checklistForActivity = groupedChecklists.ContainsKey(activity.Id)
|
||||
? groupedChecklists[activity.Id]
|
||||
: new List<ActivityCheckList>();
|
||||
|
||||
var response = _mapper.Map<ActivityVM>(activity);
|
||||
response.CheckLists = _mapper.Map<List<CheckListVM>>(checklistForActivity);
|
||||
return response;
|
||||
|
||||
}).ToList();
|
||||
|
||||
_logger.LogInfo("{Count} activity records fetched successfully for tenantId: {TenantId}", activityVMs.Count, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(activityVMs, $"{activityVMs.Count} activity records fetched successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occurred in GetActivitiesMaster");
|
||||
return ApiResponse<object>.ErrorResponse("Failed to fetch activity records", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> CreateActivityAsync(CreateActivityMasterDto createActivity, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("CreateActivity called with ActivityName: {Name}", createActivity?.ActivityName ?? "null");
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Validate input
|
||||
if (createActivity == null)
|
||||
{
|
||||
_logger.LogWarning("Null request body received in CreateActivity");
|
||||
return ApiResponse<object>.ErrorResponse("Invalid input", "Activity data is required", 400);
|
||||
}
|
||||
|
||||
var activityGroup = await _context.ActivityGroupMasters
|
||||
.Include(ag => ag.Service)
|
||||
.FirstOrDefaultAsync(ag => ag.Id == createActivity.ActitvityGroupId && ag.TenantId == tenantId);
|
||||
if (activityGroup == null)
|
||||
{
|
||||
_logger.LogWarning("User tried to create new activity, but not found activity group");
|
||||
return ApiResponse<object>.ErrorResponse("Invalid input", "Activity data is required", 400);
|
||||
}
|
||||
|
||||
// Step 2: Check permissions
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to perform this action", 403);
|
||||
}
|
||||
|
||||
// Step 3: Convert DTO to entity and add activity
|
||||
var activityMaster = _mapper.Map<ActivityMaster>(createActivity);
|
||||
activityMaster.TenantId = tenantId;
|
||||
|
||||
_context.ActivityMasters.Add(activityMaster);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
List<CheckListVM> checkListVMs = new();
|
||||
|
||||
// Step 4: Handle checklist items if present
|
||||
if (createActivity.CheckList?.Any() == true)
|
||||
{
|
||||
var activityCheckLists = createActivity.CheckList
|
||||
.Select(c =>
|
||||
{
|
||||
var response = _mapper.Map<ActivityCheckList>(c);
|
||||
response.ActivityId = activityMaster.Id;
|
||||
response.IsChecked = false;
|
||||
response.TenantId = tenantId;
|
||||
return response;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
_context.ActivityCheckLists.AddRange(activityCheckLists);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
checkListVMs = activityCheckLists
|
||||
.Select(c =>
|
||||
{
|
||||
var response = _mapper.Map<CheckListVM>(c);
|
||||
return response;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
// Step 5: Prepare final response
|
||||
var activityVM = _mapper.Map<ActivityVM>(activityMaster);
|
||||
activityVM.CheckLists = checkListVMs;
|
||||
|
||||
_logger.LogInfo("Activity '{Name}' created successfully for tenant {TenantId}", activityMaster.ActivityName, tenantId);
|
||||
return ApiResponse<object>.SuccessResponse(activityVM, "Activity created successfully", 201);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occurred while creating activity");
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred while creating activity", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> UpdateActivityAsync(Guid id, CreateActivityMasterDto createActivity, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("UpdateActivity called for ActivityId: {ActivityId}", id);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Validate input
|
||||
if (createActivity == null || string.IsNullOrWhiteSpace(createActivity.ActivityName) || string.IsNullOrWhiteSpace(createActivity.UnitOfMeasurement))
|
||||
{
|
||||
_logger.LogWarning("Invalid activity update input for ActivityId: {ActivityId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Invalid input", "ActivityName and UnitOfMeasurement are required", 400);
|
||||
}
|
||||
|
||||
// Step 2: Check permissions
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to update activities", 403);
|
||||
}
|
||||
|
||||
// Step 3: Validate service, activity group, and activity existence
|
||||
var activityGroup = await _context.ActivityGroupMasters.Include(ag => ag.Service).FirstOrDefaultAsync(ag => ag.Id == createActivity.ActitvityGroupId && ag.IsActive);
|
||||
|
||||
if (activityGroup == null)
|
||||
{
|
||||
_logger.LogWarning("User tries to update activity, but cannot able found activity group or service");
|
||||
return ApiResponse<object>.ErrorResponse("Invalid activity group ID or service ID", "Please provide valid activity group ID or service ID to update activity group", 400);
|
||||
}
|
||||
|
||||
var activity = await _context.ActivityMasters
|
||||
.Include(a => a.ActivityGroup)
|
||||
.ThenInclude(ag => ag!.Service)
|
||||
.FirstOrDefaultAsync(a => a.Id == id && a.IsActive && a.TenantId == tenantId);
|
||||
|
||||
if (activity == null)
|
||||
{
|
||||
_logger.LogWarning("Activity not found for ActivityId: {ActivityId}, TenantId: {TenantId}", id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found", 404);
|
||||
}
|
||||
|
||||
// Step 4: Update activity core data
|
||||
activity.ActivityName = createActivity.ActivityName.Trim();
|
||||
activity.UnitOfMeasurement = createActivity.UnitOfMeasurement.Trim();
|
||||
activity.ActivityGroupId = createActivity.ActitvityGroupId;
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Step 5: Handle checklist updates
|
||||
var existingChecklists = await _context.ActivityCheckLists
|
||||
.AsNoTracking()
|
||||
.Where(c => c.ActivityId == activity.Id)
|
||||
.ToListAsync();
|
||||
|
||||
var updatedChecklistVMs = new List<CheckListVM>();
|
||||
|
||||
if (createActivity.CheckList != null && createActivity.CheckList.Any())
|
||||
{
|
||||
var incomingCheckIds = createActivity.CheckList.Where(c => c.Id != null).Select(c => c.Id!.Value).ToHashSet();
|
||||
|
||||
// Prepare lists
|
||||
var newChecks = createActivity.CheckList.Where(c => c.Id == null);
|
||||
var updates = createActivity.CheckList.Where(c => c.Id != null && existingChecklists.Any(ec => ec.Id == c.Id));
|
||||
var deletes = existingChecklists.Where(ec => !incomingCheckIds.Contains(ec.Id)).ToList();
|
||||
|
||||
var toAdd = newChecks
|
||||
.Select(c =>
|
||||
{
|
||||
var response = _mapper.Map<ActivityCheckList>(c);
|
||||
response.ActivityId = activity.Id;
|
||||
response.IsChecked = false;
|
||||
response.TenantId = tenantId;
|
||||
return response;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var toUpdate = updates
|
||||
.Select(c =>
|
||||
{
|
||||
var response = _mapper.Map<ActivityCheckList>(c);
|
||||
response.ActivityId = activity.Id;
|
||||
response.TenantId = tenantId;
|
||||
return response;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
_context.ActivityCheckLists.AddRange(toAdd);
|
||||
_context.ActivityCheckLists.UpdateRange(toUpdate);
|
||||
_context.ActivityCheckLists.RemoveRange(deletes);
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Prepare view model
|
||||
updatedChecklistVMs = toAdd.Concat(toUpdate)
|
||||
.Select(c => _mapper.Map<CheckListVM>(c))
|
||||
.ToList();
|
||||
}
|
||||
else if (existingChecklists.Any())
|
||||
{
|
||||
// If no checklist provided, remove all existing
|
||||
_context.ActivityCheckLists.RemoveRange(existingChecklists);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// Step 6: Prepare response
|
||||
var activityVM = _mapper.Map<ActivityVM>(activity);
|
||||
activityVM.CheckLists = updatedChecklistVMs;
|
||||
|
||||
_logger.LogInfo("Activity updated successfully. ActivityId: {ActivityId}, TenantId: {TenantId}", activity.Id, tenantId);
|
||||
return ApiResponse<object>.SuccessResponse(activityVM, "Activity updated successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Exception in UpdateActivity");
|
||||
return ApiResponse<object>.ErrorResponse("Error updating activity", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> DeleteActivityAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("DeleteActivity called with ActivityId: {ActivityId}, IsActive: {IsActive}", id, isActive);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Validate permission
|
||||
var hasPermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "You don't have permission to delete activities", 403);
|
||||
}
|
||||
|
||||
// Step 2: Fetch the activity
|
||||
var activity = await _context.ActivityMasters
|
||||
.FirstOrDefaultAsync(a => a.Id == id && a.TenantId == tenantId);
|
||||
|
||||
if (activity == null)
|
||||
{
|
||||
_logger.LogWarning("Activity not found. ActivityId: {ActivityId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Activity not found", "Activity not found or already deleted", 404);
|
||||
}
|
||||
|
||||
// Step 3: Perform soft delete/restore
|
||||
activity.IsActive = isActive;
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
string status = isActive ? "restored" : "deactivated";
|
||||
_logger.LogInfo("Activity {ActivityId} {Status} successfully by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(new { }, $"Activity {status} successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unexpected error while deleting activity {ActivityId}", id);
|
||||
return ApiResponse<object>.ErrorResponse("Error deleting activity", ex.Message, 500);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Contact Category APIs ===================================================================
|
||||
|
||||
public async Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId)
|
||||
|
@ -7,6 +7,20 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
{
|
||||
public interface IMasterService
|
||||
{
|
||||
#region =================================================================== Service Master APIs ===================================================================
|
||||
Task<ApiResponse<object>> GetServicesAsync(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>> DeleteServiceAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId);
|
||||
|
||||
#endregion
|
||||
#region =================================================================== Activity Group Master APIs ===================================================================
|
||||
Task<ApiResponse<object>> GetActivityGroupsAsync(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>> DeleteActivityGroupAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||
|
||||
#endregion
|
||||
#region =================================================================== Contact Category APIs ===================================================================
|
||||
Task<ApiResponse<object>> CreateContactCategory(CreateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> UpdateContactCategory(Guid id, UpdateContactCategoryDto contactCategoryDto, Employee loggedInEmployee, Guid tenantId);
|
||||
@ -14,6 +28,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
Task<ApiResponse<object>> GetContactCategoryById(Guid id, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> DeleteContactCategory(Guid id, Employee loggedInEmployee, Guid tenantId);
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Contact Tag APIs ===================================================================
|
||||
Task<ApiResponse<Object>> GetContactTags(Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> CreateContactTag(CreateContactTagDto contactTagDto, Employee loggedInEmployee, Guid tenantId);
|
||||
@ -21,6 +36,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
Task<ApiResponse<object>> DeleteContactTag(Guid id, Employee loggedInEmployee, Guid tenantId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Work Status APIs ===================================================================
|
||||
Task<ApiResponse<object>> GetWorkStatusList(Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto, Employee loggedInEmployee, Guid tenantId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user