From e391c82659de7862a1c132a3d7a329871b290843 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 16:58:56 +0530 Subject: [PATCH 1/2] Added CRUD operation APIs for work Status master table --- .../Controllers/MasterController.cs | 29 +-- Marco.Pms.Services/Helpers/MasterHelper.cs | 198 ++++++++++++++++-- 2 files changed, 181 insertions(+), 46 deletions(-) diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index 4e6ad8f..ebd8998 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -693,44 +693,21 @@ namespace Marco.Pms.Services.Controllers return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } var response = await _masterHelper.CreateWorkStatus(createWorkStatusDto); - if (response.StatusCode == 200) - { - return Ok(response); - } - else if (response.StatusCode == 409) - { - return Conflict(response); - } - else - { - return BadRequest(response); - } + return StatusCode(response.StatusCode, response); } [HttpPost("work-status/edit/{id}")] public async Task UpdateWorkStatusMaster(Guid id, [FromBody] UpdateWorkStatusMasterDto updateWorkStatusDto) { var response = await _masterHelper.UpdateWorkStatus(id, updateWorkStatusDto); - if (response.StatusCode == 200) - { - return Ok(response); - } - else if (response.StatusCode == 404) - { - return NotFound(response); - } - else - { - return BadRequest(response); - - } + return StatusCode(response.StatusCode, response); } [HttpDelete("work-status/{id}")] public async Task DeleteWorkStatusMaster(Guid id) { var response = await _masterHelper.DeleteWorkStatus(id); - return Ok(response); + return StatusCode(response.StatusCode, response); } // -------------------------------- Contact Category -------------------------------- diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 508205b..115b4b6 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -3,6 +3,7 @@ using Marco.Pms.Model.Directory; using Marco.Pms.Model.Dtos.Master; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Mapper; +using Marco.Pms.Model.Master; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Services.Service; @@ -257,38 +258,195 @@ namespace Marco.Pms.Services.Helpers // -------------------------------- Work Status -------------------------------- public async Task> GetWorkStatusList() { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - bool hasViewPermission = await _permissionService.HasPermission(View_Master, LoggedInEmployee.Id); + _logger.LogInfo("GetWorkStatusList called."); - if (!hasViewPermission) + try { - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + // Step 1: Get tenant and logged-in employee info + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check permission to view master data + bool hasViewPermission = await _permissionService.HasPermission(View_Master, loggedInEmployee.Id); + if (!hasViewPermission) + { + _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + + // Step 3: Fetch work statuses for the tenant + var workStatusList = await _context.WorkStatusMasters + .Where(ws => ws.TenantId == tenantId) + .Select(ws => new + { + ws.Id, + ws.Name, + ws.Description, + ws.IsSystem + }) + .ToListAsync(); + + _logger.LogInfo("{Count} work statuses fetched for tenantId: {TenantId}", workStatusList.Count, tenantId); + + // Step 4: Return successful response + return ApiResponse.SuccessResponse( + workStatusList, + $"{workStatusList.Count} work status records fetched successfully", + 200 + ); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while fetching work status list : {Error}", ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to fetch work status list", 500); } - var workStatus = await _context.WorkStatusMasters.Where(ws => ws.TenantId == tenantId).Select(ws => new { ws.Id, ws.Name, ws.Description, ws.IsSystem }).ToListAsync(); - - return ApiResponse.SuccessResponse(workStatus, $"{workStatus.Count} number of work status fetched successfully", 200); - } public async Task> CreateWorkStatus(CreateWorkStatusMasterDto createWorkStatusDto) { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogInfo("CreateWorkStatus called with Name: {Name}", createWorkStatusDto.Name ?? ""); + + try + { + // Step 1: Get tenant and logged-in employee + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check if user has permission to manage master data + var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManageMasterPermission) + { + _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + + // Step 3: Check if work status with the same name already exists + var existingWorkStatus = await _context.WorkStatusMasters + .FirstOrDefaultAsync(ws => ws.Name == createWorkStatusDto.Name && ws.TenantId == tenantId); + + if (existingWorkStatus != null) + { + _logger.LogWarning("Work status already exists: {Name}", createWorkStatusDto.Name ?? ""); + return ApiResponse.ErrorResponse("Work status already exists", "Work status already exists", 400); + } + + // Step 4: Create new WorkStatusMaster entry + var workStatus = new WorkStatusMaster + { + Name = createWorkStatusDto.Name?.Trim() ?? "", + Description = createWorkStatusDto.Description?.Trim() ?? "", + IsSystem = false, + TenantId = tenantId + }; + + _context.WorkStatusMasters.Add(workStatus); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Work status created successfully: {Id}, Name: {Name}", workStatus.Id, workStatus.Name); + return ApiResponse.SuccessResponse(workStatus, "Work status created successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while creating work status : {Error}", ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to create work status", 500); + } } - public async Task> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto contacupdateWorkStatusDtotTagDto) + public async Task> UpdateWorkStatus(Guid id, UpdateWorkStatusMasterDto updateWorkStatusDto) { - var tenantId = _userHelper.GetTenantId(); - Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogInfo("UpdateWorkStatus called for WorkStatus ID: {Id}, New Name: {Name}", id, updateWorkStatusDto.Name ?? ""); + + try + { + // Step 1: Get tenant and employee info + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check permission to update master + var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManageMasterPermission) + { + _logger.LogWarning("Update denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + } + + // Step 3: Retrieve existing work status by id and tenant + var workStatus = await _context.WorkStatusMasters + .FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId); + + if (workStatus == null) + { + _logger.LogWarning("Work status not found for Id: {Id}", id); + return ApiResponse.ErrorResponse("Work status not found", "Work status not found", 404); + } + + // Step 4: Update fields + workStatus.Name = updateWorkStatusDto.Name?.Trim() ?? ""; + workStatus.Description = updateWorkStatusDto.Description?.Trim() ?? ""; + + await _context.SaveChangesAsync(); + + _logger.LogInfo("Work status updated successfully. Id: {Id}", workStatus.Id); + return ApiResponse.SuccessResponse(workStatus, "Work status updated successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while updating work status Id: {Id} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to update work status", 500); + } } public async Task> DeleteWorkStatus(Guid id) { - Guid tenantId = _userHelper.GetTenantId(); - var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogInfo("DeleteWorkStatus called for Id: {Id}", id); + try + { + // Step 1: Get current tenant and logged-in employee + Guid tenantId = _userHelper.GetTenantId(); + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Check permission to manage master data + var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManageMasterPermission) + { + _logger.LogWarning("Delete denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "Access denied for deleting work status", 403); + } + + // Step 3: Find the work status + var workStatus = await _context.WorkStatusMasters + .FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId); + + if (workStatus == null) + { + _logger.LogWarning("Work status not found for Id: {Id}", id); + return ApiResponse.ErrorResponse("Work status not found", "Work status not found", 404); + } + + // Step 4: Check for dependencies in TaskAllocations + bool hasDependency = await _context.TaskAllocations + .AnyAsync(ta => ta.TenantId == tenantId && ta.WorkStatusId == id); + + if (hasDependency) + { + _logger.LogWarning("Cannot delete WorkStatus Id: {Id} due to existing task dependency", id); + return ApiResponse.ErrorResponse( + "Work status has a dependency in assigned tasks and cannot be deleted", + "Deletion failed due to associated tasks", + 400 + ); + } + + // Step 5: Delete and persist + _context.WorkStatusMasters.Remove(workStatus); + await _context.SaveChangesAsync(); + + _logger.LogInfo("Work status deleted successfully. Id: {Id}", id); + return ApiResponse.SuccessResponse(new { }, "Work status deleted successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error occurred while deleting WorkStatus Id: {Id} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to delete work status", 500); + } } - } } From ff9c7c94345b9c905622e5b334af18bddd5a1a22 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 16 Jun 2025 17:19:59 +0530 Subject: [PATCH 2/2] Added code to validate the id received by path parameter with id received by payload --- Marco.Pms.Services/Helpers/MasterHelper.cs | 39 ++++++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 115b4b6..0698733 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -356,41 +356,58 @@ namespace Marco.Pms.Services.Helpers try { - // Step 1: Get tenant and employee info + // Step 1: Validate input + if (id == Guid.Empty || id != updateWorkStatusDto.Id) + { + _logger.LogWarning("Invalid ID provided for update. Route ID: {RouteId}, DTO ID: {DtoId}", id, updateWorkStatusDto.Id); + return ApiResponse.ErrorResponse("Invalid data provided", "The provided work status ID is invalid", 400); + } + + // Step 2: Get tenant and logged-in employee Guid tenantId = _userHelper.GetTenantId(); var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); - // Step 2: Check permission to update master + // Step 3: Check permissions var hasManageMasterPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); if (!hasManageMasterPermission) { - _logger.LogWarning("Update denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); - return ApiResponse.ErrorResponse("You don't have access", "Don't have access to take action", 403); + _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access denied", "You do not have permission to update this work status", 403); } - // Step 3: Retrieve existing work status by id and tenant + // Step 4: Retrieve the work status record var workStatus = await _context.WorkStatusMasters .FirstOrDefaultAsync(ws => ws.Id == id && ws.TenantId == tenantId); if (workStatus == null) { - _logger.LogWarning("Work status not found for Id: {Id}", id); - return ApiResponse.ErrorResponse("Work status not found", "Work status not found", 404); + _logger.LogWarning("Work status not found for ID: {Id}", id); + return ApiResponse.ErrorResponse("Work status not found", "No work status found with the provided ID", 404); } - // Step 4: Update fields + // Step 5: Check for duplicate name (optional) + var isDuplicate = await _context.WorkStatusMasters + .AnyAsync(ws => ws.Name == updateWorkStatusDto.Name && ws.Id != id && ws.TenantId == tenantId); + + if (isDuplicate) + { + _logger.LogWarning("Duplicate work status name '{Name}' detected during update. ID: {Id}", updateWorkStatusDto.Name ?? "", id); + return ApiResponse.ErrorResponse("Work status with the same name already exists", "Duplicate name", 400); + } + + // Step 6: Update fields workStatus.Name = updateWorkStatusDto.Name?.Trim() ?? ""; workStatus.Description = updateWorkStatusDto.Description?.Trim() ?? ""; await _context.SaveChangesAsync(); - _logger.LogInfo("Work status updated successfully. Id: {Id}", workStatus.Id); + _logger.LogInfo("Work status updated successfully. ID: {Id}", id); return ApiResponse.SuccessResponse(workStatus, "Work status updated successfully", 200); } catch (Exception ex) { - _logger.LogError("Error occurred while updating work status Id: {Id} : {Error}", id, ex.Message); - return ApiResponse.ErrorResponse("An error occurred", "Unable to update work status", 500); + _logger.LogError("Error occurred while updating work status ID: {Id} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred", "Unable to update the work status at this time", 500); } } public async Task> DeleteWorkStatus(Guid id)