diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index 72bf158..7f70d7f 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -215,6 +215,196 @@ namespace Marco.Pms.Services.Helpers } } + // -------------------------------- Activity Group -------------------------------- + + public async Task> GetActivityGroups() + { + _logger.LogInfo("GetActivityGroups called"); + + try + { + // Step 1: Get logged-in employee + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Fetch all activity groups for the tenant + var activityGroups = await _context.ActivityGroupMasters + .Include(ag => ag.ServicesMaster) + .Where(ag => ag.TenantId == tenantId && ag.IsActive) + .Select(ag => ag.ToActivityGroupMasterVMFromActivityGroupMaster(ag.ServicesMaster != null ? ag.ServicesMaster.Name : "")) + .ToListAsync(); + + _logger.LogInfo("{Count} activity group(s) fetched for tenantId: {TenantId}", activityGroups.Count, tenantId); + + return ApiResponse.SuccessResponse(activityGroups, $"{activityGroups.Count} record(s) of activity groups fetched successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error fetching activity groups: {Message}", ex.Message); + return ApiResponse.ErrorResponse("An error occurred while fetching activity groups", ex.Message, 500); + } + } + public async Task> CreateActivityGroup(ActivityGroupDto activityGroupDto) + { + _logger.LogInfo("CreateActivityGroup called with Name: {Name}", activityGroupDto?.Name ?? "null"); + + try + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 1: Check Manage Master permission + var hasPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasPermission) + { + _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access denied", "You don't have permission to take this action", 403); + } + + // Step 2: Validate input + if (string.IsNullOrWhiteSpace(activityGroupDto?.Name) || string.IsNullOrWhiteSpace(activityGroupDto.Description)) + { + _logger.LogWarning("Invalid input data for activity group by employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Invalid input", "Name and Description are required", 400); + } + + // Step 3: 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.ErrorResponse( + $"Activity group with name '{activityGroupDto.Name}' already exists", + $"Activity group with name '{activityGroupDto.Name}' already exists", 400); + } + + // Step 4: Map and persist + var activityGroup = activityGroupDto.ToActivityGroupMasterFromActivityGroupDto(tenantId); + _context.ActivityGroupMasters.Add(activityGroup); + await _context.SaveChangesAsync(); + + var service = await _context.ServicesMasters.FirstOrDefaultAsync(s => s.Id == activityGroup.ServiceId); + + var response = activityGroup.ToActivityGroupMasterVMFromActivityGroupMaster(service?.Name ?? ""); + + _logger.LogInfo("New activity group '{Name}' created successfully by employeeId: {EmployeeId}", activityGroup.Name, loggedInEmployee.Id); + return ApiResponse.SuccessResponse(response, "New activity group created successfully", 201); + } + catch (Exception ex) + { + _logger.LogError("Error creating activity group: {Error}", ex.Message); + return ApiResponse.ErrorResponse("Failed to create activity group", ex.Message, 500); + } + } + public async Task> UpdateActivityGroup(Guid id, ActivityGroupDto activityGroupDto) + { + _logger.LogInfo("UpdateActivityGroup called for Id: {Id}", id); + + try + { + // Step 1: Permission check + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var hasPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasPermission) + { + _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} lacks Manage_Master permission.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access denied", "You don't have permission to take this action", 403); + } + + // Step 2: Input validation + if (activityGroupDto == null || activityGroupDto.Id != id || + string.IsNullOrWhiteSpace(activityGroupDto.Name) || + string.IsNullOrWhiteSpace(activityGroupDto.Description)) + { + _logger.LogWarning("Invalid input for activity group update. Id: {Id}", id); + return ApiResponse.ErrorResponse("Invalid input", "Please provide valid data to update activity group", 400); + } + + var service = await _context.ServicesMasters.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.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.ServicesMaster) + .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.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 = activityGroup.ToActivityGroupMasterVMFromActivityGroupMaster(service.Name ?? ""); + + _logger.LogInfo("Activity group updated successfully. Id: {Id}, TenantId: {TenantId}", activityGroup.Id, tenantId); + return ApiResponse.SuccessResponse(response, "Activity group updated successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error while updating activity group Id: {Id}. Exception: {Message}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred while updating the activity group", ex.Message, 500); + } + } + public async Task> DeleteActivityGroup(Guid id, bool isActive) + { + _logger.LogInfo("DeleteActivityGroup called with ActivityGroupId: {ActivityGroupId}, IsActive: {IsActive}", id, isActive); + + try + { + // Step 1: Permission check + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var hasPermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + + if (!hasPermission) + { + _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have Manage_Master permission.", loggedInEmployee.Id); + return ApiResponse.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.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.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.SuccessResponse(new { }, $"Activity group {status} successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Unexpected error occurred while deleting ActivityGroup {ActivityGroupId} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("Error deleting activity group", ex.Message, 500); + } + } + // -------------------------------- Contact Category -------------------------------- public async Task> CreateContactCategory(CreateContactCategoryDto contactCategoryDto) {