diff --git a/src/Hng.Application.Test/Features/UserManagement/UserActivationCommandShould.cs b/src/Hng.Application.Test/Features/UserManagement/UserActivationCommandShould.cs new file mode 100644 index 00000000..4769ad7c --- /dev/null +++ b/src/Hng.Application.Test/Features/UserManagement/UserActivationCommandShould.cs @@ -0,0 +1,113 @@ +using AutoMapper; +using Hng.Application.Features.UserManagement.Commands; +using Hng.Application.Features.UserManagement.Dtos; +using Hng.Application.Features.UserManagement.Handlers; +using Hng.Domain.Entities; +using Hng.Domain.Enums; +using Hng.Infrastructure.Repository.Interface; +using Microsoft.AspNetCore.Http; +using Moq; +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace Hng.Application.Tests.Features.UserManagement.Handlers; + +public class UserActivationCommandHandlerTests +{ + [Fact] + public async Task Handle_UserNotFound_ReturnsNotFoundResponse() + { + // Arrange + var mockUserRepository = new Mock>(); + var mockMapper = new Mock(); + var handler = new UserActivationCommandHandler(mockUserRepository.Object, mockMapper.Object); + var command = new UserActivationCommand { UserId = Guid.NewGuid() }; + + mockUserRepository.Setup(repo => repo.GetBySpec(It.IsAny>>())) + .ReturnsAsync((User)null); + + // Act + var result = await handler.Handle(command, CancellationToken.None); + + // Assert + Assert.Equal(StatusCodes.Status404NotFound, result.StatusCode); + Assert.Equal("User not found.", result.Message); + } + + [Fact] + public async Task Handle_UserAlreadyActive_ReturnsBadRequestResponse() + { + // Arrange + var userId = Guid.NewGuid(); + var user = new User { Id = userId, UserStatus = UserStatus.activate }; + var mockUserRepository = new Mock>(); + var mockMapper = new Mock(); + var handler = new UserActivationCommandHandler(mockUserRepository.Object, mockMapper.Object); + var command = new UserActivationCommand { UserId = userId }; + + mockUserRepository.Setup(repo => repo.GetBySpec(It.IsAny>>())) + .ReturnsAsync(user); + + // Act + var result = await handler.Handle(command, CancellationToken.None); + + // Assert + Assert.Equal(StatusCodes.Status400BadRequest, result.StatusCode); + Assert.Equal("User is already active.", result.Message); + } + + [Fact] + public async Task Handle_UserActivationSuccess_ReturnsOkResponse() + { + // Arrange + var userId = Guid.NewGuid(); + var user = new User { Id = userId, UserStatus = UserStatus.deactivate }; + var userDto = new UserResponseDto { Id = userId.ToString() }; + var mockUserRepository = new Mock>(); + var mockMapper = new Mock(); + var handler = new UserActivationCommandHandler(mockUserRepository.Object, mockMapper.Object); + var command = new UserActivationCommand { UserId = userId }; + + mockUserRepository.Setup(repo => repo.GetBySpec(It.IsAny>>())) + .ReturnsAsync(user); + mockUserRepository.Setup(repo => repo.UpdateAsync(It.IsAny())) + .Returns(Task.CompletedTask); + mockUserRepository.Setup(repo => repo.SaveChanges()) + .Returns(Task.CompletedTask); + mockMapper.Setup(mapper => mapper.Map(It.IsAny())) + .Returns(userDto); + + // Act + var result = await handler.Handle(command, CancellationToken.None); + + // Assert + Assert.Equal(StatusCodes.Status200OK, result.StatusCode); + Assert.Equal("User activated successfully.", result.Message); + } + + [Fact] + public async Task Handle_ExceptionThrown_ReturnsInternalServerError() + { + // Arrange + var userId = Guid.NewGuid(); + var user = new User { Id = userId, UserStatus = UserStatus.deactivate }; + var mockUserRepository = new Mock>(); + var mockMapper = new Mock(); + var handler = new UserActivationCommandHandler(mockUserRepository.Object, mockMapper.Object); + var command = new UserActivationCommand { UserId = userId }; + + mockUserRepository.Setup(repo => repo.GetBySpec(It.IsAny>>())) + .ReturnsAsync(user); + mockUserRepository.Setup(repo => repo.UpdateAsync(It.IsAny())) + .ThrowsAsync(new Exception("Database error")); + + // Act + var result = await handler.Handle(command, CancellationToken.None); + + // Assert + Assert.Equal(StatusCodes.Status500InternalServerError, result.StatusCode); + Assert.Equal("An error occurred while activating the user.", result.Message); + } +} \ No newline at end of file diff --git a/src/Hng.Application/Features/UserManagement/Commands/UserActivationCommand.cs b/src/Hng.Application/Features/UserManagement/Commands/UserActivationCommand.cs new file mode 100644 index 00000000..75240d8d --- /dev/null +++ b/src/Hng.Application/Features/UserManagement/Commands/UserActivationCommand.cs @@ -0,0 +1,10 @@ +using Hng.Application.Features.UserManagement.Dtos; +using MediatR; + +namespace Hng.Application.Features.UserManagement.Commands +{ + public class UserActivationCommand : IRequest + { + public Guid UserId { get; set; } + } +} diff --git a/src/Hng.Application/Features/UserManagement/Dtos/SignUpResponse.cs b/src/Hng.Application/Features/UserManagement/Dtos/SignUpResponse.cs index b2a60879..8e32dbff 100644 --- a/src/Hng.Application/Features/UserManagement/Dtos/SignUpResponse.cs +++ b/src/Hng.Application/Features/UserManagement/Dtos/SignUpResponse.cs @@ -24,4 +24,14 @@ public class SignupResponseData [JsonPropertyName("subscriptions")] public List Subscription { get; set; } = []; } + public class UserActivationResponse + { + [JsonPropertyName("message")] + public string Message { get; set; } + public SignupResponseData Data { get; set; } + [JsonPropertyName("access_token")] + public string Token { get; set; } + [JsonPropertyName("status_code")] + public int StatusCode { get; set; } + } } diff --git a/src/Hng.Application/Features/UserManagement/Handlers/LoginUserCommandHandler.cs b/src/Hng.Application/Features/UserManagement/Handlers/LoginUserCommandHandler.cs index 09c8a6da..581001cf 100644 --- a/src/Hng.Application/Features/UserManagement/Handlers/LoginUserCommandHandler.cs +++ b/src/Hng.Application/Features/UserManagement/Handlers/LoginUserCommandHandler.cs @@ -3,6 +3,7 @@ using Hng.Application.Features.UserManagement.Commands; using Hng.Application.Features.UserManagement.Dtos; using Hng.Domain.Entities; +using Hng.Domain.Enums; using Hng.Infrastructure.Repository.Interface; using Hng.Infrastructure.Services.Interfaces; using MediatR; @@ -56,6 +57,16 @@ public async Task> Handle(CreateUserLog StatusCode = StatusCodes.Status401Unauthorized }; } + if (user.UserStatus == UserStatus.deactivate) + { + return new UserLoginResponseDto + { + Data = null, + AccessToken = null, + Message = "User Deactivated", + StatusCode = StatusCodes.Status401Unauthorized + }; + } if (user.Status == "Inactive") { diff --git a/src/Hng.Application/Features/UserManagement/Handlers/UserActivationCommandHandler.cs b/src/Hng.Application/Features/UserManagement/Handlers/UserActivationCommandHandler.cs new file mode 100644 index 00000000..334b43f8 --- /dev/null +++ b/src/Hng.Application/Features/UserManagement/Handlers/UserActivationCommandHandler.cs @@ -0,0 +1,72 @@ +using AutoMapper; +using Hng.Application.Features.UserManagement.Commands; +using Hng.Application.Features.UserManagement.Dtos; +using Hng.Domain.Entities; +using Hng.Domain.Enums; +using Hng.Infrastructure.Repository.Interface; +using MediatR; +using Microsoft.AspNetCore.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Hng.Application.Features.UserManagement.Handlers; + +public class UserActivationCommandHandler : IRequestHandler +{ + private readonly IRepository _userRepository; + private readonly IMapper _mapper; + + public UserActivationCommandHandler(IRepository userRepository, IMapper mapper) + { + _userRepository = userRepository; + _mapper = mapper; + } + + public async Task Handle(UserActivationCommand request, CancellationToken cancellationToken) + { + var user = await _userRepository.GetBySpec(u => u.Id == request.UserId); + + if (user is null) + { + return new UserActivationResponse + { + Message = "User not found.", + StatusCode = StatusCodes.Status404NotFound + }; + } + + if (user.UserStatus == UserStatus.activate) + { + return new UserActivationResponse + { + Message = "User is already active.", + StatusCode = StatusCodes.Status400BadRequest + }; + } + + user.UserStatus = UserStatus.activate; + + try + { + await _userRepository.UpdateAsync(user); + await _userRepository.SaveChanges(); + + var userDto = _mapper.Map(user); + + return new UserActivationResponse + { + Message = "User activated successfully.", + StatusCode = StatusCodes.Status200OK, + }; + } + catch (Exception ex) + { + // Log the exception + return new UserActivationResponse + { + Message = "An error occurred while activating the user.", + StatusCode = StatusCodes.Status500InternalServerError + }; + } + } +} \ No newline at end of file diff --git a/src/Hng.Application/Features/UserManagement/Handlers/UserSignUpCommandHandler.cs b/src/Hng.Application/Features/UserManagement/Handlers/UserSignUpCommandHandler.cs index 833f8478..89ea8b64 100644 --- a/src/Hng.Application/Features/UserManagement/Handlers/UserSignUpCommandHandler.cs +++ b/src/Hng.Application/Features/UserManagement/Handlers/UserSignUpCommandHandler.cs @@ -51,6 +51,7 @@ public async Task Handle(UserSignUpCommand request, Cancellation var createdUser = _mapper.Map(request.SignUpBody); createdUser.Id = Guid.NewGuid(); + createdUser.UserStatus = UserStatus.activate; (createdUser.PasswordSalt, createdUser.Password) = _passwordService.GeneratePasswordSaltAndHash(request.SignUpBody.Password); var userOrg = new Organization diff --git a/src/Hng.Domain/Entities/User.cs b/src/Hng.Domain/Entities/User.cs index 53fc10f9..ef67ac18 100644 --- a/src/Hng.Domain/Entities/User.cs +++ b/src/Hng.Domain/Entities/User.cs @@ -1,3 +1,4 @@ +using Hng.Domain.Enums; using System.ComponentModel.DataAnnotations; namespace Hng.Domain.Entities; @@ -37,4 +38,5 @@ public class User : EntityBase public Timezone Timezone { get; set; } public Guid? LanguageId { get; set; } public Language Language { get; set; } + public UserStatus UserStatus { get; set; } } \ No newline at end of file diff --git a/src/Hng.Domain/Enums/UserStatus.cs b/src/Hng.Domain/Enums/UserStatus.cs new file mode 100644 index 00000000..41639797 --- /dev/null +++ b/src/Hng.Domain/Enums/UserStatus.cs @@ -0,0 +1,8 @@ +namespace Hng.Domain.Enums +{ + public enum UserStatus + { + activate, + deactivate + } +} diff --git a/src/Hng.Infrastructure/ConfigureInfrastructure.cs b/src/Hng.Infrastructure/ConfigureInfrastructure.cs index 14ca8a65..e79478cd 100644 --- a/src/Hng.Infrastructure/ConfigureInfrastructure.cs +++ b/src/Hng.Infrastructure/ConfigureInfrastructure.cs @@ -29,10 +29,10 @@ public static IServiceCollection AddInfrastructureConfig(this IServiceCollection services.AddScoped(); services.AddScoped(); services.AddSingleton(sp => - { - var Configuration = ConfigurationOptions.Parse(redisConnectionString, true); - return ConnectionMultiplexer.Connect(Configuration); - }); + { + var Configuration = ConfigurationOptions.Parse(redisConnectionString, true); + return ConnectionMultiplexer.Connect(Configuration); + }); return services; } } diff --git a/src/Hng.Infrastructure/Migrations/20250227113921_first.Designer.cs b/src/Hng.Infrastructure/Migrations/20250227113921_first.Designer.cs new file mode 100644 index 00000000..70a6e9ff --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250227113921_first.Designer.cs @@ -0,0 +1,1302 @@ +// +using System; +using Hng.Infrastructure.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250227113921_first")] + partial class first + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hng.Domain.Entities.ApiStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApiGroup") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Details") + .HasColumnType("text"); + + b.Property("LastChecked") + .HasColumnType("timestamp with time zone"); + + b.Property("ResponseTime") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ApiStatuses"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.BillingPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Frequency") + .HasColumnType("integer"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("BillingPlans"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("Category") + .HasColumnType("integer"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("PublishedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("BlogId") + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("BlogId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.ContactUs", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ContactUs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PlaceHolders") + .HasColumnType("jsonb"); + + b.Property("Subject") + .HasColumnType("text"); + + b.Property("TemplateBody") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Faq", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Answer") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Question") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("FAQ"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.HelpCenterTopic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Author") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HelpCenterTopic"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Company") + .HasColumnType("text"); + + b.Property("DatePosted") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Location") + .HasColumnType("text"); + + b.Property("Salary") + .HasColumnType("double precision"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Jobs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Languages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IPAddress") + .HasColumnType("text"); + + b.Property("LoginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LogoutTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("LastLogins"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastAttemptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RecipientContact") + .IsRequired() + .HasColumnType("text"); + + b.Property("RecipientName") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NewsLetterSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("LeftOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.ToTable("NewsLetterSubscribers"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActivityWorkspaceEmail") + .HasColumnType("boolean"); + + b.Property("ActivityWorkspaceSlack") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateEmails") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateSlack") + .HasColumnType("boolean"); + + b.Property("EmailDigests") + .HasColumnType("boolean"); + + b.Property("EmailNotifications") + .HasColumnType("boolean"); + + b.Property("MobilePushNotifications") + .HasColumnType("boolean"); + + b.Property("SlackNotifications") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSettings"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Industry") + .HasColumnType("text"); + + b.Property("InviteToken") + .HasColumnType("uuid"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Organizations"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.OrganizationInvite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AcceptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("InviteCode") + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("InviteCode"); + + b.ToTable("OrganizationInvites"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Available") + .HasColumnType("boolean"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Size") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("Bio") + .HasColumnType("text"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("FacebookLink") + .HasColumnType("text"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("InstagramLink") + .HasColumnType("text"); + + b.Property("JobTitle") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LinkedinLink") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("Pronoun") + .HasColumnType("text"); + + b.Property("TwitterLink") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Profiles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.RolePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BillingPlanId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Frequency") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Plan") + .IsRequired() + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TransactionId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BillingPlanId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("TransactionId"); + + b.HasIndex("UserId"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Timezone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GmtOffset") + .HasColumnType("text"); + + b.Property("TimezoneValue") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Timezones"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PaidAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Partners") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("Reference") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubscriptionId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("Reference"); + + b.HasIndex("SubscriptionId"); + + b.HasIndex("UserId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsSuperAdmin") + .HasColumnType("boolean"); + + b.Property("LanguageId") + .HasColumnType("uuid"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordResetToken") + .HasColumnType("text"); + + b.Property("PasswordResetTokenTime") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TimezoneId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("LanguageId"); + + b.HasIndex("TimezoneId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "UserId", "RoleId") + .IsUnique(); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Waitlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Waitlists"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.Property("OrganizationsId") + .HasColumnType("uuid"); + + b.Property("UsersId") + .HasColumnType("uuid"); + + b.HasKey("OrganizationsId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("OrganizationUser"); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.Property("PermissionsId") + .HasColumnType("uuid"); + + b.Property("RolesId") + .HasColumnType("uuid"); + + b.HasKey("PermissionsId", "RolesId"); + + b.HasIndex("RolesId"); + + b.ToTable("RoleRolePermission"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany("Blogs") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Blog", "Blog") + .WithMany("Comments") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("LastLogins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.HasOne("Hng.Domain.Entities.Category", null) + .WithMany("Products") + .HasForeignKey("CategoryId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Products") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithOne("Profile") + .HasForeignKey("Hng.Domain.Entities.Profile", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Organisation") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organisation"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.HasOne("Hng.Domain.Entities.BillingPlan", "BillingPlan") + .WithMany() + .HasForeignKey("BillingPlanId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany("Subscriptions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Hng.Domain.Entities.Transaction", "Transaction") + .WithMany() + .HasForeignKey("TransactionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Subscriptions") + .HasForeignKey("UserId"); + + b.Navigation("BillingPlan"); + + b.Navigation("Organization"); + + b.Navigation("Transaction"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.HasOne("Hng.Domain.Entities.Product", "Product") + .WithMany("Transactions") + .HasForeignKey("ProductId"); + + b.HasOne("Hng.Domain.Entities.Subscription", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Product"); + + b.Navigation("Subscription"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.HasOne("Hng.Domain.Entities.Language", "Language") + .WithMany("Users") + .HasForeignKey("LanguageId"); + + b.HasOne("Hng.Domain.Entities.Timezone", "Timezone") + .WithMany() + .HasForeignKey("TimezoneId"); + + b.Navigation("Language"); + + b.Navigation("Timezone"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Orgainzation") + .WithMany("UsersRoles") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", "Role") + .WithMany("UsersRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("UsersRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Orgainzation"); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.HasOne("Hng.Domain.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.HasOne("Hng.Domain.Entities.RolePermission", null) + .WithMany() + .HasForeignKey("PermissionsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", null) + .WithMany() + .HasForeignKey("RolesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Navigation("Subscriptions"); + + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Navigation("Blogs"); + + b.Navigation("LastLogins"); + + b.Navigation("Products"); + + b.Navigation("Profile"); + + b.Navigation("Subscriptions"); + + b.Navigation("Transactions"); + + b.Navigation("UsersRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250227113921_first.cs b/src/Hng.Infrastructure/Migrations/20250227113921_first.cs new file mode 100644 index 00000000..ba8502e9 --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250227113921_first.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + /// + public partial class first : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250227115421_second.Designer.cs b/src/Hng.Infrastructure/Migrations/20250227115421_second.Designer.cs new file mode 100644 index 00000000..be6a64bc --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250227115421_second.Designer.cs @@ -0,0 +1,1302 @@ +// +using System; +using Hng.Infrastructure.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250227115421_second")] + partial class second + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hng.Domain.Entities.ApiStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApiGroup") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Details") + .HasColumnType("text"); + + b.Property("LastChecked") + .HasColumnType("timestamp with time zone"); + + b.Property("ResponseTime") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ApiStatuses"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.BillingPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Frequency") + .HasColumnType("integer"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("BillingPlans"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("Category") + .HasColumnType("integer"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("PublishedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("BlogId") + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("BlogId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.ContactUs", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ContactUs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PlaceHolders") + .HasColumnType("jsonb"); + + b.Property("Subject") + .HasColumnType("text"); + + b.Property("TemplateBody") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Faq", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Answer") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Question") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("FAQ"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.HelpCenterTopic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Author") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HelpCenterTopic"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Company") + .HasColumnType("text"); + + b.Property("DatePosted") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Location") + .HasColumnType("text"); + + b.Property("Salary") + .HasColumnType("double precision"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Jobs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Languages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IPAddress") + .HasColumnType("text"); + + b.Property("LoginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LogoutTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("LastLogins"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastAttemptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RecipientContact") + .IsRequired() + .HasColumnType("text"); + + b.Property("RecipientName") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NewsLetterSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("LeftOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.ToTable("NewsLetterSubscribers"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActivityWorkspaceEmail") + .HasColumnType("boolean"); + + b.Property("ActivityWorkspaceSlack") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateEmails") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateSlack") + .HasColumnType("boolean"); + + b.Property("EmailDigests") + .HasColumnType("boolean"); + + b.Property("EmailNotifications") + .HasColumnType("boolean"); + + b.Property("MobilePushNotifications") + .HasColumnType("boolean"); + + b.Property("SlackNotifications") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSettings"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Industry") + .HasColumnType("text"); + + b.Property("InviteToken") + .HasColumnType("uuid"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Organizations"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.OrganizationInvite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AcceptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("InviteCode") + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("InviteCode"); + + b.ToTable("OrganizationInvites"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Available") + .HasColumnType("boolean"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Size") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("Bio") + .HasColumnType("text"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("FacebookLink") + .HasColumnType("text"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("InstagramLink") + .HasColumnType("text"); + + b.Property("JobTitle") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LinkedinLink") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("Pronoun") + .HasColumnType("text"); + + b.Property("TwitterLink") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Profiles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.RolePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BillingPlanId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Frequency") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Plan") + .IsRequired() + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TransactionId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BillingPlanId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("TransactionId"); + + b.HasIndex("UserId"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Timezone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GmtOffset") + .HasColumnType("text"); + + b.Property("TimezoneValue") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Timezones"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PaidAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Partners") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("Reference") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubscriptionId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("Reference"); + + b.HasIndex("SubscriptionId"); + + b.HasIndex("UserId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsSuperAdmin") + .HasColumnType("boolean"); + + b.Property("LanguageId") + .HasColumnType("uuid"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordResetToken") + .HasColumnType("text"); + + b.Property("PasswordResetTokenTime") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TimezoneId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("LanguageId"); + + b.HasIndex("TimezoneId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "UserId", "RoleId") + .IsUnique(); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Waitlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Waitlists"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.Property("OrganizationsId") + .HasColumnType("uuid"); + + b.Property("UsersId") + .HasColumnType("uuid"); + + b.HasKey("OrganizationsId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("OrganizationUser"); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.Property("PermissionsId") + .HasColumnType("uuid"); + + b.Property("RolesId") + .HasColumnType("uuid"); + + b.HasKey("PermissionsId", "RolesId"); + + b.HasIndex("RolesId"); + + b.ToTable("RoleRolePermission"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany("Blogs") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Blog", "Blog") + .WithMany("Comments") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("LastLogins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.HasOne("Hng.Domain.Entities.Category", null) + .WithMany("Products") + .HasForeignKey("CategoryId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Products") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithOne("Profile") + .HasForeignKey("Hng.Domain.Entities.Profile", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Organisation") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organisation"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.HasOne("Hng.Domain.Entities.BillingPlan", "BillingPlan") + .WithMany() + .HasForeignKey("BillingPlanId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany("Subscriptions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Hng.Domain.Entities.Transaction", "Transaction") + .WithMany() + .HasForeignKey("TransactionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Subscriptions") + .HasForeignKey("UserId"); + + b.Navigation("BillingPlan"); + + b.Navigation("Organization"); + + b.Navigation("Transaction"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.HasOne("Hng.Domain.Entities.Product", "Product") + .WithMany("Transactions") + .HasForeignKey("ProductId"); + + b.HasOne("Hng.Domain.Entities.Subscription", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Product"); + + b.Navigation("Subscription"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.HasOne("Hng.Domain.Entities.Language", "Language") + .WithMany("Users") + .HasForeignKey("LanguageId"); + + b.HasOne("Hng.Domain.Entities.Timezone", "Timezone") + .WithMany() + .HasForeignKey("TimezoneId"); + + b.Navigation("Language"); + + b.Navigation("Timezone"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Orgainzation") + .WithMany("UsersRoles") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", "Role") + .WithMany("UsersRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("UsersRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Orgainzation"); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.HasOne("Hng.Domain.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.HasOne("Hng.Domain.Entities.RolePermission", null) + .WithMany() + .HasForeignKey("PermissionsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", null) + .WithMany() + .HasForeignKey("RolesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Navigation("Subscriptions"); + + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Navigation("Blogs"); + + b.Navigation("LastLogins"); + + b.Navigation("Products"); + + b.Navigation("Profile"); + + b.Navigation("Subscriptions"); + + b.Navigation("Transactions"); + + b.Navigation("UsersRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250227115421_second.cs b/src/Hng.Infrastructure/Migrations/20250227115421_second.cs new file mode 100644 index 00000000..c9053c24 --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250227115421_second.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + /// + public partial class second : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250228181221_secon.Designer.cs b/src/Hng.Infrastructure/Migrations/20250228181221_secon.Designer.cs new file mode 100644 index 00000000..3b23d057 --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250228181221_secon.Designer.cs @@ -0,0 +1,1302 @@ +// +using System; +using Hng.Infrastructure.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250228181221_secon")] + partial class secon + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hng.Domain.Entities.ApiStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApiGroup") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Details") + .HasColumnType("text"); + + b.Property("LastChecked") + .HasColumnType("timestamp with time zone"); + + b.Property("ResponseTime") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ApiStatuses"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.BillingPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Frequency") + .HasColumnType("integer"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("BillingPlans"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("Category") + .HasColumnType("integer"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("PublishedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("BlogId") + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("BlogId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.ContactUs", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ContactUs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PlaceHolders") + .HasColumnType("jsonb"); + + b.Property("Subject") + .HasColumnType("text"); + + b.Property("TemplateBody") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Faq", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Answer") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Question") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("FAQ"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.HelpCenterTopic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Author") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HelpCenterTopic"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Company") + .HasColumnType("text"); + + b.Property("DatePosted") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Location") + .HasColumnType("text"); + + b.Property("Salary") + .HasColumnType("double precision"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Jobs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Languages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IPAddress") + .HasColumnType("text"); + + b.Property("LoginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LogoutTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("LastLogins"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastAttemptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RecipientContact") + .IsRequired() + .HasColumnType("text"); + + b.Property("RecipientName") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NewsLetterSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("LeftOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.ToTable("NewsLetterSubscribers"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActivityWorkspaceEmail") + .HasColumnType("boolean"); + + b.Property("ActivityWorkspaceSlack") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateEmails") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateSlack") + .HasColumnType("boolean"); + + b.Property("EmailDigests") + .HasColumnType("boolean"); + + b.Property("EmailNotifications") + .HasColumnType("boolean"); + + b.Property("MobilePushNotifications") + .HasColumnType("boolean"); + + b.Property("SlackNotifications") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSettings"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Industry") + .HasColumnType("text"); + + b.Property("InviteToken") + .HasColumnType("uuid"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Organizations"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.OrganizationInvite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AcceptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("InviteCode") + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("InviteCode"); + + b.ToTable("OrganizationInvites"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Available") + .HasColumnType("boolean"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Size") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("Bio") + .HasColumnType("text"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("FacebookLink") + .HasColumnType("text"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("InstagramLink") + .HasColumnType("text"); + + b.Property("JobTitle") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LinkedinLink") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("Pronoun") + .HasColumnType("text"); + + b.Property("TwitterLink") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Profiles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.RolePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BillingPlanId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Frequency") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Plan") + .IsRequired() + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TransactionId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BillingPlanId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("TransactionId"); + + b.HasIndex("UserId"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Timezone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GmtOffset") + .HasColumnType("text"); + + b.Property("TimezoneValue") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Timezones"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PaidAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Partners") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("Reference") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubscriptionId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("Reference"); + + b.HasIndex("SubscriptionId"); + + b.HasIndex("UserId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsSuperAdmin") + .HasColumnType("boolean"); + + b.Property("LanguageId") + .HasColumnType("uuid"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordResetToken") + .HasColumnType("text"); + + b.Property("PasswordResetTokenTime") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TimezoneId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("LanguageId"); + + b.HasIndex("TimezoneId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "UserId", "RoleId") + .IsUnique(); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Waitlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Waitlists"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.Property("OrganizationsId") + .HasColumnType("uuid"); + + b.Property("UsersId") + .HasColumnType("uuid"); + + b.HasKey("OrganizationsId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("OrganizationUser"); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.Property("PermissionsId") + .HasColumnType("uuid"); + + b.Property("RolesId") + .HasColumnType("uuid"); + + b.HasKey("PermissionsId", "RolesId"); + + b.HasIndex("RolesId"); + + b.ToTable("RoleRolePermission"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany("Blogs") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Blog", "Blog") + .WithMany("Comments") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("LastLogins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.HasOne("Hng.Domain.Entities.Category", null) + .WithMany("Products") + .HasForeignKey("CategoryId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Products") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithOne("Profile") + .HasForeignKey("Hng.Domain.Entities.Profile", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Organisation") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organisation"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.HasOne("Hng.Domain.Entities.BillingPlan", "BillingPlan") + .WithMany() + .HasForeignKey("BillingPlanId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany("Subscriptions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Hng.Domain.Entities.Transaction", "Transaction") + .WithMany() + .HasForeignKey("TransactionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Subscriptions") + .HasForeignKey("UserId"); + + b.Navigation("BillingPlan"); + + b.Navigation("Organization"); + + b.Navigation("Transaction"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.HasOne("Hng.Domain.Entities.Product", "Product") + .WithMany("Transactions") + .HasForeignKey("ProductId"); + + b.HasOne("Hng.Domain.Entities.Subscription", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Product"); + + b.Navigation("Subscription"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.HasOne("Hng.Domain.Entities.Language", "Language") + .WithMany("Users") + .HasForeignKey("LanguageId"); + + b.HasOne("Hng.Domain.Entities.Timezone", "Timezone") + .WithMany() + .HasForeignKey("TimezoneId"); + + b.Navigation("Language"); + + b.Navigation("Timezone"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Orgainzation") + .WithMany("UsersRoles") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", "Role") + .WithMany("UsersRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("UsersRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Orgainzation"); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.HasOne("Hng.Domain.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.HasOne("Hng.Domain.Entities.RolePermission", null) + .WithMany() + .HasForeignKey("PermissionsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", null) + .WithMany() + .HasForeignKey("RolesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Navigation("Subscriptions"); + + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Navigation("Blogs"); + + b.Navigation("LastLogins"); + + b.Navigation("Products"); + + b.Navigation("Profile"); + + b.Navigation("Subscriptions"); + + b.Navigation("Transactions"); + + b.Navigation("UsersRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250228181221_secon.cs b/src/Hng.Infrastructure/Migrations/20250228181221_secon.cs new file mode 100644 index 00000000..ae57b379 --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250228181221_secon.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + /// + public partial class secon : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250228203150_seco.Designer.cs b/src/Hng.Infrastructure/Migrations/20250228203150_seco.Designer.cs new file mode 100644 index 00000000..463cfc3a --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250228203150_seco.Designer.cs @@ -0,0 +1,1305 @@ +// +using System; +using Hng.Infrastructure.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250228203150_seco")] + partial class seco + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Hng.Domain.Entities.ApiStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApiGroup") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Details") + .HasColumnType("text"); + + b.Property("LastChecked") + .HasColumnType("timestamp with time zone"); + + b.Property("ResponseTime") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ApiStatuses"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.BillingPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Frequency") + .HasColumnType("integer"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("BillingPlans"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("Category") + .HasColumnType("integer"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("PublishedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("BlogId") + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("BlogId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.ContactUs", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ContactUs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PlaceHolders") + .HasColumnType("jsonb"); + + b.Property("Subject") + .HasColumnType("text"); + + b.Property("TemplateBody") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Faq", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Answer") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Question") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("FAQ"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.HelpCenterTopic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Author") + .HasColumnType("text"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("HelpCenterTopic"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Company") + .HasColumnType("text"); + + b.Property("DatePosted") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("Location") + .HasColumnType("text"); + + b.Property("Salary") + .HasColumnType("double precision"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Jobs"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Languages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IPAddress") + .HasColumnType("text"); + + b.Property("LoginTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LogoutTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("LastLogins"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastAttemptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RecipientContact") + .IsRequired() + .HasColumnType("text"); + + b.Property("RecipientName") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NewsLetterSubscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("LeftOn") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.ToTable("NewsLetterSubscribers"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActivityWorkspaceEmail") + .HasColumnType("boolean"); + + b.Property("ActivityWorkspaceSlack") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateEmails") + .HasColumnType("boolean"); + + b.Property("AnnouncementsUpdateSlack") + .HasColumnType("boolean"); + + b.Property("EmailDigests") + .HasColumnType("boolean"); + + b.Property("EmailNotifications") + .HasColumnType("boolean"); + + b.Property("MobilePushNotifications") + .HasColumnType("boolean"); + + b.Property("SlackNotifications") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSettings"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Industry") + .HasColumnType("text"); + + b.Property("InviteToken") + .HasColumnType("uuid"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Organizations"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.OrganizationInvite", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AcceptedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("InviteCode") + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("InviteCode"); + + b.ToTable("OrganizationInvites"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Available") + .HasColumnType("boolean"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ImageUrl") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Size") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("Bio") + .HasColumnType("text"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("FacebookLink") + .HasColumnType("text"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("InstagramLink") + .HasColumnType("text"); + + b.Property("JobTitle") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LinkedinLink") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("Pronoun") + .HasColumnType("text"); + + b.Property("TwitterLink") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Profiles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.RolePermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BillingPlanId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Frequency") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Plan") + .IsRequired() + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("TransactionId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("BillingPlanId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("TransactionId"); + + b.HasIndex("UserId"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Timezone", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GmtOffset") + .HasColumnType("text"); + + b.Property("TimezoneValue") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Timezones"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PaidAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Partners") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("Reference") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubscriptionId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("Reference"); + + b.HasIndex("SubscriptionId"); + + b.HasIndex("UserId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsSuperAdmin") + .HasColumnType("boolean"); + + b.Property("LanguageId") + .HasColumnType("uuid"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Password") + .HasColumnType("text"); + + b.Property("PasswordResetToken") + .HasColumnType("text"); + + b.Property("PasswordResetTokenTime") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordSalt") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TimezoneId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserStatus") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("LanguageId"); + + b.HasIndex("TimezoneId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "UserId", "RoleId") + .IsUnique(); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Waitlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Waitlists"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.Property("OrganizationsId") + .HasColumnType("uuid"); + + b.Property("UsersId") + .HasColumnType("uuid"); + + b.HasKey("OrganizationsId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("OrganizationUser"); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.Property("PermissionsId") + .HasColumnType("uuid"); + + b.Property("RolesId") + .HasColumnType("uuid"); + + b.HasKey("PermissionsId", "RolesId"); + + b.HasIndex("RolesId"); + + b.ToTable("RoleRolePermission"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany("Blogs") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Comment", b => + { + b.HasOne("Hng.Domain.Entities.User", "Author") + .WithMany() + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Blog", "Blog") + .WithMany("Comments") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.LastLogin", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("LastLogins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Notification", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.NotificationSettings", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.HasOne("Hng.Domain.Entities.Category", null) + .WithMany("Products") + .HasForeignKey("CategoryId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Products") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Profile", b => + { + b.HasOne("Hng.Domain.Entities.User", "User") + .WithOne("Profile") + .HasForeignKey("Hng.Domain.Entities.Profile", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Organisation") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organisation"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Subscription", b => + { + b.HasOne("Hng.Domain.Entities.BillingPlan", "BillingPlan") + .WithMany() + .HasForeignKey("BillingPlanId"); + + b.HasOne("Hng.Domain.Entities.Organization", "Organization") + .WithMany("Subscriptions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Hng.Domain.Entities.Transaction", "Transaction") + .WithMany() + .HasForeignKey("TransactionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Subscriptions") + .HasForeignKey("UserId"); + + b.Navigation("BillingPlan"); + + b.Navigation("Organization"); + + b.Navigation("Transaction"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Transaction", b => + { + b.HasOne("Hng.Domain.Entities.Product", "Product") + .WithMany("Transactions") + .HasForeignKey("ProductId"); + + b.HasOne("Hng.Domain.Entities.Subscription", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Product"); + + b.Navigation("Subscription"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.HasOne("Hng.Domain.Entities.Language", "Language") + .WithMany("Users") + .HasForeignKey("LanguageId"); + + b.HasOne("Hng.Domain.Entities.Timezone", "Timezone") + .WithMany() + .HasForeignKey("TimezoneId"); + + b.Navigation("Language"); + + b.Navigation("Timezone"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.UserRole", b => + { + b.HasOne("Hng.Domain.Entities.Organization", "Orgainzation") + .WithMany("UsersRoles") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", "Role") + .WithMany("UsersRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", "User") + .WithMany("UsersRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Orgainzation"); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("OrganizationUser", b => + { + b.HasOne("Hng.Domain.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("RoleRolePermission", b => + { + b.HasOne("Hng.Domain.Entities.RolePermission", null) + .WithMany() + .HasForeignKey("PermissionsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Hng.Domain.Entities.Role", null) + .WithMany() + .HasForeignKey("RolesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Blog", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Category", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Language", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Organization", b => + { + b.Navigation("Subscriptions"); + + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Product", b => + { + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.Role", b => + { + b.Navigation("UsersRoles"); + }); + + modelBuilder.Entity("Hng.Domain.Entities.User", b => + { + b.Navigation("Blogs"); + + b.Navigation("LastLogins"); + + b.Navigation("Products"); + + b.Navigation("Profile"); + + b.Navigation("Subscriptions"); + + b.Navigation("Transactions"); + + b.Navigation("UsersRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/20250228203150_seco.cs b/src/Hng.Infrastructure/Migrations/20250228203150_seco.cs new file mode 100644 index 00000000..06a4bbfd --- /dev/null +++ b/src/Hng.Infrastructure/Migrations/20250228203150_seco.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Hng.Infrastructure.Migrations +{ + /// + public partial class seco : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UserStatus", + table: "Users", + type: "integer", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UserStatus", + table: "Users"); + } + } +} diff --git a/src/Hng.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Hng.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index dc951645..728dda1e 100644 --- a/src/Hng.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Hng.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -937,6 +937,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); + b.Property("UserStatus") + .HasColumnType("integer"); + b.HasKey("Id"); b.HasIndex("LanguageId"); diff --git a/src/Hng.Web/Controllers/AdminController.cs b/src/Hng.Web/Controllers/AdminController.cs index 163c5d6b..fcc80653 100644 --- a/src/Hng.Web/Controllers/AdminController.cs +++ b/src/Hng.Web/Controllers/AdminController.cs @@ -1,5 +1,8 @@ using Hng.Application.Features.SuperAdmin.Dto; using Hng.Application.Features.SuperAdmin.Queries; +using Hng.Application.Features.UserManagement.Commands; +using Hng.Application.Features.UserManagement.Dtos; +using Hng.Application.Features.UserManagement.Queries; using Hng.Application.Shared.Dtos; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -29,5 +32,19 @@ public async Task GetUsersBySearch([FromQuery] UsersQueryParameter var users = await _mediator.Send(new GetUsersBySearchQuery(parameters)); return Ok(new PaginatedResponseDto> { Data = users, Metadata = users.MetaData }); } + + [HttpPut("users/{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task ActivateUser(Guid id) + { + var command = new UserActivationCommand + { + UserId = id, + + }; + + var response = await _mediator.Send(command); + return Ok(response); + } } } diff --git a/src/Hng.Web/Program.cs b/src/Hng.Web/Program.cs index 58b04200..3e61db4d 100644 --- a/src/Hng.Web/Program.cs +++ b/src/Hng.Web/Program.cs @@ -32,12 +32,12 @@ }; }); +builder.Services.AddApplicationConfig(builder.Configuration); +builder.Services.AddInfrastructureConfig(builder.Configuration.GetConnectionString("DefaultConnectionString"), builder.Configuration.GetConnectionString("RedisConnectionString")); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerDocs(); -builder.Services.AddApplicationConfig(builder.Configuration); builder.Services.AddGraphql(); -builder.Services.AddInfrastructureConfig(builder.Configuration.GetConnectionString("DefaultConnectionString"), builder.Configuration.GetConnectionString("RedisConnectionString")); builder.Services.AddSwaggerGen(c => { c.SchemaFilter();