diff --git a/Marco.Pms.Services/Controllers/ServiceProjectController.cs b/Marco.Pms.Services/Controllers/ServiceProjectController.cs index d3f337b..bdb364b 100644 --- a/Marco.Pms.Services/Controllers/ServiceProjectController.cs +++ b/Marco.Pms.Services/Controllers/ServiceProjectController.cs @@ -96,6 +96,66 @@ namespace Marco.Pms.Services.Controllers } #endregion + #region =================================================================== Project Branch Functions =================================================================== + + [HttpGet("branch/list/{projectId}")] + public async Task GetProjectBranchListByProject(Guid projectId, [FromQuery] string? searchString, [FromQuery] bool isActive = true, + [FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20) + { + Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _serviceProject.GetProjectBranchListByProjectAsync(projectId, isActive, searchString, pageNumber, pageSize, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } + + [HttpGet("branch/details/{id}")] + public async Task GetProjectBranchDetails(Guid id) + { + Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _serviceProject.GetProjectBranchDetailsAsync(id, loggedInEmployee, tenantId); + + return StatusCode(response.StatusCode, response); + } + + [HttpPost("branch/create")] + public async Task CreateProjectBranch([FromBody] ProjectBranchDto model) + { + Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _serviceProject.CreateProjectBranchAsync(model, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Project_Branch", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + + [HttpPut("branch/edit/{id}")] + public async Task UpdateProjectBranch(Guid id, ProjectBranchDto model) + { + Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _serviceProject.UpdateProjectBranchAsync(id, model, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Project_Branch", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + + [HttpDelete("branch/delete/{id}")] + public async Task DeleteProjectBranch(Guid id, [FromQuery] bool isActive = false) + { + Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _serviceProject.DeleteProjectBranchAsync(id, isActive, loggedInEmployee, tenantId); + if (response.Success) + { + var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Project_Branch", Response = response.Data }; + await _signalR.SendNotificationAsync(notification); + } + return StatusCode(response.StatusCode, response); + } + #endregion + #region =================================================================== Service Project Allocation Functions =================================================================== [HttpGet("get/allocation/list")] diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IServiceProject.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IServiceProject.cs index 3dc53d7..b4bc747 100644 --- a/Marco.Pms.Services/Service/ServiceInterfaces/IServiceProject.cs +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IServiceProject.cs @@ -15,6 +15,14 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces Task> DeActivateServiceProjectAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId); #endregion + #region =================================================================== Project Branch Functions =================================================================== + Task> GetProjectBranchListByProjectAsync(Guid projectId, bool isActive, string? searchString, int pageNumber, int pageSize, Employee loggedInEmployee, Guid tenantId); + Task> GetProjectBranchDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId); + Task> CreateProjectBranchAsync(ProjectBranchDto model, Employee loggedInEmployee, Guid tenantId); + Task> UpdateProjectBranchAsync(Guid id, ProjectBranchDto model, Employee loggedInEmployee, Guid tenantId); + Task> DeleteProjectBranchAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId); + #endregion + #region =================================================================== Service Project Allocation Functions =================================================================== Task> GetServiceProjectAllocationListAsync(Guid? projectId, Guid? employeeId, bool isActive, Employee loggedInEmployee, Guid tenantId); Task> ManageServiceProjectAllocationAsync(List model, Employee loggedInEmployee, Guid tenantId); diff --git a/Marco.Pms.Services/Service/ServiceProjectService.cs b/Marco.Pms.Services/Service/ServiceProjectService.cs index 2c2828f..70b6895 100644 --- a/Marco.Pms.Services/Service/ServiceProjectService.cs +++ b/Marco.Pms.Services/Service/ServiceProjectService.cs @@ -30,6 +30,7 @@ namespace Marco.Pms.Services.Service private readonly ILoggingService _logger; private readonly S3UploadService _s3Service; private readonly IMapper _mapper; + private readonly UtilityMongoDBHelper _updateLogHelper; private readonly Guid NewStatus = Guid.Parse("32d76a02-8f44-4aa0-9b66-c3716c45a918"); private readonly Guid AssignedStatus = Guid.Parse("cfa1886d-055f-4ded-84c6-42a2a8a14a66"); @@ -44,7 +45,8 @@ namespace Marco.Pms.Services.Service ApplicationDbContext context, ILoggingService logger, S3UploadService s3Service, - IMapper mapper) + IMapper mapper, + UtilityMongoDBHelper updateLogHelper) { _serviceScopeFactory = serviceScopeFactory; _context = context; @@ -52,11 +54,11 @@ namespace Marco.Pms.Services.Service _s3Service = s3Service; _mapper = mapper; _dbContextFactory = dbContextFactory; + _updateLogHelper = updateLogHelper; } #region =================================================================== Service Project Functions =================================================================== - /// /// Retrieves a paginated list of active service projects for a tenant, including related services, job counts, and team member information. /// @@ -195,7 +197,6 @@ namespace Marco.Pms.Services.Service } } - /// /// Retrieves detailed information for a specific service project, including related client, status, services, and audit information. /// @@ -439,9 +440,7 @@ namespace Marco.Pms.Services.Service } // Create BSON snapshot of existing entity for audit logging (MongoDB) - using var scope = _serviceScopeFactory.CreateScope(); - var updateLogHelper = scope.ServiceProvider.GetRequiredService(); - BsonDocument existingEntityBson = updateLogHelper.EntityToBsonDocument(serviceProject); + BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(serviceProject); // Map incoming DTO to the tracked entity _mapper.Map(model, serviceProject); @@ -509,7 +508,7 @@ namespace Marco.Pms.Services.Service }); // Push update log asynchronously to MongoDB for audit - var updateLogTask = updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + var updateLogTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject { EntityId = id.ToString(), UpdatedById = loggedInEmployee.Id.ToString(), @@ -566,9 +565,7 @@ namespace Marco.Pms.Services.Service } // Create BSON snapshot of existing entity for audit logging (MongoDB) - using var scope = _serviceScopeFactory.CreateScope(); - var updateLogHelper = scope.ServiceProvider.GetRequiredService(); - BsonDocument existingEntityBson = updateLogHelper.EntityToBsonDocument(serviceProject); + BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(serviceProject); // Update active status as requested by the client serviceProject.IsActive = isActive; @@ -576,7 +573,7 @@ namespace Marco.Pms.Services.Service await _context.SaveChangesAsync(); // Push update log asynchronously to MongoDB for audit - await updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + await _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject { EntityId = id.ToString(), UpdatedById = loggedInEmployee.Id.ToString(), @@ -599,6 +596,349 @@ namespace Marco.Pms.Services.Service #endregion + #region =================================================================== Project Branch Functions =================================================================== + + /// + /// Retrieves a paginated list of project branches filtered by activity status and optional search criteria. + /// Implements enterprise-grade optimizations, detailed logging, and standardized error handling. + /// + /// Unique identifier for the project. + /// Filter by active/inactive branches. + /// Optional search string for filtering by branch name, address, or type. + /// Current page number for pagination. + /// Number of records per page. + /// Current logged-in employee details. + /// Tenant identifier for multi-tenant architecture. + /// ApiResponse containing paginated branches or error details. + public async Task> GetProjectBranchListByProjectAsync(Guid projectId, bool isActive, string? searchString, int pageNumber, int pageSize, + Employee loggedInEmployee, Guid tenantId) + { + // Log method invocation with parameters for audit and debugging + _logger.LogInfo("Fetching project branches for ProjectId: {ProjectId}, IsActive: {IsActive}, Page: {PageNumber}, Size: {PageSize}", projectId, isActive, pageNumber, pageSize); + + try + { + // Check if the service project exists + var serviceProject = await _context.ServiceProjects + .AsNoTracking() + .FirstOrDefaultAsync(sp => sp.Id == projectId && sp.TenantId == tenantId); + if (serviceProject == null) + { + _logger.LogWarning("Service project not found for ProjectId: {ProjectId}", projectId); + return ApiResponse.ErrorResponse("Service project not found", "Service project not found", 404); + } + + // Build base query with necessary includes and filters + var branchQuery = _context.ProjectBranches + .Include(pb => pb.Project).ThenInclude(sp => sp!.Status) + .Include(pb => pb.CreatedBy).ThenInclude(e => e!.JobRole) + .AsNoTracking() + .Where(pb => pb.ProjectId == projectId && pb.TenantId == tenantId && pb.IsActive == isActive); + + // Apply search filtering if search string is provided + if (!string.IsNullOrWhiteSpace(searchString)) + { + var normalized = searchString.Trim().ToLowerInvariant(); + branchQuery = branchQuery.Where(pb => + pb.BranchName.ToLower().Contains(normalized) || + pb.Address.ToLower().Contains(normalized) || + pb.BranchType.ToLower().Contains(normalized)); + } + + // Count total records for pagination metadata + var totalEntities = await branchQuery.CountAsync(); + var totalPages = (int)Math.Ceiling((double)totalEntities / pageSize); + + // Fetch paginated data sorted by name descending + var branches = await branchQuery + .OrderByDescending(pb => pb.BranchName) + .Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + // Map entities to view models + var projectBranchVMs = _mapper.Map>(branches); + + // Prepare response with pagination metadata + var response = new + { + CurrentPage = pageNumber, + TotalPages = totalPages, + TotalEntities = totalEntities, + Data = projectBranchVMs + }; + + // Log successful fetch + _logger.LogInfo("Fetched {Count} branches for Project: {ProjectName}", projectBranchVMs.Count, serviceProject.Name); + return ApiResponse.SuccessResponse(response, $"{projectBranchVMs.Count} branches of project {serviceProject.Name} fetched successfully"); + } + catch (Exception ex) + { + // Log exception details + _logger.LogError(ex, "Error occurred while fetching project branches for ProjectId: {ProjectId}", projectId); + // Return standardized problem details response + return ApiResponse.ErrorResponse("An unexpected error occurred.", ex.Message, 500); + } + } + + /// + /// Retrieves detailed information for a single project branch by ID, including related project and employee metadata. + /// Provides enterprise-grade optimization, structured error handling, and detailed logging. + /// + /// Unique identifier of the project branch. + /// Information about the currently logged-in employee (for auditing/security). + /// The current tenant's unique identifier (multi-tenancy support). + /// ApiResponse with the branch details or a standardized error. + public async Task> GetProjectBranchDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId) + { + _logger.LogInfo("Attempting to fetch details for ProjectBranchId: {ProjectBranchId}, TenantId: {TenantId} by EmployeeId: {EmployeeId}", + id, tenantId, loggedInEmployee.Id); + + try + { + // Query the branch with required related entities; .AsNoTracking improves read speed/performance for lookups. + var projectBranch = await _context.ProjectBranches + .AsNoTracking() + .Include(pb => pb.Project).ThenInclude(sp => sp!.Status) + .Include(pb => pb.CreatedBy).ThenInclude(e => e!.JobRole) + .Include(pb => pb.UpdatedBy).ThenInclude(e => e!.JobRole) + .FirstOrDefaultAsync(pb => pb.Id == id && pb.TenantId == tenantId); + + // Not found: log and return a descriptive error, using the correct HTTP status code. + if (projectBranch == null) + { + _logger.LogWarning("Project branch not found. ProjectBranchId: {ProjectBranchId}, TenantId: {TenantId}", id, tenantId); + return ApiResponse.ErrorResponse( + "Project branch not found", + "No project branch exists with the given ID for this tenant.", + 404 + ); + } + + // Map entity to detail view model to avoid exposing domain internals in API. + var branchDetails = _mapper.Map(projectBranch); + + _logger.LogInfo("Project branch details successfully fetched. ProjectBranchId: {ProjectBranchId}", id); + + // Return success with data using a descriptive message. + return ApiResponse.SuccessResponse(branchDetails, "Project branch details fetched successfully."); + } + catch (Exception ex) + { + // Log the complete exception with an error log, capturing all contextual info for troubleshooting. + _logger.LogError(ex, "Error while fetching project branch details. ProjectBranchId: {ProjectBranchId}, TenantId: {TenantId}, EmployeeId: {EmployeeId}", + id, tenantId, loggedInEmployee.Id); + + // Return a standardized error message; hide internal error details when handing unknown errors. + return ApiResponse.ErrorResponse( + "An unexpected error occurred while fetching project branch details.", + ex.Message, + 500 + ); + } + } + + /// + /// Creates a new project branch associated with a specific service project. + /// Applies enterprise-grade validation, logging, and exception handling. + /// + /// DTO containing project branch creation data. + /// Logged-in employee details for auditing. + /// Tenant identifier for multi-tenancy context. + /// ApiResponse containing created project branch details or error info. + public async Task> CreateProjectBranchAsync(ProjectBranchDto model, Employee loggedInEmployee, Guid tenantId) + { + _logger.LogInfo("Starting project branch creation. ProjectId: {ProjectId}, TenantId: {TenantId}, CreatedBy: {EmployeeId}", + model.ProjectId, tenantId, loggedInEmployee.Id); + + try + { + // Validate existence of related service project for given tenant + var serviceProject = await _context.ServiceProjects + .AsNoTracking() + .FirstOrDefaultAsync(sp => sp.Id == model.ProjectId && sp.TenantId == tenantId); + + if (serviceProject == null) + { + _logger.LogWarning("Service project not found for ProjectId: {ProjectId}, TenantId: {TenantId}", model.ProjectId, tenantId); + return ApiResponse.ErrorResponse("Service project not found", "No service project exists with the given ID for this tenant.", 404); + } + + // Map DTO to domain entity and initialize audit and status fields + var projectBranch = _mapper.Map(model); + projectBranch.Id = Guid.NewGuid(); + projectBranch.IsActive = true; + projectBranch.CreatedAt = DateTime.UtcNow; + projectBranch.CreatedById = loggedInEmployee.Id; + projectBranch.TenantId = tenantId; + + // Add and persist new project branch + await using var transaction = await _context.Database.BeginTransactionAsync(); + _context.ProjectBranches.Add(projectBranch); + await _context.SaveChangesAsync(); + await transaction.CommitAsync(); + + // Map to response view models assembling nested related data + var response = _mapper.Map(projectBranch); + response.Project = _mapper.Map(serviceProject); + response.CreatedBy = _mapper.Map(loggedInEmployee); + + _logger.LogInfo("Project branch created successfully. ProjectBranchId: {ProjectBranchId}", projectBranch.Id); + return ApiResponse.SuccessResponse(response, "Created project branch successfully", 201); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred while creating project branch. ProjectId: {ProjectId}, TenantId: {TenantId}, EmployeeId: {EmployeeId}", + model.ProjectId, tenantId, loggedInEmployee.Id); + + return ApiResponse.ErrorResponse("An unexpected error occurred while creating the project branch.", ex.Message, 500); + } + } + + /// + /// Updates an existing project branch with new data. Ensures data consistency, logs changes, and maintains comprehensive audit trail. + /// Implements enterprise best practices for validation, logging, transaction management, and error handling. + /// + /// ID of the project branch to update. + /// DTO containing updated project branch data. + /// Current employee performing the update (for audit and logging). + /// Tenant ID for multi-tenant data isolation. + /// ApiResponse indicating success or failure with detailed messages. + public async Task> UpdateProjectBranchAsync(Guid id, ProjectBranchDto model, Employee loggedInEmployee, Guid tenantId) + { + // Validate ID consistency between route parameter and payload DTO + if (model.Id.HasValue && model.Id != id) + { + _logger.LogWarning("ID mismatch: Route ID {RouteId} != Payload ID {PayloadId}", id, model.Id); + return ApiResponse.ErrorResponse("ID mismatch between route and payload", "The ID provided in the route does not match the payload.", 400); + } + + // Fetch current entity state for auditing + var projectBranch = await _context.ProjectBranches + .AsNoTracking() + .FirstOrDefaultAsync(pb => pb.Id == id && pb.TenantId == tenantId); + + if (projectBranch == null) + { + _logger.LogWarning("Project branch not found for update. Id: {Id}, TenantId: {TenantId}", id, tenantId); + return ApiResponse.ErrorResponse("Project branch not found", "No project branch exists with the provided ID for this tenant.", 404); + } + + // Convert existing entity to BSON for detailed audit logging + BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(projectBranch); + + // Map the incoming DTO onto the existing entity + _mapper.Map(model, projectBranch); + projectBranch.UpdatedAt = DateTime.UtcNow; + projectBranch.UpdatedById = loggedInEmployee.Id; + + try + { + // Execute update within a transaction to ensure atomicity + await using var transaction = await _context.Database.BeginTransactionAsync(); + + // Mark the entity as modified + _context.ProjectBranches.Update(projectBranch); + await _context.SaveChangesAsync(); + + // Commit transaction + await transaction.CommitAsync(); + + // Log the update in a dedicated audit log asynchronously + var updateLogTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, "ProjectBranchModificationLog"); + + // Fetch the latest entity details with related info for response + var branchTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.ProjectBranches + .Include(pb => pb.Project).ThenInclude(sp => sp!.Status) + .Include(pb => pb.CreatedBy).ThenInclude(e => e!.JobRole) + .AsNoTracking() + .FirstOrDefaultAsync(pb => pb.Id == id && pb.TenantId == tenantId); + }); + + await Task.WhenAll(updateLogTask, branchTask); + + // Map updated entity to view model for API response + var response = _mapper.Map(branchTask.Result); + + _logger.LogInfo("Successfully updated project branch. Id: {Id}", id); + return ApiResponse.SuccessResponse(response, "Project branch updated successfully.", 200); + } + catch (Exception ex) + { + // Log detailed error for troubleshooting + _logger.LogError(ex, "Error during project branch update. Id: {Id}, TenantId: {TenantId}", id, tenantId); + return ApiResponse.ErrorResponse("Failed to update project branch due to an internal error.", ex.Message, 500); + } + } + + /// + /// Soft deletes or restores a project branch by toggling its IsActive flag. + /// Implements audit logging, transaction safety, and detailed error handling to ensure enterprise readiness. + /// + /// The unique identifier of the project branch to be deleted or restored. + /// Boolean indicating active state; false to soft delete, true to restore. + /// The authenticated employee performing the operation, for auditing purposes. + /// Tenant ID to enforce multi-tenant data isolation. + /// ApiResponse indicating the result of the operation, with status and descriptive message. + public async Task> DeleteProjectBranchAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId) + { + _logger.LogInfo("Starting soft delete operation for ProjectBranchId: {ProjectBranchId}, TenantId: {TenantId}, By EmployeeId: {EmployeeId}", + id, tenantId, loggedInEmployee.Id); + + try + { + // Fetch the existing project branch record for the tenant + var projectBranch = await _context.ProjectBranches + .FirstOrDefaultAsync(pb => pb.Id == id && pb.TenantId == tenantId); + + if (projectBranch == null) + { + _logger.LogWarning("Project branch not found for soft delete. ProjectBranchId: {ProjectBranchId}, TenantId: {TenantId}", id, tenantId); + return ApiResponse.ErrorResponse("Project branch not found", "No project branch exists with the given ID for this tenant.", 404); + } + + // Capture existing entity state for audit logging + BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(projectBranch); + + // Update the IsActive flag to soft delete or restore + projectBranch.IsActive = isActive; + + // Save changes within a transaction to ensure atomicity + await using var transaction = await _context.Database.BeginTransactionAsync(); + await _context.SaveChangesAsync(); + await transaction.CommitAsync(); + + // Log the change asynchronously for audit trail + await _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + { + EntityId = id.ToString(), + UpdatedById = loggedInEmployee.Id.ToString(), + OldObject = existingEntityBson, + UpdatedAt = DateTime.UtcNow + }, "ProjectBranchModificationLog"); + + _logger.LogInfo("Soft delete operation completed successfully for ProjectBranchId: {ProjectBranchId}", id); + + return ApiResponse.SuccessResponse(new { }, isActive ? "Branch restored successfully" : "Branch deleted successfully", 200); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred during soft delete operation for ProjectBranchId: {ProjectBranchId}, TenantId: {TenantId}", id, tenantId); + return ApiResponse.ErrorResponse("Failed to delete project branch due to an internal error.", ex.Message, 500); + } + } + + #endregion + #region =================================================================== Service Project Allocation Functions =================================================================== /// @@ -1699,9 +2039,7 @@ namespace Marco.Pms.Services.Service } // Create BSON snapshot of existing entity for audit logging (MongoDB) - using var scope = _serviceScopeFactory.CreateScope(); - var updateLogHelper = scope.ServiceProvider.GetRequiredService(); - BsonDocument existingEntityBson = updateLogHelper.EntityToBsonDocument(jobTicket); + BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(jobTicket); // Map updated properties from DTO, set audit metadata _mapper.Map(model, jobTicket); @@ -1825,7 +2163,7 @@ namespace Marco.Pms.Services.Service await transaction.CommitAsync(); // Push update log asynchronously to MongoDB for audit - var updateLogTask = updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + var updateLogTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject { EntityId = id.ToString(), UpdatedById = loggedInEmployee.Id.ToString(), @@ -2172,9 +2510,7 @@ namespace Marco.Pms.Services.Service } // Audit: BSON snapshot before update (MongoDB) - using var scope = _serviceScopeFactory.CreateScope(); - var updateLogHelper = scope.ServiceProvider.GetRequiredService(); - BsonDocument existingEntityBson = updateLogHelper.EntityToBsonDocument(jobComment); + BsonDocument existingEntityBson = _updateLogHelper.EntityToBsonDocument(jobComment); // Update comment core fields and audit _mapper.Map(model, jobComment); @@ -2274,7 +2610,7 @@ namespace Marco.Pms.Services.Service } // Push audit log to MongoDB - var updateLogTask = updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject + var updateLogTask = _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject { EntityId = id.ToString(), UpdatedById = loggedInEmployee.Id.ToString(), @@ -2733,8 +3069,6 @@ namespace Marco.Pms.Services.Service //private async Task DeleteTalkingPointAttachments(List documentIds) //{ - // using var scope = _serviceScopeFactory.CreateScope(); - // var _updateLogHelper = scope.ServiceProvider.GetRequiredService(); // var attachmentTask = Task.Run(async () => // { @@ -2778,8 +3112,6 @@ namespace Marco.Pms.Services.Service private async Task DeleteJobAttachemnts(List documentIds) { - using var scope = _serviceScopeFactory.CreateScope(); - var _updateLogHelper = scope.ServiceProvider.GetRequiredService(); var attachmentTask = Task.Run(async () => {