using System.Net; using System.Text.Json; using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Dtos.Tenant; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Tenant; using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Marco.Pms.Services.Controllers { [Route("api/[controller]")] [ApiController] public class TenantController : ControllerBase { private readonly string jsonString = System.IO.File.ReadAllText("Data/RolesCofiguration.json"); private readonly ApplicationDbContext _context; private readonly UserManager _userManager; private readonly ILoggingService _logger; private readonly IEmailSender _emailSender; private readonly IConfiguration _configuration; public TenantController(ApplicationDbContext context, UserManager userManager, ILoggingService logger, IEmailSender emailSender, IConfiguration configuration) { _context = context; _userManager = userManager; _logger = logger; _emailSender = emailSender; _configuration = configuration; } [HttpPost] public async Task CreateTenant([FromForm] CreateTenantDto createTenantDto) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var existedUser = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Email == createTenantDto.Email && u.IsActive == true); var existedTenanat = await _context.Tenants.FirstOrDefaultAsync(t => t.Name == createTenantDto.OrganizatioinName); if (existedUser == null && existedTenanat == null) { var transaction = _context.Database.BeginTransaction(); Tenant newTenant = createTenantDto.CreateDtoToTenant(); _context.Tenants.Add(newTenant); await _context.SaveChangesAsync(); //Tenant? tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Name == newTenant.Name); if (newTenant != null) { RoleConfiguration settings = JsonSerializer.Deserialize(jsonString) ?? new RoleConfiguration(); var TenantId = newTenant.Id; JobRole jobRole = new JobRole { Name = settings.JobRoleName, Description = settings.JobRoleDescription, TenantId = TenantId }; ApplicationRole role = new ApplicationRole { Role = settings.RoleName, Description = settings.RoleDescription, TenantId = TenantId }; _context.JobRoles.Add(jobRole); _context.ApplicationRoles.Add(role); await _context.SaveChangesAsync(); List permissions = await _context.FeaturePermissions.AsNoTracking().ToListAsync(); List rolePermissionMappings = new List(); foreach (var permission in permissions) { var item = new RolePermissionMappings() { ApplicationRoleId = role.Id, FeaturePermissionId = permission.Id }; bool assigned = _context.RolePermissionMappings.Any(c => c.ApplicationRoleId == role.Id && c.FeaturePermissionId == permission.Id); if (permission.IsEnabled && !assigned) rolePermissionMappings.Add(item); } _context.RolePermissionMappings.AddRange(rolePermissionMappings); await _context.SaveChangesAsync(); var user = new ApplicationUser { UserName = createTenantDto.Email, Email = createTenantDto.Email, TenantId = TenantId, IsRootUser = true, EmailConfirmed = true // comment this line of code after implimenting proper email verification }; var result = await _userManager.CreateAsync(user, createTenantDto.Password); if (result.Succeeded) { try { var token = await _userManager.GeneratePasswordResetTokenAsync(user); var resetLink = $"{_configuration["AppSettings:WebFrontendUrl"]}/reset-password?token={WebUtility.UrlEncode(token)}"; if (user.Email == null) return NotFound(ApiResponse.ErrorResponse("Email Not found", "Email Not found", 404)); await _emailSender.SendTenanatRegistrationSuccessEmail(user.Email, newTenant.ContactName ?? "", resetLink); Employee newEmployee = CreateTenantDtoToEmployee(createTenantDto, TenantId, user.Id, jobRole.Id); _context.Employees.Add(newEmployee); await _context.SaveChangesAsync(); var employeeRoleMapping = new EmployeeRoleMapping { EmployeeId = newEmployee.Id, RoleId = role.Id, TenantId = TenantId, IsEnabled = true }; _context.EmployeeRoleMappings.Add(employeeRoleMapping); await _context.SaveChangesAsync(); transaction.Commit(); return Ok(ApiResponse.SuccessResponse(result.Succeeded, "Tenant created successfully.", 200)); }catch(Exception ex) { transaction.Rollback(); _logger.LogError("{Error}", ex); } } else { // Log the errors for debugging foreach (var error in result.Errors) { // Log error.Description _logger.LogError("{Error}", error.Description); } transaction.Rollback(); return BadRequest("Failed to create the root user."); } } transaction.Rollback(); return BadRequest("Falied to create Tenant"); } return BadRequest("Email Already Exists"); } [HttpGet("profile/{tenantId}")] public async Task GetTenantProfile(int tenantId) { if (tenantId <= 0) { return BadRequest("Tenant Id is required and must be greater than zero."); } var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId && t.IsActive ==true); if (tenant == null) { return NotFound("Tenant Not Found"); } TenantVM tenantVM = tenant.ToTenantVMFromTenant(); return Ok(ApiResponse.SuccessResponse(tenantVM, "Tenant Profile.", 200)); } [HttpPost("edit/{tenantId}")] public async Task SuspendTenant(int tenantId, UpdateTenantDto model) { if (tenantId <= 0) { return BadRequest("Tenant Id is required and must be greater than zero."); } var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId && t.IsActive == true); //var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.TenantId == tenantId && u.IsRootUser == true); //var employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == tenantId && e.ApplicationUserId == user.Id); if (tenant == null) { return NotFound("Tenant Not Found"); } tenant.Name = model.OrganizatioinName; tenant.DomainName = model.Website; tenant.ContactName = model.Name; tenant.Description = model.About; tenant.ContactNumber = model.ContactNumber; tenant.OnBoardingDate = model.OnBoardingDate; await _context.SaveChangesAsync(); TenantVM tenantVM = tenant.ToTenantVMFromTenant(); return Ok(ApiResponse.SuccessResponse(tenantVM, "Tenant Profile.", 200)); } [HttpDelete("suspend/{tenantId}")] public async Task SuspendTenant(int tenantId) { if (tenantId <= 0) { return BadRequest("Tenant Id is required and must be greater than zero."); } var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId); var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.TenantId == tenantId && u.IsRootUser == true); if (tenant != null && user != null) { var employee = await _context.Employees.FirstOrDefaultAsync(e => e.TenantId == tenantId && e.ApplicationUserId == user.Id) ?? new Employee(); tenant.IsActive = false; user.IsActive = false; user.IsRootUser = false; employee.IsActive = false; var result = await _userManager.UpdateAsync(user); _context.Tenants.Update(tenant); _context.Employees.Update(employee); await _context.SaveChangesAsync(); return Ok("Tenant is Suspended"); } return NotFound("Tenant Not Found"); } private static Employee CreateTenantDtoToEmployee(CreateTenantDto model, int TenantId, string? ApplicationUserId, int jobRoleId) { return new Employee { ApplicationUserId = ApplicationUserId, FirstName = model.Name, LastName = "", Email = model.Email, TenantId = TenantId, CurrentAddress = "", BirthDate = DateTime.UtcNow, EmergencyPhoneNumber = "", EmergencyContactPerson = "", AadharNumber = "", Gender = "", MiddleName = "", PanNumber = "", PermanentAddress = "", PhoneNumber = model.ContactNumber, Photo = null, // GetFileDetails(model.Photo).Result.FileData, JobRoleId = jobRoleId, JoiningDate = DateTime.UtcNow, }; } } }