Compare commits
No commits in common. "main" and "Ashutosh_Enhancement#1452" have entirely different histories.
main
...
Ashutosh_E
@ -212,48 +212,6 @@ namespace Marco.Pms.Helpers.CacheHelper
|
||||
|
||||
return true;
|
||||
}
|
||||
public async Task<bool> ClearAllEmployeesFromCacheByOnlyEmployeeId(Guid employeeId)
|
||||
{
|
||||
var employeeIdString = employeeId.ToString();
|
||||
|
||||
try
|
||||
{
|
||||
var filter = Builders<EmployeePermissionMongoDB>.Filter.Eq(e => e.Id, employeeIdString);
|
||||
|
||||
var result = await _collection.DeleteManyAsync(filter);
|
||||
|
||||
if (result.DeletedCount == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while deleting employee profile");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public async Task<bool> ClearAllEmployeesFromCacheByTenantId(Guid tenantId)
|
||||
{
|
||||
var tenantIdString = tenantId.ToString();
|
||||
|
||||
try
|
||||
{
|
||||
var filter = Builders<EmployeePermissionMongoDB>.Filter.Eq(e => e.TenantId, tenantIdString);
|
||||
|
||||
var result = await _collection.DeleteManyAsync(filter);
|
||||
|
||||
if (result.DeletedCount == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while deleting employee profile");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public async Task<bool> ClearAllEmployeesFromCacheByEmployeeIds(List<string> employeeIds, Guid tenantId)
|
||||
{
|
||||
var tenantIdString = tenantId.ToString();
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
public class CreateWorkStatusMasterDto
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public required string Description { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
public class UpdateWorkStatusMasterDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
public required string Description { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
public class CreateContactCategoryDto
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public required string Description { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
public class CreateContactTagDto
|
||||
{
|
||||
public required string Name { get; set; }
|
||||
public required string Description { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
{
|
||||
public class UpdateContactCategoryDto
|
||||
{
|
||||
public required Guid Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
public required string Description { get; set; }
|
||||
public Guid Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
public class UpdateContactTagDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
public required string Description { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Tenant;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@ -1470,9 +1469,6 @@ namespace MarcoBMS.Services.Controllers
|
||||
// Generate and store refresh token
|
||||
var refreshToken = await _refreshTokenService.CreateRefreshToken(loggedInEmployee.ApplicationUserId, tenantId.ToString(), loggedInEmployee.OrganizationId, _jwtSettings);
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
await _cache.ClearAllEmployeesFromCacheByOnlyEmployeeId(loggedInEmployee.Id);
|
||||
|
||||
_logger.LogInfo("Tenant selected and tokens generated for TenantId: {TenantId} and Employee: {EmployeeEmail}", tenantId, loggedInEmployee.Email ?? string.Empty);
|
||||
|
||||
// Return success response including tokens
|
||||
|
@ -9,7 +9,6 @@ using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Model.ViewModels.Organization;
|
||||
using Marco.Pms.Model.ViewModels.Projects;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using Marco.Pms.Services.Service;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
@ -31,7 +30,6 @@ namespace Marco.Pms.Services.Controllers
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly Guid tenantId;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly Guid loggedOrganizationId;
|
||||
private readonly ILoggingService _logger;
|
||||
|
||||
private static readonly Guid PMCProvider = Guid.Parse("b1877a3b-8832-47b1-bbe3-dc7e98672f49");
|
||||
@ -49,7 +47,6 @@ namespace Marco.Pms.Services.Controllers
|
||||
_userHelper = userHelper ?? throw new ArgumentNullException(nameof(userHelper));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
||||
loggedOrganizationId = _userHelper.GetCurrentOrganizationId();
|
||||
tenantId = userHelper.GetTenantId();
|
||||
}
|
||||
#region =================================================================== Get Functions ===================================================================
|
||||
@ -672,8 +669,6 @@ namespace Marco.Pms.Services.Controllers
|
||||
Service = _mapper.Map<ServiceMasterVM>(s)
|
||||
}).ToList();
|
||||
|
||||
await AssignApplicationRoleToOrganization(organization.Id, project.TenantId);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Organization successfully assigned to the project", 200));
|
||||
}
|
||||
catch (DbUpdateException dbEx)
|
||||
@ -722,36 +717,34 @@ namespace Marco.Pms.Services.Controllers
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Organization not found", "Organization not found in database", 404));
|
||||
}
|
||||
|
||||
if (organizationTenantMapping != null)
|
||||
if (organizationTenantMapping == null)
|
||||
{
|
||||
// Create new tenant-organization mapping if none exists
|
||||
var newMapping = new TenantOrgMapping
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
SPRID = organization.SPRID,
|
||||
AssignedDate = DateTime.UtcNow,
|
||||
IsActive = true,
|
||||
AssignedById = loggedInEmployee.Id,
|
||||
TenantId = tenantId
|
||||
};
|
||||
_context.TenantOrgMappings.Add(newMapping);
|
||||
await _context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
|
||||
_logger.LogInfo("Assigned organization {OrganizationId} to tenant {TenantId} successfully.", organizationId, tenantId);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInfo("Organization {OrganizationId} is already assigned to tenant {TenantId}. No action taken.", organizationId, tenantId);
|
||||
// Commit transaction anyway to complete scope cleanly (optional)
|
||||
await transaction.RollbackAsync();
|
||||
return StatusCode(409, ApiResponse<object>.ErrorResponse("Organization is already assigned to tenant", "Organization is already assigned to tenant", 409));
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
|
||||
// Create new tenant-organization mapping if none exists
|
||||
var newMapping = new TenantOrgMapping
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
SPRID = organization.SPRID,
|
||||
AssignedDate = DateTime.UtcNow,
|
||||
IsActive = true,
|
||||
AssignedById = loggedInEmployee.Id,
|
||||
TenantId = tenantId
|
||||
};
|
||||
_context.TenantOrgMappings.Add(newMapping);
|
||||
await _context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
|
||||
_logger.LogInfo("Assigned organization {OrganizationId} to tenant {TenantId} successfully.", organizationId, tenantId);
|
||||
|
||||
|
||||
// Prepare response view model
|
||||
var response = _mapper.Map<BasicOrganizationVm>(organization);
|
||||
|
||||
await AssignApplicationRoleToOrganization(organization.Id, tenantId);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Organization has been assigned to tenant", 200));
|
||||
}
|
||||
catch (DbUpdateException dbEx)
|
||||
@ -945,98 +938,45 @@ namespace Marco.Pms.Services.Controllers
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Helper Functions ===================================================================
|
||||
//private ServicesProviderFilter? TryDeserializeServicesProviderFilter(string? filter)
|
||||
//{
|
||||
// if (string.IsNullOrWhiteSpace(filter))
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
private async Task AssignApplicationRoleToOrganization(Guid organizationId, Guid tenantId)
|
||||
{
|
||||
if (loggedOrganizationId == organizationId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
using var scope = _serviceScope.CreateScope();
|
||||
// var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
// ServicesProviderFilter? documentFilter = null;
|
||||
|
||||
var rootEmployee = await _context.Employees
|
||||
.Include(e => e.ApplicationUser)
|
||||
.FirstOrDefaultAsync(e => e.ApplicationUser != null && e.ApplicationUser.IsRootUser.HasValue && e.ApplicationUser.IsRootUser.Value && e.OrganizationId == organizationId && e.IsPrimary);
|
||||
if (rootEmployee == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
string serviceProviderRoleName = "Service Provider Role";
|
||||
// try
|
||||
// {
|
||||
// // First, try to deserialize directly. This is the expected case (e.g., from a web client).
|
||||
// documentFilter = JsonSerializer.Deserialize<ServicesProviderFilter>(filter, options);
|
||||
// }
|
||||
// catch (JsonException ex)
|
||||
// {
|
||||
// _logger.LogError(ex, "[{MethodName}] Failed to directly deserialize filter. Attempting to unescape and re-parse. Filter: {Filter}", nameof(TryDeserializeServicesProviderFilter), filter);
|
||||
|
||||
var serviceProviderRole = await _context.ApplicationRoles.FirstOrDefaultAsync(ar => ar.Role == serviceProviderRoleName && ar.TenantId == tenantId);
|
||||
if (serviceProviderRole == null)
|
||||
{
|
||||
serviceProviderRole = new Model.Roles.ApplicationRole
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Role = serviceProviderRoleName,
|
||||
Description = serviceProviderRoleName,
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
};
|
||||
_context.ApplicationRoles.Add(serviceProviderRole);
|
||||
// // If direct deserialization fails, it might be an escaped string (common with tools like Postman or some mobile clients).
|
||||
// try
|
||||
// {
|
||||
// // Unescape the string first, then deserialize the result.
|
||||
// string unescapedJsonString = JsonSerializer.Deserialize<string>(filter, options) ?? "";
|
||||
// if (!string.IsNullOrWhiteSpace(unescapedJsonString))
|
||||
// {
|
||||
// documentFilter = JsonSerializer.Deserialize<ServicesProviderFilter>(unescapedJsonString, options);
|
||||
// }
|
||||
// }
|
||||
// catch (JsonException ex1)
|
||||
// {
|
||||
// // If both attempts fail, log the final error and return null.
|
||||
// _logger.LogError(ex1, "[{MethodName}] All attempts to deserialize the filter failed. Filter will be ignored. Filter: {Filter}", nameof(TryDeserializeServicesProviderFilter), filter);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// return documentFilter;
|
||||
//}
|
||||
|
||||
var rolePermissionMappigs = new List<RolePermissionMappings> {
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.ViewProject
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.ViewProjectInfra
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.ViewTask
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.ViewAllEmployees
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.TeamAttendance
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.AssignRoles
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.ManageProjectInfra
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.AssignAndReportProgress
|
||||
},
|
||||
new RolePermissionMappings
|
||||
{
|
||||
ApplicationRoleId = serviceProviderRole.Id,
|
||||
FeaturePermissionId = PermissionsMaster.AddAndEditTask
|
||||
}
|
||||
};
|
||||
_context.RolePermissionMappings.AddRange(rolePermissionMappigs);
|
||||
}
|
||||
_context.EmployeeRoleMappings.Add(new EmployeeRoleMapping
|
||||
{
|
||||
EmployeeId = rootEmployee.Id,
|
||||
RoleId = serviceProviderRole.Id,
|
||||
IsEnabled = true,
|
||||
TenantId = tenantId
|
||||
});
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
await _cache.ClearAllPermissionIdsByEmployeeID(rootEmployee.Id, tenantId);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -560,13 +560,6 @@ namespace MarcoBMS.Services.Controllers
|
||||
var response = await _projectServices.GetAssignedOrganizationsToProjectAsync(projectId, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
[HttpGet("get/assigned/organization/dropdown/{projectId}")]
|
||||
public async Task<IActionResult> GetAssignedOrganizationsToProjectForDropdownAsync(Guid projectId)
|
||||
{
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _projectServices.GetAssignedOrganizationsToProjectForDropdownAsync(projectId, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -1013,6 +1013,10 @@ namespace Marco.Pms.Services.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await ClearPermissionForTenant();
|
||||
});
|
||||
var features = await _featureDetailsHelper.GetFeatureDetails(subscriptionPlan.FeaturesId);
|
||||
if (features == null)
|
||||
{
|
||||
@ -1065,7 +1069,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
// Get root employee and role for this tenant
|
||||
var rootEmployee = await _context.Employees
|
||||
.Include(e => e.ApplicationUser)
|
||||
.FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.OrganizationId == tenant.OrganizationId);
|
||||
.FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.TenantId == model.TenantId);
|
||||
|
||||
if (rootEmployee == null)
|
||||
{
|
||||
@ -1123,9 +1127,6 @@ namespace Marco.Pms.Services.Controllers
|
||||
_logger.LogInfo("Removed {Count} role permission mappings for role {RoleId}", deleteMappings.Count, roleId);
|
||||
}
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
await _cache.ClearAllEmployeesFromCacheByTenantId(tenant.Id);
|
||||
|
||||
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
||||
|
||||
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
||||
@ -1324,6 +1325,10 @@ namespace Marco.Pms.Services.Controllers
|
||||
_logger.LogInfo("Subscription plan changed: Tenant={TenantId}, NewPlan={PlanId}",
|
||||
model.TenantId, model.PlanId);
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await ClearPermissionForTenant();
|
||||
});
|
||||
|
||||
// 8. Update tenant permissions based on subscription features.
|
||||
var features = await _featureDetailsHelper.GetFeatureDetails(subscriptionPlan.FeaturesId);
|
||||
@ -1358,7 +1363,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
// 8c. Find root employee & role for this tenant.
|
||||
var rootEmployee = await context.Employees
|
||||
.Include(e => e.ApplicationUser)
|
||||
.FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.OrganizationId == tenant.OrganizationId);
|
||||
.FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.TenantId == model.TenantId);
|
||||
|
||||
if (rootEmployee == null)
|
||||
{
|
||||
@ -1369,8 +1374,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
|
||||
var rootRoleId = await context.EmployeeRoleMappings
|
||||
.AsNoTracking()
|
||||
.Include(er => er.Role)
|
||||
.Where(er => er.EmployeeId == rootEmployee.Id && er.TenantId == model.TenantId && er.Role != null && er.Role.Role == "Super User")
|
||||
.Where(er => er.EmployeeId == rootEmployee.Id && er.TenantId == model.TenantId)
|
||||
.Select(er => er.RoleId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
@ -1435,9 +1439,6 @@ namespace Marco.Pms.Services.Controllers
|
||||
_logger.LogInfo("Permissions revoked: {Count} for Role={RoleId}", mappingsToRemove.Count, rootRoleId);
|
||||
}
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
await _cache.ClearAllEmployeesFromCacheByTenantId(tenant.Id);
|
||||
|
||||
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
||||
|
||||
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
||||
@ -1822,6 +1823,19 @@ namespace Marco.Pms.Services.Controllers
|
||||
return ApiResponse<SubscriptionPlanVM>.SuccessResponse(VM, "Success", 200);
|
||||
}
|
||||
|
||||
private async Task ClearPermissionForTenant()
|
||||
{
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
var _cacheLogger = scope.ServiceProvider.GetRequiredService<ILoggingService>();
|
||||
|
||||
var employeeIds = await _context.Employees.Where(e => e.TenantId == tenantId).Select(e => e.Id).ToListAsync();
|
||||
await _cache.ClearAllEmployeesFromCacheByEmployeeIds(employeeIds, tenantId);
|
||||
_cacheLogger.LogInfo("{EmployeeCount} number of employee deleted", employeeIds.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -956,28 +956,6 @@ namespace Marco.Pms.Services.Helpers
|
||||
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
||||
}
|
||||
}
|
||||
public async Task ClearAllEmployeesFromCacheByOnlyEmployeeId(Guid employeeId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _employeeCache.ClearAllEmployeesFromCacheByOnlyEmployeeId(employeeId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
||||
}
|
||||
}
|
||||
public async Task ClearAllEmployeesFromCacheByTenantId(Guid tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _employeeCache.ClearAllEmployeesFromCacheByTenantId(tenantId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
||||
}
|
||||
}
|
||||
public async Task ClearAllEmployees()
|
||||
{
|
||||
try
|
||||
|
@ -379,27 +379,6 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Contact Category Master =======================================================
|
||||
CreateMap<CreateContactCategoryDto, ContactCategoryMaster>();
|
||||
CreateMap<UpdateContactCategoryDto, ContactCategoryMaster>();
|
||||
CreateMap<ContactCategoryMaster, ContactCategoryVM>();
|
||||
#endregion
|
||||
#region ======================================================= Contact Tag Master =======================================================
|
||||
CreateMap<CreateContactTagDto, ContactTagMaster>();
|
||||
CreateMap<UpdateContactTagDto, ContactTagMaster>();
|
||||
CreateMap<ContactTagMaster, ContactTagVM>();
|
||||
#endregion
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Document =======================================================
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2805,128 +2805,6 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<object>.ErrorResponse("Internal error", "An internal exception occurred", 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> GetAssignedOrganizationsToProjectForDropdownAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee)
|
||||
{
|
||||
_logger.LogDebug("Started fetching assigned organizations for ProjectId: {ProjectId} and TenantId: {TenantId} by user {UserId}",
|
||||
projectId, tenantId, loggedInEmployee.Id);
|
||||
|
||||
try
|
||||
{
|
||||
// Create a scoped PermissionServices instance for permission checks
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
|
||||
// Retrieve the project by projectId and tenantId
|
||||
var projectTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.Projects.AsNoTracking().Include(p => p.Promoter).Include(p => p.PMC).FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
||||
});
|
||||
|
||||
var tenantTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.Tenants.AsNoTracking().Include(t => t.Organization).FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||
});
|
||||
var projectServiceTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.ProjectServiceMappings
|
||||
.AsNoTracking()
|
||||
.Include(ps => ps!.Service)
|
||||
.Where(ps => ps.ProjectId == projectId && ps.TenantId == tenantId).ToListAsync();
|
||||
});
|
||||
|
||||
await Task.WhenAll(projectTask, tenantTask, projectServiceTask);
|
||||
|
||||
var project = projectTask.Result;
|
||||
var tenant = tenantTask.Result;
|
||||
var projectService = projectServiceTask.Result;
|
||||
|
||||
if (project == null || tenant == null)
|
||||
{
|
||||
_logger.LogWarning("Project {ProjectId} not found in database for tenant {TenantId}", projectId, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404);
|
||||
}
|
||||
|
||||
// Check if the logged in employee has permission to access the project
|
||||
var hasPermission = await permissionService.HasProjectPermission(loggedInEmployee, projectId);
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied for user {UserId} on project {ProjectId}", loggedInEmployee.Id, projectId);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied", "You do not have permission to access this project.", 403);
|
||||
}
|
||||
|
||||
// Fetch all project-organization mappings with related service and organization data
|
||||
var projectOrgMappingsQuery = _context.ProjectOrgMappings
|
||||
.AsNoTracking()
|
||||
.Include(po => po.ProjectService)
|
||||
.ThenInclude(ps => ps!.Service)
|
||||
.Include(po => po.AssignedBy)
|
||||
.Include(po => po.OrganizationType)
|
||||
.Include(po => po.Organization)
|
||||
.Where(po => po.ProjectService != null
|
||||
&& po.ProjectService.ProjectId == projectId
|
||||
&& po.TenantId == tenantId);
|
||||
|
||||
if (loggedInEmployee.OrganizationId != project.PMCId && loggedInEmployee.OrganizationId != project.PromoterId && loggedInEmployee.OrganizationId != tenant.OrganizationId)
|
||||
{
|
||||
projectOrgMappingsQuery = projectOrgMappingsQuery.Where(po => po.ParentOrganizationId == loggedInEmployee.OrganizationId || po.OrganizationId == loggedInEmployee.OrganizationId);
|
||||
}
|
||||
|
||||
var projectOrgMappings = await projectOrgMappingsQuery
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
var organizations = projectOrgMappings.Select(po => po.Organization!).ToList();
|
||||
|
||||
if (loggedInEmployee.OrganizationId == project.PMCId || loggedInEmployee.OrganizationId == project.PromoterId || loggedInEmployee.OrganizationId == tenant.OrganizationId)
|
||||
{
|
||||
var pmc = project.PMC;
|
||||
var promoter = project.Promoter;
|
||||
var organization = tenant.Organization;
|
||||
|
||||
if (!organizations.Any(r => r.Id == project.PMCId) && pmc != null)
|
||||
{
|
||||
organizations.Add(pmc);
|
||||
}
|
||||
if (!organizations.Any(r => r.Id == project.PromoterId) && promoter != null)
|
||||
{
|
||||
organizations.Add(promoter);
|
||||
}
|
||||
if (!organizations.Any(r => r.Id == tenant.OrganizationId) && organization != null)
|
||||
{
|
||||
organizations.Add(organization);
|
||||
}
|
||||
}
|
||||
|
||||
organizations = organizations.DistinctBy(o => o.Id).ToList();
|
||||
|
||||
// Filter and map the data to the desired view model
|
||||
var response = organizations
|
||||
.Select(o => new ProjectOrganizationVM
|
||||
{
|
||||
Id = o.Id,
|
||||
Name = o.Name,
|
||||
SPRID = 0
|
||||
})
|
||||
.ToList();
|
||||
|
||||
_logger.LogInfo("Fetched {Count} assigned organizations for ProjectId: {ProjectId}", response.Count, projectId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, "Successfully fetched the list of organizations assigned to the project", 200);
|
||||
}
|
||||
catch (DbUpdateException dbEx)
|
||||
{
|
||||
_logger.LogError(dbEx, "Database exception while fetching assigned organizations for ProjectId: {ProjectId}", projectId);
|
||||
return ApiResponse<object>.ErrorResponse("Internal error", "A database exception occurred", 500);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unhandled exception while fetching assigned organizations for ProjectId: {ProjectId}", projectId);
|
||||
return ApiResponse<object>.ErrorResponse("Internal error", "An internal exception occurred", 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -49,7 +49,6 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
Task<ApiResponse<object>> DeassignServiceToProjectAsync(DeassignServiceDto model, Guid tenantId, Employee loggedInEmployee);
|
||||
|
||||
Task<ApiResponse<object>> GetAssignedOrganizationsToProjectAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetAssignedOrganizationsToProjectForDropdownAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user