From cc96756e416987dc3ad6ae78b94ff2f8f3020e80 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Thu, 26 Jun 2025 17:57:58 +0530 Subject: [PATCH] Implemented CRUD API for services --- Marco.Pms.Model/Mapper/ActivitiesMapper.cs | 14 +- Marco.Pms.Model/Mapper/MasterMapper.cs | 48 ++++++ Marco.Pms.Services/Helpers/MasterHelper.cs | 184 ++++++++++++++++++++- 3 files changed, 242 insertions(+), 4 deletions(-) diff --git a/Marco.Pms.Model/Mapper/ActivitiesMapper.cs b/Marco.Pms.Model/Mapper/ActivitiesMapper.cs index e2dc503..b65c09a 100644 --- a/Marco.Pms.Model/Mapper/ActivitiesMapper.cs +++ b/Marco.Pms.Model/Mapper/ActivitiesMapper.cs @@ -95,8 +95,11 @@ namespace Marco.Pms.Model.Mapper { return new ActivityMaster { - ActivityName = createActivity.ActivityName, - UnitOfMeasurement = createActivity.UnitOfMeasurement, + ServiceId = createActivity.ServiceId, + ActitvityGroupId = createActivity.ActitvityGroupId, + ActivityName = createActivity.ActivityName ?? string.Empty, + UnitOfMeasurement = createActivity.UnitOfMeasurement ?? string.Empty, + IsActive = true, TenantId = tenantId }; } @@ -135,13 +138,18 @@ namespace Marco.Pms.Model.Mapper }; } - public static ActivityVM ToActivityVMFromActivityMaster(this ActivityMaster activity, List checkList) + public static ActivityVM ToActivityVMFromActivityMaster(this ActivityMaster activity, List checkList, string? serviceName, string? activityGroupName) { return new ActivityVM { Id = activity.Id, + ServiceId = activity.ServiceId, + ServicesName = serviceName, + ActitvityGroupId = activity.ActitvityGroupId, + ActivityGroupName = activityGroupName, ActivityName = activity.ActivityName, UnitOfMeasurement = activity.UnitOfMeasurement, + IsActive = activity.IsActive, CheckLists = checkList, }; } diff --git a/Marco.Pms.Model/Mapper/MasterMapper.cs b/Marco.Pms.Model/Mapper/MasterMapper.cs index 548c162..e6ae857 100644 --- a/Marco.Pms.Model/Mapper/MasterMapper.cs +++ b/Marco.Pms.Model/Mapper/MasterMapper.cs @@ -27,5 +27,53 @@ namespace Marco.Pms.Model.Mapper IsSystem = categoryMaster.IsSystem }; } + + // -------------------------------- Services -------------------------------- + public static ServicesMaster ToServicesMasterFromServiceMasterDto(this ServiceMasterDto model, Guid tenantId) + { + return new ServicesMaster + { + Name = model.Name ?? string.Empty, + Description = model.Description ?? string.Empty, + TenantId = tenantId + }; + } + public static ServiceMasterVM ToServiceMasterVMFromServiceMaster(this ServicesMaster model) + { + return new ServiceMasterVM + { + Id = model.Id, + Name = model.Name, + Description = model.Description, + IsActive = model.IsActive, + IsSystem = model.IsSystem + }; + } + + // -------------------------------- Activity Group -------------------------------- + + public static ActivityGroupMaster ToActivityGroupMasterFromActivityGroupDto(this ActivityGroupDto model, Guid tenantId) + { + return new ActivityGroupMaster + { + ServiceId = model.ServiceId, + Name = model.Name ?? string.Empty, + Description = model.Description ?? string.Empty, + TenantId = tenantId + }; + } + public static ActivityGroupMasterVM ToActivityGroupMasterVMFromActivityGroupMaster(this ActivityGroupMaster model, string serviceName) + { + return new ActivityGroupMasterVM + { + Id = model.Id, + ServiceId = model.ServiceId, + ServicesName = serviceName, + Name = model.Name ?? string.Empty, + Description = model.Description ?? string.Empty, + IsActive = model.IsActive, + IsSystem = model.IsSystem + }; + } } } diff --git a/Marco.Pms.Services/Helpers/MasterHelper.cs b/Marco.Pms.Services/Helpers/MasterHelper.cs index cdad89c..eb26bca 100644 --- a/Marco.Pms.Services/Helpers/MasterHelper.cs +++ b/Marco.Pms.Services/Helpers/MasterHelper.cs @@ -21,6 +21,7 @@ namespace Marco.Pms.Services.Helpers private readonly PermissionServices _permissionService; private readonly Guid View_Master; private readonly Guid Manage_Master; + private readonly Guid tenantId; public MasterHelper(ApplicationDbContext context, ILoggingService logger, UserHelper userHelper, PermissionServices permissionServices) @@ -31,7 +32,189 @@ namespace Marco.Pms.Services.Helpers _permissionService = permissionServices; View_Master = Guid.Parse("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d"); Manage_Master = Guid.Parse("588a8824-f924-4955-82d8-fc51956cf323"); + tenantId = _userHelper.GetTenantId(); } + + // -------------------------------- Services -------------------------------- + public async Task> GetServices() + { + _logger.LogInfo("GetServices called"); + + try + { + // Step 1: Get current logged-in employee + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 2: Fetch services for the tenant + var services = await _context.ServicesMasters + .Where(s => s.TenantId == tenantId && s.IsActive) + .Select(s => s.ToServiceMasterVMFromServiceMaster()) + .ToListAsync(); + + _logger.LogInfo("Fetched {Count} service records for tenantId: {TenantId}", services.Count, tenantId); + + return ApiResponse.SuccessResponse(services, $"{services.Count} record(s) of services fetched successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error fetching services: {Message}", ex.Message); + return ApiResponse.ErrorResponse("An error occurred while fetching services", ex.Message, 500); + } + } + public async Task> CreateService(ServiceMasterDto serviceMasterDto) + { + _logger.LogInfo("CreateService called with Name: {ServiceName}", serviceMasterDto?.Name ?? "null"); + + try + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 1: Permission check + var hasManagePermission = await _permissionService.HasPermission(Manage_Master, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access denied for employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("You don't have access", "You don't have permission to take this action", 403); + } + + // Step 2: Validate input + if (string.IsNullOrWhiteSpace(serviceMasterDto?.Name) || + string.IsNullOrWhiteSpace(serviceMasterDto?.Description)) + { + _logger.LogWarning("Invalid input data for service creation by employeeId: {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Invalid data", "Name and Description are required", 400); + } + + // Step 3: Check for duplicate name + bool isExist = await _context.ServicesMasters + .AnyAsync(s => s.TenantId == tenantId && s.Name.ToLower() == serviceMasterDto.Name.ToLower()); + + if (isExist) + { + _logger.LogWarning("Duplicate service name '{ServiceName}' attempted by employeeId: {EmployeeId}", serviceMasterDto.Name, loggedInEmployee.Id); + return ApiResponse.ErrorResponse( + $"Service with name '{serviceMasterDto.Name}' already exists", + $"Service with name '{serviceMasterDto.Name}' already exists", 400); + } + + // Step 4: Save new service + ServicesMaster service = serviceMasterDto.ToServicesMasterFromServiceMasterDto(tenantId); + _context.ServicesMasters.Add(service); + await _context.SaveChangesAsync(); + + var response = service.ToServiceMasterVMFromServiceMaster(); + + _logger.LogInfo("New service '{ServiceName}' created successfully by employeeId: {EmployeeId}", service.Name, loggedInEmployee.Id); + + return ApiResponse.SuccessResponse(response, "New service created successfully", 201); + } + catch (Exception ex) + { + _logger.LogError("Error creating service: {Error}", ex.Message); + return ApiResponse.ErrorResponse("Failed to create service", ex.Message, 500); + } + } + public async Task> UpdateService(Guid id, ServiceMasterDto serviceMasterDto) + { + _logger.LogInfo("UpdateService called for Id: {Id}", id); + + try + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + + // Step 1: Permission check + 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 (serviceMasterDto == null || serviceMasterDto.Id != id || + string.IsNullOrWhiteSpace(serviceMasterDto.Name) || + string.IsNullOrWhiteSpace(serviceMasterDto.Description)) + { + _logger.LogWarning("Invalid input data provided for UpdateService. Id: {Id}", id); + return ApiResponse.ErrorResponse("Invalid input", "Please provide valid service data", 400); + } + + // Step 3: Retrieve service + var service = await _context.ServicesMasters + .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.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 = service.ToServiceMasterVMFromServiceMaster(); + + _logger.LogInfo("Service updated successfully. Id: {Id}, TenantId: {TenantId}", service.Id, tenantId); + return ApiResponse.SuccessResponse(response, "Service updated successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Error while updating service Id: {Id}. Exception: {Message}", id, ex.Message); + return ApiResponse.ErrorResponse("An error occurred while updating the service", ex.Message, 500); + } + } + public async Task> DeleteService(Guid id, bool isActive) + { + _logger.LogInfo("DeleteService called with ServiceId: {ServiceId}, IsActive: {IsActive}", id, isActive); + + try + { + // Step 1: Get current user and validate permission + 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 services", 403); + } + + // Step 2: Check if the service exists + var service = await _context.ServicesMasters + .FirstOrDefaultAsync(s => s.Id == id && s.TenantId == tenantId); + + if (service == null) + { + _logger.LogWarning("Service not found. ServiceId: {ServiceId}", id); + return ApiResponse.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.ErrorResponse("Cannot delete system-defined service", "This service is system-defined and cannot be deleted", 400); + } + + // Step 3: Soft delete or restore + service.IsActive = isActive; + await _context.SaveChangesAsync(); + + var status = isActive ? "restored" : "deactivated"; + _logger.LogInfo("Service {ServiceId} has been {Status} successfully by EmployeeId: {EmployeeId}", id, status, loggedInEmployee.Id); + + return ApiResponse.SuccessResponse(new { }, $"Service {status} successfully", 200); + } + catch (Exception ex) + { + _logger.LogError("Unexpected error occurred while deleting service {ServiceId} : {Error}", id, ex.Message); + return ApiResponse.ErrorResponse("Error deleting service", ex.Message, 500); + } + } + // -------------------------------- Contact Category -------------------------------- public async Task> CreateContactCategory(CreateContactCategoryDto contactCategoryDto) { @@ -154,7 +337,6 @@ namespace Marco.Pms.Services.Helpers // -------------------------------- Contact Tag -------------------------------- - public async Task> GetContactTags() { Guid tenantId = _userHelper.GetTenantId();