diff --git a/Marco.Pms.Model/Dtos/Organization/AssignOrganizationDto.cs b/Marco.Pms.Model/Dtos/Organization/AssignOrganizationDto.cs new file mode 100644 index 0000000..b11780c --- /dev/null +++ b/Marco.Pms.Model/Dtos/Organization/AssignOrganizationDto.cs @@ -0,0 +1,11 @@ +namespace Marco.Pms.Model.Dtos.Organization +{ + public class AssignOrganizationDto + { + public required Guid ProjectId { get; set; } + public required Guid OrganizationId { get; set; } + public Guid? ParentOrganizationId { get; set; } + public required List ServiceIds { get; set; } + public required Guid OrganizationTypeId { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Organization/UpdateOrganizationDto.cs b/Marco.Pms.Model/Dtos/Organization/UpdateOrganizationDto.cs new file mode 100644 index 0000000..61f37b1 --- /dev/null +++ b/Marco.Pms.Model/Dtos/Organization/UpdateOrganizationDto.cs @@ -0,0 +1,12 @@ +namespace Marco.Pms.Model.Dtos.Organization +{ + public class UpdateOrganizationDto + { + public required Guid Id { get; set; } + public required string Name { get; set; } + public required string ContactPerson { get; set; } + public required string Address { get; set; } + public required string ContactNumber { get; set; } + public required List ServiceIds { get; set; } + } +} diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index b9636b6..71e3eb1 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -73,6 +73,7 @@ namespace Marco.Pms.Services.Controllers } #endregion + #region =================================================================== Services APIs =================================================================== [HttpGet("service/list")] diff --git a/Marco.Pms.Services/Controllers/OrganizationController.cs b/Marco.Pms.Services/Controllers/OrganizationController.cs index 847d380..366d0e7 100644 --- a/Marco.Pms.Services/Controllers/OrganizationController.cs +++ b/Marco.Pms.Services/Controllers/OrganizationController.cs @@ -29,6 +29,8 @@ namespace Marco.Pms.Services.Controllers private readonly ILoggingService _logger; private static readonly Guid PMCProvider = Guid.Parse("b1877a3b-8832-47b1-bbe3-dc7e98672f49"); + private static readonly Guid ServiceProvider = Guid.Parse("5ee49bcd-b6d3-482f-9aaf-484afe04abec"); + private static readonly Guid SubContractorProvider = Guid.Parse("a283356a-9b02-4029-afb7-e65c703efdd4"); private static readonly Guid superTenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"); public OrganizationController(IDbContextFactory dbContextFactory, IServiceScopeFactory serviceScope, @@ -57,25 +59,25 @@ namespace Marco.Pms.Services.Controllers var organizationQuery = _context.Organizations .Where(o => o.IsActive == active); - if (tenantId != superTenantId) - { - var organizationIds = await _context.TenantOrgMappings.Where(to => to.TenantId == tenantId && to.IsActive).Select(to => to.OrganizationId).ToListAsync(); - organizationQuery = organizationQuery.Where(o => organizationIds.Contains(o.Id)); - } - if (sprid.HasValue) { organizationQuery = organizationQuery.Where(o => o.SPRID == sprid.Value); } - - if (!string.IsNullOrWhiteSpace(searchString)) + else { - organizationQuery = organizationQuery.Where(sp => - sp.Name.Contains(searchString) || - sp.ContactPerson.Contains(searchString) || - sp.Address.Contains(searchString) || - sp.Email.Contains(searchString) || - sp.ContactNumber.Contains(searchString)); + var organizationIds = await _context.TenantOrgMappings.Where(to => to.TenantId == tenantId && to.IsActive).Select(to => to.OrganizationId).ToListAsync(); + organizationQuery = organizationQuery.Where(o => organizationIds.Contains(o.Id)); + + if (!string.IsNullOrWhiteSpace(searchString)) + { + organizationQuery = organizationQuery.Where(sp => + sp.Name.Contains(searchString) + //|| sp.ContactPerson.Contains(searchString) + //|| sp.Address.Contains(searchString) + //|| sp.Email.Contains(searchString) + //|| sp.ContactNumber.Contains(searchString) + ); + } } var organizations = await organizationQuery @@ -233,93 +235,153 @@ namespace Marco.Pms.Services.Controllers } } - //[HttpPost("assign/project")] - //public async Task AssignServiceProviderToProjectAsync([FromBody] AssignOrganizationDto model) - //{ - // await using var _context = await _dbContextFactory.CreateDbContextAsync(); - // using var scope = _serviceScope.CreateScope(); + [HttpPost("assign/project")] + public async Task AssignServiceProviderToProjectAsync([FromBody] AssignOrganizationDto model) + { + await using var _context = await _dbContextFactory.CreateDbContextAsync(); + using var scope = _serviceScope.CreateScope(); + await using var transaction = await _context.Database.BeginTransactionAsync(); - // var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + try + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var todaysDate = DateTime.UtcNow.Date; - // var todaysDate = DateTime.UtcNow.Date; - // var serviceTask = Task.Run(async () => - // { - // await using var context = await _dbContextFactory.CreateDbContextAsync(); - // //return await context.ServiceMasters.FirstOrDefaultAsync(sp => sp.Id == model.ServiceId); - // }); - // var projectServiceTask = Task.Run(async () => - // { - // await using var context = await _dbContextFactory.CreateDbContextAsync(); - // return await context.ProjectServiceMappings - // .FirstOrDefaultAsync(sp => sp.ServiceId == model.ServiceId && sp.ProjectId == model.ProjectId && sp.PlannedEndDate.Date <= todaysDate - // && sp.PlannedStartDate.Date >= todaysDate && sp.ActualStartDate.Date >= todaysDate); - // }); - // var serviceProviderTask = Task.Run(async () => - // { - // await using var context = await _dbContextFactory.CreateDbContextAsync(); - // return await context.ServiceProviders.FirstOrDefaultAsync(sp => sp.Id == model.ServiceProviderId); - // }); - // var projectTask = Task.Run(async () => - // { - // await using var context = await _dbContextFactory.CreateDbContextAsync(); - // return await context.Projects.FirstOrDefaultAsync(sp => sp.Id == model.ProjectId); - // }); + var projectServicesTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.ProjectServiceMappings + .Where(sp => model.ServiceIds.Contains(sp.ServiceId) && sp.ProjectId == model.ProjectId && sp.PlannedEndDate.Date <= todaysDate + && sp.PlannedStartDate.Date >= todaysDate && sp.ActualStartDate.Date >= todaysDate).ToListAsync(); + }); - // await Task.WhenAll(serviceProviderTask, projectTask, serviceTask, projectServiceTask); + var organizationTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.Organizations.FirstOrDefaultAsync(o => o.Id == model.OrganizationId); + }); - // var serviceProvider = serviceProviderTask.Result; - // var projectService = projectServiceTask.Result; - // //var service = serviceTask.Result; - // var project = projectTask.Result; + var parentorganizationTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.Organizations.FirstOrDefaultAsync(o => o.Id == model.ParentOrganizationId); + }); - // //if (service == null) - // //{ - // // return NotFound(ApiResponse.ErrorResponse("Service not found", "Service not found in database", 404)); - // //} - // if (serviceProvider == null) - // { - // return NotFound(ApiResponse.ErrorResponse("Service Provider not found", "Service Provider not found in database", 404)); - // } - // if (project == null) - // { - // return NotFound(ApiResponse.ErrorResponse("Project not found", "Project not found in database", 404)); - // } - // if (projectService == null) - // { - // return NotFound(ApiResponse.ErrorResponse("Project Service not found", "Project Service not found in database", 404)); - // } - // var serviceProviderTenantMapping = await _context.ServiceProviderTenantMappings - // .FirstOrDefaultAsync(spt => spt.ServiceProviderId == model.ServiceProviderId && spt.TenantId == project.TenantId); + var projectTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.Projects.FirstOrDefaultAsync(p => p.Id == model.ProjectId); + }); - // if (serviceProviderTenantMapping == null) - // { - // var newServiceProviderTenantMapping = new OrganizationTenantMapping - // { - // ServiceProviderId = serviceProvider.Id, - // SPRID = serviceProvider.SPRID, - // IsActive = true, - // TenantId = project.TenantId - // }; - // _context.ServiceProviderTenantMappings.Add(newServiceProviderTenantMapping); - // } + var isPMCTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.Projects.AnyAsync(p => p.Id == model.ProjectId && p.PMCId == loggedInEmployee.OrganizationId); + }); - // var projectServiceProviderMapping = new ProjectOrganizationMapping - // { - // ProjectServiceId = projectService.Id, - // ServiceProviderId = model.ServiceProviderId, - // AssignedDate = model.AssignedDate, - // CompletionDate = model.CompletionDate, - // TenantId = project.TenantId - // }; + var isServiceProviderTask = Task.Run(async () => + { + await using var context = await _dbContextFactory.CreateDbContextAsync(); + return await context.ProjectOrgMappings.AnyAsync(p => p.Id == model.ProjectId && p.OrganizationId == loggedInEmployee.OrganizationId + && p.OrganizationTypeId == ServiceProvider); + }); - // _context.ProjectServiceProviderMappings.Add(projectServiceProviderMapping); + await Task.WhenAll(organizationTask, parentorganizationTask, projectTask, projectServicesTask, isPMCTask, isServiceProviderTask); - // await _context.SaveChangesAsync(); + var organization = organizationTask.Result; + var projectServices = projectServicesTask.Result; + var parentorganization = parentorganizationTask.Result; + var project = projectTask.Result; + var isPMC = isPMCTask.Result; + var isServiceProvider = isServiceProviderTask.Result; - // var response = _mapper.Map(serviceProvider); + if (organization == null) + { + return NotFound(ApiResponse.ErrorResponse("Organization not found", "Organization not found in database", 404)); + } + if (project == null) + { + return NotFound(ApiResponse.ErrorResponse("Project not found", "Project not found in database", 404)); + } + if (projectServices == null) + { + return NotFound(ApiResponse.ErrorResponse("Project Service not found", "Project Service not found in database", 404)); + } - // return Ok(ApiResponse.SuccessResponse(response, "Service Provider successfully assigned to the project", 200)); - //} + var serviceProviderTenantMapping = await _context.TenantOrgMappings + .FirstOrDefaultAsync(spt => spt.OrganizationId == model.OrganizationId && spt.TenantId == project.TenantId); + + if (serviceProviderTenantMapping == null) + { + var newServiceProviderTenantMapping = new TenantOrgMapping + { + OrganizationId = organization.Id, + SPRID = organization.SPRID, + IsActive = true, + TenantId = project.TenantId + }; + _context.TenantOrgMappings.Add(newServiceProviderTenantMapping); + } + + List projectOrgMappings = new List(); + + foreach (var serviceId in model.ServiceIds) + { + if (isPMC && model.OrganizationTypeId != ServiceProvider && model.OrganizationTypeId != SubContractorProvider) + { + continue; + } + if (isServiceProvider && model.OrganizationTypeId == ServiceProvider) + { + continue; + } + var projectService = projectServices.FirstOrDefault(ps => ps.ServiceId == serviceId); + if (projectService == null) + { + projectService = new ProjectServiceMapping + { + ProjectId = project.Id, + ServiceId = serviceId, + TenantId = project.TenantId, + PlannedStartDate = project.StartDate ?? DateTime.UtcNow, + PlannedEndDate = project.EndDate ?? DateTime.UtcNow, + ActualStartDate = DateTime.UtcNow, + }; + _context.ProjectServiceMappings.Add(projectService); + } + var projectOrgMapping = new ProjectOrgMapping + { + ProjectServiceId = projectService.Id, + OrganizationId = model.OrganizationId, + OrganizationTypeId = model.OrganizationTypeId, + ParentOrganizationId = model.ParentOrganizationId ?? loggedInEmployee.OrganizationId, + AssignedDate = DateTime.UtcNow, + TenantId = project.TenantId + }; + projectOrgMappings.Add(projectOrgMapping); + } + + _context.ProjectOrgMappings.AddRange(projectOrgMappings); + + await _context.SaveChangesAsync(); + + var response = _mapper.Map(organization); + + return Ok(ApiResponse.SuccessResponse(response, "Organization successfully assigned to the project", 200)); + } + catch (DbUpdateException dbEx) + { + await transaction.RollbackAsync(); + + _logger.LogError(dbEx, "Database Exception has been occured"); + return StatusCode(500, ApiResponse.ErrorResponse("Internal error", "An database exception has been occured", 500)); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception has been occured"); + return StatusCode(500, ApiResponse.ErrorResponse("Internal error", "An internal exception has been occured", 500)); + } + } #endregion #region =================================================================== Put Functions =================================================================== @@ -340,7 +402,7 @@ namespace Marco.Pms.Services.Controllers // var employeeTask = Task.Run(async () => // { // await using var context = await _dbContextFactory.CreateDbContextAsync(); - // return await context.Employees.AsNoTracking().FirstOrDefaultAsync(e => e.ServiceProviderId == id && e.IsPrimary); + // return await context.Employees.AsNoTracking().FirstOrDefaultAsync(e => e.OrganizationId == id && e.IsPrimary); // }); // await Task.WhenAll(clientTask, employeeTask);