diff --git a/Directory.Packages.props b/Directory.Packages.props index 5430aaa0d..0b6a6c417 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,6 +36,7 @@ + diff --git a/src/DevBetterWeb.Core/Entities/Member.cs b/src/DevBetterWeb.Core/Entities/Member.cs index 2b0549ca1..5598ee5e2 100644 --- a/src/DevBetterWeb.Core/Entities/Member.cs +++ b/src/DevBetterWeb.Core/Entities/Member.cs @@ -44,7 +44,6 @@ internal Member(string userId, string firstName, string lastName) public string? LastName { get; private set; } public Birthday? Birthday { get; private set; } public string? AboutInfo { get; private set; } - public string? Address { get; private set; } public Address? ShippingAddress { get; private set; } public Geolocation? CityLocation { get; private set; } @@ -64,6 +63,9 @@ internal Member(string userId, string firstName, string lastName) public string? DiscordUsername { get; private set; } public string? MastodonUrl { get; private set; } // added and deployed 5 Jan 2022 but site broke + private readonly List _addressHistory = new(); + public IReadOnlyList AddressHistory => _addressHistory.AsReadOnly(); + public List BooksRead { get; set; } = new List(); public List UploadedBooks { get; set; } = new List(); public List MemberVideosProgress { get; set; } = new List(); @@ -123,21 +125,6 @@ public void UpdateName(string? firstName, string? lastName, bool isEvent = true) } } - public void UpdateAddress(string? address, bool isEvent = true) - { - var isUpdate = false; - if (Address != address) - { - Address = address; - isUpdate = true; - } - - if (isEvent && isUpdate) - { - CreateOrUpdateAddressUpdateEvent(nameof(Address)); - } - } - public void UpdateBirthday(int? day, int? month, bool isEvent = true) { if (day == Birthday?.Day && month == Birthday?.Month) return; @@ -197,10 +184,15 @@ public void UpdateShippingAddress(string street, string city, string state, stri isUpdated = ShippingAddress.Update(street, city, state, postalCode, country); } - if (isEvent && isUpdated) + if (isUpdated) { - var addressUpdatedEvent = new MemberAddressUpdatedEvent(this, ShippingAddress); - Events.Add(addressUpdatedEvent); + _addressHistory.Add(new MemberAddressHistory(Id, ShippingAddress)); + + if (isEvent) + { + var addressUpdatedEvent = new MemberAddressUpdatedEvent(this, ShippingAddress); + Events.Add(addressUpdatedEvent); + } } } diff --git a/src/DevBetterWeb.Core/Entities/MemberAddressHistory.cs b/src/DevBetterWeb.Core/Entities/MemberAddressHistory.cs new file mode 100644 index 000000000..55a37d1a4 --- /dev/null +++ b/src/DevBetterWeb.Core/Entities/MemberAddressHistory.cs @@ -0,0 +1,24 @@ +using System; +using DevBetterWeb.Core.Interfaces; +using DevBetterWeb.Core.SharedKernel; +using DevBetterWeb.Core.ValueObjects; + +namespace DevBetterWeb.Core.Entities; +public class MemberAddressHistory : BaseEntity, IAggregateRoot +{ + public int MemberId { get; private set; } + public Address? Address { get; private set; } + public DateTimeOffset UpdatedOn { get; private set; } + + public MemberAddressHistory(int memberId, Address address) + { + MemberId = memberId; + Address = address; + UpdatedOn = DateTime.UtcNow; + } + + private MemberAddressHistory() + { + // EF + } +} diff --git a/src/DevBetterWeb.Core/Specs/MemberByUserIdSpec.cs b/src/DevBetterWeb.Core/Specs/MemberByUserIdSpec.cs index 52de19856..e8a1c2b4a 100644 --- a/src/DevBetterWeb.Core/Specs/MemberByUserIdSpec.cs +++ b/src/DevBetterWeb.Core/Specs/MemberByUserIdSpec.cs @@ -3,11 +3,13 @@ namespace DevBetterWeb.Core.Specs; -public class MemberByUserIdSpec : Specification, +public sealed class MemberByUserIdSpec : Specification, ISingleResultSpecification { public MemberByUserIdSpec(string userId) { - Query.Where(member => member.UserId == userId); + Query + .Include(member => member.AddressHistory) + .Where(member => member.UserId == userId); } } diff --git a/src/DevBetterWeb.Core/ValueObjects/Address.cs b/src/DevBetterWeb.Core/ValueObjects/Address.cs index 1afd510c9..347c71c07 100644 --- a/src/DevBetterWeb.Core/ValueObjects/Address.cs +++ b/src/DevBetterWeb.Core/ValueObjects/Address.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Metrics; using CSharpFunctionalExtensions; namespace DevBetterWeb.Core.ValueObjects; @@ -87,4 +86,9 @@ public bool Update(string street, string city, string state, string postalCode, return isUpdated; } + + public override string ToString() + { + return $"{Street}, {City}, {State} {PostalCode}, {Country}"; + } } diff --git a/src/DevBetterWeb.Infrastructure/Data/Config/MemberAddressHistoryConfig.cs b/src/DevBetterWeb.Infrastructure/Data/Config/MemberAddressHistoryConfig.cs new file mode 100644 index 000000000..06741f50f --- /dev/null +++ b/src/DevBetterWeb.Infrastructure/Data/Config/MemberAddressHistoryConfig.cs @@ -0,0 +1,23 @@ +using DevBetterWeb.Core.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace DevBetterWeb.Infrastructure.Data.Config; + +public class MemberAddressHistoryConfig : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.Property(i => i.MemberId).IsRequired(); + builder.Property(i => i.UpdatedOn).IsRequired(); + + builder.OwnsOne(x => x.Address, sa => + { + sa.Property(p => p!.Street).HasMaxLength(500).HasDefaultValue(""); + sa.Property(p => p!.City).HasMaxLength(DataConfigConstants.NAME_COLUMN_WIDTH).HasDefaultValue(""); + sa.Property(p => p!.State).HasMaxLength(DataConfigConstants.NAME_COLUMN_WIDTH).HasDefaultValue(""); + sa.Property(p => p!.PostalCode).HasMaxLength(12).HasDefaultValue(""); + sa.Property(p => p!.Country).HasMaxLength(DataConfigConstants.NAME_COLUMN_WIDTH).HasDefaultValue(""); + }); + } +} diff --git a/src/DevBetterWeb.Infrastructure/Data/Config/MemberConfig.cs b/src/DevBetterWeb.Infrastructure/Data/Config/MemberConfig.cs index 5f0a1469d..d271277e1 100644 --- a/src/DevBetterWeb.Infrastructure/Data/Config/MemberConfig.cs +++ b/src/DevBetterWeb.Infrastructure/Data/Config/MemberConfig.cs @@ -10,7 +10,6 @@ public class MemberConfig : IEntityTypeConfiguration public void Configure(EntityTypeBuilder builder) { builder.Property(x => x.UserId).HasMaxLength(500); - builder.Property(x => x.Address).HasMaxLength(500); builder.Property(x => x.BlogUrl).HasMaxLength(DataConfigConstants.URL_COLUMN_WIDTH); builder.Property(x => x.CodinGameUrl).HasMaxLength(DataConfigConstants.URL_COLUMN_WIDTH); builder.Property(x => x.GitHubUrl).HasMaxLength(DataConfigConstants.URL_COLUMN_WIDTH); @@ -49,5 +48,10 @@ public void Configure(EntityTypeBuilder builder) }); builder.HasMany(x => x.FavoriteArchiveVideos); - } + + builder.HasMany(x => x.AddressHistory) + .WithOne() + .HasForeignKey(ah => ah.MemberId) + .OnDelete(DeleteBehavior.Cascade); + } } diff --git a/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730190343_AddressRemoved.Designer.cs b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730190343_AddressRemoved.Designer.cs new file mode 100644 index 000000000..686459e27 --- /dev/null +++ b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730190343_AddressRemoved.Designer.cs @@ -0,0 +1,945 @@ +// +using System; +using DevBetterWeb.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace DevBetterWeb.Infrastructure.Data.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20240730190343_AddressRemoved")] + partial class AddressRemoved + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BookMember", b => + { + b.Property("BooksReadId") + .HasColumnType("int"); + + b.Property("MembersWhoHaveReadId") + .HasColumnType("int"); + + b.HasKey("BooksReadId", "MembersWhoHaveReadId"); + + b.HasIndex("MembersWhoHaveReadId"); + + b.ToTable("BookMember"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AnimatedThumbnailUri") + .HasColumnType("nvarchar(max)"); + + b.Property("DateCreated") + .HasColumnType("datetimeoffset"); + + b.Property("DateUploaded") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Duration") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("VideoId") + .HasColumnType("nvarchar(max)"); + + b.Property("VideoUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ArchiveVideos"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasMaxLength(500) + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.ToTable("BillingActivities"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("BookCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(1); + + b.Property("Details") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("MemberWhoUploadId") + .HasColumnType("int"); + + b.Property("PurchaseUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Title") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("BookCategoryId"); + + b.HasIndex("MemberWhoUploadId"); + + b.ToTable("Books"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Title") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.ToTable("BookCategories"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("StartAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("CoachingSessions", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.DailyCheck", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.Property("TasksCompleted") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.ToTable("DailyChecks"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Invitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Active") + .HasColumnType("bit"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateOfLastAdminPing") + .HasColumnType("datetime2"); + + b.Property("DateOfUserPing") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("InviteCode") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("PaymentHandlerSubscriptionId") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.ToTable("Invitations"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AboutInfo") + .HasColumnType("nvarchar(max)"); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("BlueskyUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CityLatitude") + .HasColumnType("decimal(18,2)"); + + b.Property("CityLongitude") + .HasColumnType("decimal(18,2)"); + + b.Property("CodinGameUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DiscordUsername") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("GitHubUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("LastName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("LinkedInUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("MastodonUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OtherUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PEFriendCode") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("PEUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("TwitchUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("TwitterUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("YouTubeUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Members"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("MemberSubscriptionPlanId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.ToTable("MemberSubscriptions"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.HasKey("Id"); + + b.ToTable("MemberSubscriptionPlan"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ArchiveVideoId") + .HasColumnType("int"); + + b.Property("CurrentDuration") + .HasColumnType("int"); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("VideoWatchedStatus") + .IsRequired() + .HasMaxLength(1) + .HasColumnType("nvarchar(1)") + .HasColumnName("VideoWatchedStatus"); + + b.HasKey("Id"); + + b.HasIndex("ArchiveVideoId"); + + b.HasIndex("MemberId"); + + b.ToTable("MembersVideosProgress", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ArchiveVideoId") + .HasColumnType("int"); + + b.Property("CoachingSessionId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("QuestionText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Votes") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CoachingSessionId"); + + b.HasIndex("MemberId"); + + b.ToTable("Questions", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.HasIndex("QuestionId"); + + b.ToTable("QuestionVote"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("ParentCommentId") + .HasColumnType("int"); + + b.Property("VideoId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.HasIndex("ParentCommentId"); + + b.HasIndex("VideoId"); + + b.ToTable("VideoComments"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => + { + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("ArchiveVideoId") + .HasColumnType("int"); + + b.HasKey("MemberId", "ArchiveVideoId"); + + b.HasIndex("ArchiveVideoId"); + + b.ToTable("MemberFavoriteArchiveVideos", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Infrastructure.Identity.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedUserName") + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("ApplicationUser"); + }); + + modelBuilder.Entity("BookMember", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Book", null) + .WithMany() + .HasForeignKey("BooksReadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany() + .HasForeignKey("MembersWhoHaveReadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("BillingActivities") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.BillingDetails", "Details", b1 => + { + b1.Property("BillingActivityId") + .HasColumnType("int"); + + b1.Property("ActionVerbPastTense") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Amount") + .ValueGeneratedOnAdd() + .HasColumnType("decimal(18,4)") + .HasDefaultValue(0m); + + b1.Property("BillingPeriod") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Date") + .HasColumnType("datetime2"); + + b1.Property("MemberName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.Property("SubscriptionPlanName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.HasKey("BillingActivityId"); + + b1.ToTable("BillingActivities"); + + b1.WithOwner() + .HasForeignKey("BillingActivityId"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => + { + b.HasOne("DevBetterWeb.Core.Entities.BookCategory", "BookCategory") + .WithMany("Books") + .HasForeignKey("BookCategoryId"); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoUpload") + .WithMany("UploadedBooks") + .HasForeignKey("MemberWhoUploadId"); + + b.Navigation("BookCategory"); + + b.Navigation("MemberWhoUpload"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Address", "ShippingAddress", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("City") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Country") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("PostalCode") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)") + .HasDefaultValue(""); + + b1.Property("State") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Street") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasDefaultValue(""); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Birthday", "Birthday", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("Day") + .HasColumnType("int"); + + b1.Property("Month") + .HasColumnType("int"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Geolocation", "CityLocation", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("Latitude") + .HasColumnType("decimal(18,4)"); + + b1.Property("Longitude") + .HasColumnType("decimal(18,4)"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.Navigation("Birthday"); + + b.Navigation("CityLocation"); + + b.Navigation("ShippingAddress"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("MemberSubscriptions") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.DateTimeRange", "Dates", b1 => + { + b1.Property("MemberSubscriptionId") + .HasColumnType("int"); + + b1.Property("EndDate") + .HasColumnType("datetime2"); + + b1.Property("StartDate") + .HasColumnType("datetime2"); + + b1.HasKey("MemberSubscriptionId"); + + b1.ToTable("MemberSubscriptionDates", (string)null); + + b1.WithOwner() + .HasForeignKey("MemberSubscriptionId"); + }); + + b.Navigation("Dates") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => + { + b.OwnsOne("DevBetterWeb.Core.ValueObjects.MemberSubscriptionPlanDetails", "Details", b1 => + { + b1.Property("MemberSubscriptionPlanId") + .HasColumnType("int"); + + b1.Property("BillingPeriod") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.Property("PricePerBillingPeriod") + .HasMaxLength(100) + .HasColumnType("decimal(18,2)"); + + b1.HasKey("MemberSubscriptionPlanId"); + + b1.ToTable("MemberSubscriptionPlan"); + + b1.WithOwner() + .HasForeignKey("MemberSubscriptionPlanId"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => + { + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") + .WithMany("MembersVideoProgress") + .HasForeignKey("ArchiveVideoId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") + .WithMany("MemberVideosProgress") + .HasForeignKey("MemberId") + .IsRequired(); + + b.Navigation("Member"); + + b.Navigation("Video"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.HasOne("DevBetterWeb.Core.Entities.CoachingSession", "CoachingSession") + .WithMany("Questions") + .HasForeignKey("CoachingSessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") + .WithMany("Questions") + .HasForeignKey("MemberId") + .IsRequired(); + + b.Navigation("CoachingSession"); + + b.Navigation("MemberWhoCreate"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") + .WithMany("QuestionVotes") + .HasForeignKey("MemberId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Question", "Question") + .WithMany("QuestionVotes") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Member"); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") + .WithMany("VideosComments") + .HasForeignKey("MemberId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.VideoComment", "ParentComment") + .WithMany("Replies") + .HasForeignKey("ParentCommentId"); + + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") + .WithMany("Comments") + .HasForeignKey("VideoId") + .IsRequired(); + + b.Navigation("MemberWhoCreate"); + + b.Navigation("ParentComment"); + + b.Navigation("Video"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => + { + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", null) + .WithMany("MemberFavorites") + .HasForeignKey("ArchiveVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("FavoriteArchiveVideos") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => + { + b.Navigation("Comments"); + + b.Navigation("MemberFavorites"); + + b.Navigation("MembersVideoProgress"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => + { + b.Navigation("Books"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.Navigation("BillingActivities"); + + b.Navigation("FavoriteArchiveVideos"); + + b.Navigation("MemberSubscriptions"); + + b.Navigation("MemberVideosProgress"); + + b.Navigation("QuestionVotes"); + + b.Navigation("Questions"); + + b.Navigation("UploadedBooks"); + + b.Navigation("VideosComments"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.Navigation("QuestionVotes"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.Navigation("Replies"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730190343_AddressRemoved.cs b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730190343_AddressRemoved.cs new file mode 100644 index 000000000..7b9b0f9b8 --- /dev/null +++ b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730190343_AddressRemoved.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DevBetterWeb.Infrastructure.Data.Migrations +{ + /// + public partial class AddressRemoved : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Address", + table: "Members"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Address", + table: "Members", + type: "nvarchar(500)", + maxLength: 500, + nullable: true); + } + } +} diff --git a/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730194008_AddressHistoryAdded.Designer.cs b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730194008_AddressHistoryAdded.Designer.cs new file mode 100644 index 000000000..1e3588499 --- /dev/null +++ b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730194008_AddressHistoryAdded.Designer.cs @@ -0,0 +1,1027 @@ +// +using System; +using DevBetterWeb.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace DevBetterWeb.Infrastructure.Data.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20240730194008_AddressHistoryAdded")] + partial class AddressHistoryAdded + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BookMember", b => + { + b.Property("BooksReadId") + .HasColumnType("int"); + + b.Property("MembersWhoHaveReadId") + .HasColumnType("int"); + + b.HasKey("BooksReadId", "MembersWhoHaveReadId"); + + b.HasIndex("MembersWhoHaveReadId"); + + b.ToTable("BookMember"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AnimatedThumbnailUri") + .HasColumnType("nvarchar(max)"); + + b.Property("DateCreated") + .HasColumnType("datetimeoffset"); + + b.Property("DateUploaded") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Duration") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("VideoId") + .HasColumnType("nvarchar(max)"); + + b.Property("VideoUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ArchiveVideos"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasMaxLength(500) + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.ToTable("BillingActivities"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("BookCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(1); + + b.Property("Details") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("MemberWhoUploadId") + .HasColumnType("int"); + + b.Property("PurchaseUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Title") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("BookCategoryId"); + + b.HasIndex("MemberWhoUploadId"); + + b.ToTable("Books"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Title") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.ToTable("BookCategories"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("StartAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("CoachingSessions", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.DailyCheck", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.Property("TasksCompleted") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.ToTable("DailyChecks"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Invitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Active") + .HasColumnType("bit"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateOfLastAdminPing") + .HasColumnType("datetime2"); + + b.Property("DateOfUserPing") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("InviteCode") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("PaymentHandlerSubscriptionId") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.ToTable("Invitations"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AboutInfo") + .HasColumnType("nvarchar(max)"); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("BlueskyUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CityLatitude") + .HasColumnType("decimal(18,2)"); + + b.Property("CityLongitude") + .HasColumnType("decimal(18,2)"); + + b.Property("CodinGameUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DiscordUsername") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("GitHubUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("LastName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("LinkedInUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("MastodonUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OtherUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("PEFriendCode") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("PEUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("TwitchUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("TwitterUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("YouTubeUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Members"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberAddressHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("UpdatedOn") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.ToTable("MemberAddressHistory"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("MemberSubscriptionPlanId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.ToTable("MemberSubscriptions"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.HasKey("Id"); + + b.ToTable("MemberSubscriptionPlan"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ArchiveVideoId") + .HasColumnType("int"); + + b.Property("CurrentDuration") + .HasColumnType("int"); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("VideoWatchedStatus") + .IsRequired() + .HasMaxLength(1) + .HasColumnType("nvarchar(1)") + .HasColumnName("VideoWatchedStatus"); + + b.HasKey("Id"); + + b.HasIndex("ArchiveVideoId"); + + b.HasIndex("MemberId"); + + b.ToTable("MembersVideosProgress", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ArchiveVideoId") + .HasColumnType("int"); + + b.Property("CoachingSessionId") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("QuestionText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Votes") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CoachingSessionId"); + + b.HasIndex("MemberId"); + + b.ToTable("Questions", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.HasIndex("QuestionId"); + + b.ToTable("QuestionVote"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("ParentCommentId") + .HasColumnType("int"); + + b.Property("VideoId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("MemberId"); + + b.HasIndex("ParentCommentId"); + + b.HasIndex("VideoId"); + + b.ToTable("VideoComments"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => + { + b.Property("MemberId") + .HasColumnType("int"); + + b.Property("ArchiveVideoId") + .HasColumnType("int"); + + b.HasKey("MemberId", "ArchiveVideoId"); + + b.HasIndex("ArchiveVideoId"); + + b.ToTable("MemberFavoriteArchiveVideos", (string)null); + }); + + modelBuilder.Entity("DevBetterWeb.Infrastructure.Identity.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedUserName") + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("ApplicationUser"); + }); + + modelBuilder.Entity("BookMember", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Book", null) + .WithMany() + .HasForeignKey("BooksReadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany() + .HasForeignKey("MembersWhoHaveReadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("BillingActivities") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.BillingDetails", "Details", b1 => + { + b1.Property("BillingActivityId") + .HasColumnType("int"); + + b1.Property("ActionVerbPastTense") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Amount") + .ValueGeneratedOnAdd() + .HasColumnType("decimal(18,4)") + .HasDefaultValue(0m); + + b1.Property("BillingPeriod") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Date") + .HasColumnType("datetime2"); + + b1.Property("MemberName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.Property("SubscriptionPlanName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.HasKey("BillingActivityId"); + + b1.ToTable("BillingActivities"); + + b1.WithOwner() + .HasForeignKey("BillingActivityId"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => + { + b.HasOne("DevBetterWeb.Core.Entities.BookCategory", "BookCategory") + .WithMany("Books") + .HasForeignKey("BookCategoryId"); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoUpload") + .WithMany("UploadedBooks") + .HasForeignKey("MemberWhoUploadId"); + + b.Navigation("BookCategory"); + + b.Navigation("MemberWhoUpload"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Address", "ShippingAddress", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("City") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Country") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("PostalCode") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)") + .HasDefaultValue(""); + + b1.Property("State") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Street") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasDefaultValue(""); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Birthday", "Birthday", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("Day") + .HasColumnType("int"); + + b1.Property("Month") + .HasColumnType("int"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Geolocation", "CityLocation", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("Latitude") + .HasColumnType("decimal(18,4)"); + + b1.Property("Longitude") + .HasColumnType("decimal(18,4)"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.Navigation("Birthday"); + + b.Navigation("CityLocation"); + + b.Navigation("ShippingAddress"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberAddressHistory", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("AddressHistory") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Address", "Address", b1 => + { + b1.Property("MemberAddressHistoryId") + .HasColumnType("int"); + + b1.Property("City") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Country") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("PostalCode") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)") + .HasDefaultValue(""); + + b1.Property("State") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Street") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasDefaultValue(""); + + b1.HasKey("MemberAddressHistoryId"); + + b1.ToTable("MemberAddressHistory"); + + b1.WithOwner() + .HasForeignKey("MemberAddressHistoryId"); + }); + + b.Navigation("Address"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("MemberSubscriptions") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.DateTimeRange", "Dates", b1 => + { + b1.Property("MemberSubscriptionId") + .HasColumnType("int"); + + b1.Property("EndDate") + .HasColumnType("datetime2"); + + b1.Property("StartDate") + .HasColumnType("datetime2"); + + b1.HasKey("MemberSubscriptionId"); + + b1.ToTable("MemberSubscriptionDates", (string)null); + + b1.WithOwner() + .HasForeignKey("MemberSubscriptionId"); + }); + + b.Navigation("Dates") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => + { + b.OwnsOne("DevBetterWeb.Core.ValueObjects.MemberSubscriptionPlanDetails", "Details", b1 => + { + b1.Property("MemberSubscriptionPlanId") + .HasColumnType("int"); + + b1.Property("BillingPeriod") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.Property("PricePerBillingPeriod") + .HasMaxLength(100) + .HasColumnType("decimal(18,2)"); + + b1.HasKey("MemberSubscriptionPlanId"); + + b1.ToTable("MemberSubscriptionPlan"); + + b1.WithOwner() + .HasForeignKey("MemberSubscriptionPlanId"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => + { + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") + .WithMany("MembersVideoProgress") + .HasForeignKey("ArchiveVideoId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") + .WithMany("MemberVideosProgress") + .HasForeignKey("MemberId") + .IsRequired(); + + b.Navigation("Member"); + + b.Navigation("Video"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.HasOne("DevBetterWeb.Core.Entities.CoachingSession", "CoachingSession") + .WithMany("Questions") + .HasForeignKey("CoachingSessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") + .WithMany("Questions") + .HasForeignKey("MemberId") + .IsRequired(); + + b.Navigation("CoachingSession"); + + b.Navigation("MemberWhoCreate"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") + .WithMany("QuestionVotes") + .HasForeignKey("MemberId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Question", "Question") + .WithMany("QuestionVotes") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Member"); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") + .WithMany("VideosComments") + .HasForeignKey("MemberId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.VideoComment", "ParentComment") + .WithMany("Replies") + .HasForeignKey("ParentCommentId"); + + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") + .WithMany("Comments") + .HasForeignKey("VideoId") + .IsRequired(); + + b.Navigation("MemberWhoCreate"); + + b.Navigation("ParentComment"); + + b.Navigation("Video"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => + { + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", null) + .WithMany("MemberFavorites") + .HasForeignKey("ArchiveVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("FavoriteArchiveVideos") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => + { + b.Navigation("Comments"); + + b.Navigation("MemberFavorites"); + + b.Navigation("MembersVideoProgress"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => + { + b.Navigation("Books"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.Navigation("AddressHistory"); + + b.Navigation("BillingActivities"); + + b.Navigation("FavoriteArchiveVideos"); + + b.Navigation("MemberSubscriptions"); + + b.Navigation("MemberVideosProgress"); + + b.Navigation("QuestionVotes"); + + b.Navigation("Questions"); + + b.Navigation("UploadedBooks"); + + b.Navigation("VideosComments"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.Navigation("QuestionVotes"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.Navigation("Replies"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730194008_AddressHistoryAdded.cs b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730194008_AddressHistoryAdded.cs new file mode 100644 index 000000000..5a56e56c5 --- /dev/null +++ b/src/DevBetterWeb.Infrastructure/Data/Migrations/20240730194008_AddressHistoryAdded.cs @@ -0,0 +1,52 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DevBetterWeb.Infrastructure.Data.Migrations +{ + /// + public partial class AddressHistoryAdded : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "MemberAddressHistory", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + MemberId = table.Column(type: "int", nullable: false), + Address_Street = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true, defaultValue: ""), + Address_City = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true, defaultValue: ""), + Address_State = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true, defaultValue: ""), + Address_PostalCode = table.Column(type: "nvarchar(12)", maxLength: 12, nullable: true, defaultValue: ""), + Address_Country = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true, defaultValue: ""), + UpdatedOn = table.Column(type: "datetimeoffset", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MemberAddressHistory", x => x.Id); + table.ForeignKey( + name: "FK_MemberAddressHistory_Members_MemberId", + column: x => x.MemberId, + principalTable: "Members", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_MemberAddressHistory_MemberId", + table: "MemberAddressHistory", + column: "MemberId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "MemberAddressHistory"); + } + } +} diff --git a/src/DevBetterWeb.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs b/src/DevBetterWeb.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs index 7d212a6f5..cb5240f52 100644 --- a/src/DevBetterWeb.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs +++ b/src/DevBetterWeb.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs @@ -10,937 +10,1015 @@ namespace DevBetterWeb.Infrastructure.Data.Migrations { - [DbContext(typeof(AppDbContext))] - partial class AppDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { + [DbContext(typeof(AppDbContext))] + partial class AppDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("BookMember", b => - { - b.Property("BooksReadId") - .HasColumnType("int"); + modelBuilder.Entity("BookMember", b => + { + b.Property("BooksReadId") + .HasColumnType("int"); - b.Property("MembersWhoHaveReadId") - .HasColumnType("int"); + b.Property("MembersWhoHaveReadId") + .HasColumnType("int"); - b.HasKey("BooksReadId", "MembersWhoHaveReadId"); + b.HasKey("BooksReadId", "MembersWhoHaveReadId"); - b.HasIndex("MembersWhoHaveReadId"); + b.HasIndex("MembersWhoHaveReadId"); - b.ToTable("BookMember"); - }); + b.ToTable("BookMember"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("AnimatedThumbnailUri") - .HasColumnType("nvarchar(max)"); + b.Property("AnimatedThumbnailUri") + .HasColumnType("nvarchar(max)"); - b.Property("DateCreated") - .HasColumnType("datetimeoffset"); + b.Property("DateCreated") + .HasColumnType("datetimeoffset"); - b.Property("DateUploaded") - .HasColumnType("datetimeoffset"); + b.Property("DateUploaded") + .HasColumnType("datetimeoffset"); - b.Property("Description") - .HasColumnType("nvarchar(max)"); + b.Property("Description") + .HasColumnType("nvarchar(max)"); - b.Property("Duration") - .HasColumnType("int"); + b.Property("Duration") + .HasColumnType("int"); - b.Property("Status") - .HasColumnType("nvarchar(max)"); + b.Property("Status") + .HasColumnType("nvarchar(max)"); - b.Property("Title") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("Title") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("VideoId") - .HasColumnType("nvarchar(max)"); + b.Property("VideoId") + .HasColumnType("nvarchar(max)"); - b.Property("VideoUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("VideoUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("Views") - .HasColumnType("int"); + b.Property("Views") + .HasColumnType("int"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("ArchiveVideos"); - }); + b.ToTable("ArchiveVideos"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("MemberId") - .HasMaxLength(500) - .HasColumnType("int"); + b.Property("MemberId") + .HasMaxLength(500) + .HasColumnType("int"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("MemberId"); + b.HasIndex("MemberId"); - b.ToTable("BillingActivities"); - }); + b.ToTable("BillingActivities"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Author") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Property("BookCategoryId") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasDefaultValue(1); + b.Property("BookCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(1); - b.Property("Details") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); + b.Property("Details") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); - b.Property("MemberWhoUploadId") - .HasColumnType("int"); + b.Property("MemberWhoUploadId") + .HasColumnType("int"); - b.Property("PurchaseUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("PurchaseUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("Title") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("Title") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("BookCategoryId"); + b.HasIndex("BookCategoryId"); - b.HasIndex("MemberWhoUploadId"); + b.HasIndex("MemberWhoUploadId"); - b.ToTable("Books"); - }); + b.ToTable("Books"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Title") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("Title") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("BookCategories"); - }); + b.ToTable("BookCategories"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("StartAt") - .HasColumnType("datetime2"); + b.Property("StartAt") + .HasColumnType("datetime2"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("CoachingSessions", (string)null); - }); + b.ToTable("CoachingSessions", (string)null); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.DailyCheck", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.DailyCheck", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Date") - .HasColumnType("datetime2"); + b.Property("Date") + .HasColumnType("datetime2"); - b.Property("TasksCompleted") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("TasksCompleted") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("DailyChecks"); - }); + b.ToTable("DailyChecks"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.Invitation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Invitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Active") - .HasColumnType("bit"); + b.Property("Active") + .HasColumnType("bit"); - b.Property("DateCreated") - .HasColumnType("datetime2"); + b.Property("DateCreated") + .HasColumnType("datetime2"); - b.Property("DateOfLastAdminPing") - .HasColumnType("datetime2"); + b.Property("DateOfLastAdminPing") + .HasColumnType("datetime2"); - b.Property("DateOfUserPing") - .HasColumnType("datetime2"); + b.Property("DateOfUserPing") + .HasColumnType("datetime2"); - b.Property("Email") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("InviteCode") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("InviteCode") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - b.Property("PaymentHandlerSubscriptionId") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("PaymentHandlerSubscriptionId") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("Invitations"); - }); + b.ToTable("Invitations"); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("AboutInfo") - .HasColumnType("nvarchar(max)"); + b.Property("AboutInfo") + .HasColumnType("nvarchar(max)"); - b.Property("Address") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("BlogUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("BlueskyUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("BlueskyUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("CityLatitude") + .HasColumnType("decimal(18,2)"); - b.Property("CityLatitude") - .HasColumnType("decimal(18,2)"); + b.Property("CityLongitude") + .HasColumnType("decimal(18,2)"); - b.Property("CityLongitude") - .HasColumnType("decimal(18,2)"); + b.Property("CodinGameUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("CodinGameUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("DateCreated") + .HasColumnType("datetime2"); - b.Property("DateCreated") - .HasColumnType("datetime2"); + b.Property("DiscordUsername") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("DiscordUsername") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("Email") + .HasColumnType("nvarchar(max)"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); + b.Property("FirstName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Property("FirstName") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.Property("GitHubUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("GitHubUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("LastName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Property("LastName") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.Property("LinkedInUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("LinkedInUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("MastodonUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("MastodonUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("OtherUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("OtherUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("PEFriendCode") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Property("PEFriendCode") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.Property("PEUsername") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Property("PEUsername") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.Property("TwitchUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("TwitchUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("TwitterUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("TwitterUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.Property("UserId") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - b.Property("UserId") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + b.Property("YouTubeUrl") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); - b.Property("YouTubeUrl") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); + b.HasKey("Id"); - b.HasKey("Id"); + b.ToTable("Members"); + }); - b.ToTable("Members"); - }); + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberAddressHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("MemberId") + .HasColumnType("int"); - b.Property("MemberId") - .HasColumnType("int"); + b.Property("UpdatedOn") + .HasColumnType("datetimeoffset"); - b.Property("MemberSubscriptionPlanId") - .HasColumnType("int"); + b.HasKey("Id"); - b.HasKey("Id"); + b.HasIndex("MemberId"); - b.HasIndex("MemberId"); + b.ToTable("MemberAddressHistory"); + }); - b.ToTable("MemberSubscriptions"); - }); + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("MemberId") + .HasColumnType("int"); - b.HasKey("Id"); + b.Property("MemberSubscriptionPlanId") + .HasColumnType("int"); - b.ToTable("MemberSubscriptionPlan"); - }); + b.HasKey("Id"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + b.HasIndex("MemberId"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.ToTable("MemberSubscriptions"); + }); - b.Property("ArchiveVideoId") - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("CurrentDuration") - .HasColumnType("int"); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("MemberId") - .HasColumnType("int"); + b.HasKey("Id"); - b.Property("VideoWatchedStatus") - .IsRequired() - .HasMaxLength(1) - .HasColumnType("nvarchar(1)") - .HasColumnName("VideoWatchedStatus"); + b.ToTable("MemberSubscriptionPlan"); + }); - b.HasKey("Id"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.HasIndex("ArchiveVideoId"); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.HasIndex("MemberId"); + b.Property("ArchiveVideoId") + .HasColumnType("int"); - b.ToTable("MembersVideosProgress", (string)null); - }); + b.Property("CurrentDuration") + .HasColumnType("int"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + b.Property("MemberId") + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("VideoWatchedStatus") + .IsRequired() + .HasMaxLength(1) + .HasColumnType("nvarchar(1)") + .HasColumnName("VideoWatchedStatus"); - b.Property("ArchiveVideoId") - .HasColumnType("int"); + b.HasKey("Id"); - b.Property("CoachingSessionId") - .HasColumnType("int"); + b.HasIndex("ArchiveVideoId"); - b.Property("CreatedAt") - .HasColumnType("datetime2"); + b.HasIndex("MemberId"); - b.Property("MemberId") - .HasColumnType("int"); + b.ToTable("MembersVideosProgress", (string)null); + }); - b.Property("QuestionText") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Votes") - .HasColumnType("int"); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.HasKey("Id"); + b.Property("ArchiveVideoId") + .HasColumnType("int"); - b.HasIndex("CoachingSessionId"); + b.Property("CoachingSessionId") + .HasColumnType("int"); - b.HasIndex("MemberId"); + b.Property("CreatedAt") + .HasColumnType("datetime2"); - b.ToTable("Questions", (string)null); - }); + b.Property("MemberId") + .HasColumnType("int"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + b.Property("QuestionText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("Votes") + .HasColumnType("int"); - b.Property("MemberId") - .HasColumnType("int"); + b.HasKey("Id"); - b.Property("QuestionId") - .HasColumnType("int"); + b.HasIndex("CoachingSessionId"); - b.HasKey("Id"); + b.HasIndex("MemberId"); - b.HasIndex("MemberId"); + b.ToTable("Questions", (string)null); + }); - b.HasIndex("QuestionId"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.ToTable("QuestionVote"); - }); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); + b.Property("MemberId") + .HasColumnType("int"); - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("QuestionId") + .HasColumnType("int"); - b.Property("Body") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); + b.HasKey("Id"); - b.Property("CreatedAt") - .HasColumnType("datetimeoffset"); + b.HasIndex("MemberId"); - b.Property("MemberId") - .HasColumnType("int"); + b.HasIndex("QuestionId"); - b.Property("ParentCommentId") - .HasColumnType("int"); + b.ToTable("QuestionVote"); + }); - b.Property("VideoId") - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.HasKey("Id"); + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.HasIndex("MemberId"); + b.Property("Body") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); - b.HasIndex("ParentCommentId"); + b.Property("CreatedAt") + .HasColumnType("datetimeoffset"); - b.HasIndex("VideoId"); + b.Property("MemberId") + .HasColumnType("int"); - b.ToTable("VideoComments"); - }); + b.Property("ParentCommentId") + .HasColumnType("int"); - modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => - { - b.Property("MemberId") - .HasColumnType("int"); + b.Property("VideoId") + .HasColumnType("int"); - b.Property("ArchiveVideoId") - .HasColumnType("int"); + b.HasKey("Id"); - b.HasKey("MemberId", "ArchiveVideoId"); + b.HasIndex("MemberId"); - b.HasIndex("ArchiveVideoId"); + b.HasIndex("ParentCommentId"); - b.ToTable("MemberFavoriteArchiveVideos", (string)null); - }); + b.HasIndex("VideoId"); - modelBuilder.Entity("DevBetterWeb.Infrastructure.Identity.Data.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); + b.ToTable("VideoComments"); + }); - b.Property("AccessFailedCount") - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => + { + b.Property("MemberId") + .HasColumnType("int"); - b.Property("ConcurrencyStamp") - .HasColumnType("nvarchar(max)"); + b.Property("ArchiveVideoId") + .HasColumnType("int"); - b.Property("DateCreated") - .HasColumnType("datetime2"); + b.HasKey("MemberId", "ArchiveVideoId"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); + b.HasIndex("ArchiveVideoId"); - b.Property("EmailConfirmed") - .HasColumnType("bit"); + b.ToTable("MemberFavoriteArchiveVideos", (string)null); + }); - b.Property("LockoutEnabled") - .HasColumnType("bit"); + modelBuilder.Entity("DevBetterWeb.Infrastructure.Identity.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); + b.Property("AccessFailedCount") + .HasColumnType("int"); - b.Property("NormalizedEmail") - .HasColumnType("nvarchar(max)"); + b.Property("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); - b.Property("NormalizedUserName") - .HasColumnType("nvarchar(max)"); + b.Property("DateCreated") + .HasColumnType("datetime2"); - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); + b.Property("Email") + .HasColumnType("nvarchar(max)"); - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); + b.Property("EmailConfirmed") + .HasColumnType("bit"); - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); + b.Property("LockoutEnabled") + .HasColumnType("bit"); - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); + b.Property("NormalizedEmail") + .HasColumnType("nvarchar(max)"); - b.Property("UserName") - .HasColumnType("nvarchar(max)"); + b.Property("NormalizedUserName") + .HasColumnType("nvarchar(max)"); - b.HasKey("Id"); + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); - b.ToTable("ApplicationUser"); - }); + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); - modelBuilder.Entity("BookMember", b => - { - b.HasOne("DevBetterWeb.Core.Entities.Book", null) - .WithMany() - .HasForeignKey("BooksReadId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); - b.HasOne("DevBetterWeb.Core.Entities.Member", null) - .WithMany() - .HasForeignKey("MembersWhoHaveReadId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => - { - b.HasOne("DevBetterWeb.Core.Entities.Member", null) - .WithMany("BillingActivities") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); - b.OwnsOne("DevBetterWeb.Core.ValueObjects.BillingDetails", "Details", b1 => - { - b1.Property("BillingActivityId") - .HasColumnType("int"); + b.Property("UserName") + .HasColumnType("nvarchar(max)"); - b1.Property("ActionVerbPastTense") - .HasMaxLength(100) - .HasColumnType("int"); + b.HasKey("Id"); - b1.Property("Amount") - .ValueGeneratedOnAdd() - .HasColumnType("decimal(18,4)") - .HasDefaultValue(0m); + b.ToTable("ApplicationUser"); + }); - b1.Property("BillingPeriod") - .HasMaxLength(100) - .HasColumnType("int"); - - b1.Property("Date") - .HasColumnType("datetime2"); + modelBuilder.Entity("BookMember", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Book", null) + .WithMany() + .HasForeignKey("BooksReadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b1.Property("MemberName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany() + .HasForeignKey("MembersWhoHaveReadId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); - b1.Property("SubscriptionPlanName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b1.HasKey("BillingActivityId"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.BillingActivity", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("BillingActivities") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b1.ToTable("BillingActivities"); + b.OwnsOne("DevBetterWeb.Core.ValueObjects.BillingDetails", "Details", b1 => + { + b1.Property("BillingActivityId") + .HasColumnType("int"); - b1.WithOwner() - .HasForeignKey("BillingActivityId"); - }); + b1.Property("ActionVerbPastTense") + .HasMaxLength(100) + .HasColumnType("int"); - b.Navigation("Details") - .IsRequired(); - }); + b1.Property("Amount") + .ValueGeneratedOnAdd() + .HasColumnType("decimal(18,4)") + .HasDefaultValue(0m); - modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => - { - b.HasOne("DevBetterWeb.Core.Entities.BookCategory", "BookCategory") - .WithMany("Books") - .HasForeignKey("BookCategoryId"); + b1.Property("BillingPeriod") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Date") + .HasColumnType("datetime2"); - b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoUpload") - .WithMany("UploadedBooks") - .HasForeignKey("MemberWhoUploadId"); + b1.Property("MemberName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Navigation("BookCategory"); + b1.Property("SubscriptionPlanName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.HasKey("BillingActivityId"); - b.Navigation("MemberWhoUpload"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => - { - b.OwnsOne("DevBetterWeb.Core.ValueObjects.Address", "ShippingAddress", b1 => - { - b1.Property("MemberId") - .HasColumnType("int"); - - b1.Property("City") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasDefaultValue(""); - - b1.Property("Country") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasDefaultValue(""); - - b1.Property("PostalCode") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(12) - .HasColumnType("nvarchar(12)") - .HasDefaultValue(""); - - b1.Property("State") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)") - .HasDefaultValue(""); - - b1.Property("Street") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasDefaultValue(""); + b1.ToTable("BillingActivities"); - b1.HasKey("MemberId"); + b1.WithOwner() + .HasForeignKey("BillingActivityId"); + }); - b1.ToTable("Members"); + b.Navigation("Details") + .IsRequired(); + }); - b1.WithOwner() - .HasForeignKey("MemberId"); - }); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Book", b => + { + b.HasOne("DevBetterWeb.Core.Entities.BookCategory", "BookCategory") + .WithMany("Books") + .HasForeignKey("BookCategoryId"); - b.OwnsOne("DevBetterWeb.Core.ValueObjects.Birthday", "Birthday", b1 => - { - b1.Property("MemberId") - .HasColumnType("int"); + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoUpload") + .WithMany("UploadedBooks") + .HasForeignKey("MemberWhoUploadId"); - b1.Property("Day") - .HasColumnType("int"); + b.Navigation("BookCategory"); - b1.Property("Month") - .HasColumnType("int"); + b.Navigation("MemberWhoUpload"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Address", "ShippingAddress", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("City") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Country") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("PostalCode") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)") + .HasDefaultValue(""); + + b1.Property("State") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Street") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasDefaultValue(""); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Birthday", "Birthday", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("Day") + .HasColumnType("int"); + + b1.Property("Month") + .HasColumnType("int"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Geolocation", "CityLocation", b1 => + { + b1.Property("MemberId") + .HasColumnType("int"); + + b1.Property("Latitude") + .HasColumnType("decimal(18,4)"); + + b1.Property("Longitude") + .HasColumnType("decimal(18,4)"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.Navigation("Birthday"); + + b.Navigation("CityLocation"); + + b.Navigation("ShippingAddress"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberAddressHistory", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("AddressHistory") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.Address", "Address", b1 => + { + b1.Property("MemberAddressHistoryId") + .HasColumnType("int"); + + b1.Property("City") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("Country") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); + + b1.Property("PostalCode") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(12) + .HasColumnType("nvarchar(12)") + .HasDefaultValue(""); + + b1.Property("State") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)") + .HasDefaultValue(""); - b1.HasKey("MemberId"); + b1.Property("Street") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)") + .HasDefaultValue(""); - b1.ToTable("Members"); + b1.HasKey("MemberAddressHistoryId"); + + b1.ToTable("MemberAddressHistory"); + + b1.WithOwner() + .HasForeignKey("MemberAddressHistoryId"); + }); + + b.Navigation("Address"); + }); - b1.WithOwner() - .HasForeignKey("MemberId"); - }); + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("MemberSubscriptions") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("DevBetterWeb.Core.ValueObjects.DateTimeRange", "Dates", b1 => + { + b1.Property("MemberSubscriptionId") + .HasColumnType("int"); + + b1.Property("EndDate") + .HasColumnType("datetime2"); + + b1.Property("StartDate") + .HasColumnType("datetime2"); + + b1.HasKey("MemberSubscriptionId"); + + b1.ToTable("MemberSubscriptionDates", (string)null); + + b1.WithOwner() + .HasForeignKey("MemberSubscriptionId"); + }); + + b.Navigation("Dates") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => + { + b.OwnsOne("DevBetterWeb.Core.ValueObjects.MemberSubscriptionPlanDetails", "Details", b1 => + { + b1.Property("MemberSubscriptionPlanId") + .HasColumnType("int"); + + b1.Property("BillingPeriod") + .HasMaxLength(100) + .HasColumnType("int"); + + b1.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b1.Property("PricePerBillingPeriod") + .HasMaxLength(100) + .HasColumnType("decimal(18,2)"); + + b1.HasKey("MemberSubscriptionPlanId"); + + b1.ToTable("MemberSubscriptionPlan"); + + b1.WithOwner() + .HasForeignKey("MemberSubscriptionPlanId"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => + { + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") + .WithMany("MembersVideoProgress") + .HasForeignKey("ArchiveVideoId") + .IsRequired(); + + b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") + .WithMany("MemberVideosProgress") + .HasForeignKey("MemberId") + .IsRequired(); + + b.Navigation("Member"); + + b.Navigation("Video"); + }); + + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.HasOne("DevBetterWeb.Core.Entities.CoachingSession", "CoachingSession") + .WithMany("Questions") + .HasForeignKey("CoachingSessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.OwnsOne("DevBetterWeb.Core.ValueObjects.Geolocation", "CityLocation", b1 => - { - b1.Property("MemberId") - .HasColumnType("int"); + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") + .WithMany("Questions") + .HasForeignKey("MemberId") + .IsRequired(); - b1.Property("Latitude") - .HasColumnType("decimal(18,4)"); + b.Navigation("CoachingSession"); - b1.Property("Longitude") - .HasColumnType("decimal(18,4)"); + b.Navigation("MemberWhoCreate"); + }); - b1.HasKey("MemberId"); - - b1.ToTable("Members"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") + .WithMany("QuestionVotes") + .HasForeignKey("MemberId") + .IsRequired(); - b1.WithOwner() - .HasForeignKey("MemberId"); - }); + b.HasOne("DevBetterWeb.Core.Entities.Question", "Question") + .WithMany("QuestionVotes") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Birthday"); + b.Navigation("Member"); - b.Navigation("CityLocation"); + b.Navigation("Question"); + }); - b.Navigation("ShippingAddress"); - }); + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") + .WithMany("VideosComments") + .HasForeignKey("MemberId") + .IsRequired(); - modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscription", b => - { - b.HasOne("DevBetterWeb.Core.Entities.Member", null) - .WithMany("MemberSubscriptions") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.OwnsOne("DevBetterWeb.Core.ValueObjects.DateTimeRange", "Dates", b1 => - { - b1.Property("MemberSubscriptionId") - .HasColumnType("int"); + b.HasOne("DevBetterWeb.Core.Entities.VideoComment", "ParentComment") + .WithMany("Replies") + .HasForeignKey("ParentCommentId"); - b1.Property("EndDate") - .HasColumnType("datetime2"); + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") + .WithMany("Comments") + .HasForeignKey("VideoId") + .IsRequired(); - b1.Property("StartDate") - .HasColumnType("datetime2"); + b.Navigation("MemberWhoCreate"); - b1.HasKey("MemberSubscriptionId"); + b.Navigation("ParentComment"); - b1.ToTable("MemberSubscriptionDates", (string)null); + b.Navigation("Video"); + }); - b1.WithOwner() - .HasForeignKey("MemberSubscriptionId"); - }); + modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => + { + b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", null) + .WithMany("MemberFavorites") + .HasForeignKey("ArchiveVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Dates") - .IsRequired(); - }); + b.HasOne("DevBetterWeb.Core.Entities.Member", null) + .WithMany("FavoriteArchiveVideos") + .HasForeignKey("MemberId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); - modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberSubscriptionPlan", b => - { - b.OwnsOne("DevBetterWeb.Core.ValueObjects.MemberSubscriptionPlanDetails", "Details", b1 => - { - b1.Property("MemberSubscriptionPlanId") - .HasColumnType("int"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => + { + b.Navigation("Comments"); - b1.Property("BillingPeriod") - .HasMaxLength(100) - .HasColumnType("int"); + b.Navigation("MemberFavorites"); - b1.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); + b.Navigation("MembersVideoProgress"); + }); - b1.Property("PricePerBillingPeriod") - .HasMaxLength(100) - .HasColumnType("decimal(18,2)"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => + { + b.Navigation("Books"); + }); - b1.HasKey("MemberSubscriptionPlanId"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => + { + b.Navigation("Questions"); + }); - b1.ToTable("MemberSubscriptionPlan"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => + { + b.Navigation("AddressHistory"); - b1.WithOwner() - .HasForeignKey("MemberSubscriptionPlanId"); - }); + b.Navigation("BillingActivities"); - b.Navigation("Details") - .IsRequired(); - }); + b.Navigation("FavoriteArchiveVideos"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.MemberVideoProgress", b => - { - b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") - .WithMany("MembersVideoProgress") - .HasForeignKey("ArchiveVideoId") - .IsRequired(); + b.Navigation("MemberSubscriptions"); - b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") - .WithMany("MemberVideosProgress") - .HasForeignKey("MemberId") - .IsRequired(); + b.Navigation("MemberVideosProgress"); - b.Navigation("Member"); + b.Navigation("QuestionVotes"); - b.Navigation("Video"); - }); + b.Navigation("Questions"); - modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => - { - b.HasOne("DevBetterWeb.Core.Entities.CoachingSession", "CoachingSession") - .WithMany("Questions") - .HasForeignKey("CoachingSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + b.Navigation("UploadedBooks"); - b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") - .WithMany("Questions") - .HasForeignKey("MemberId") - .IsRequired(); + b.Navigation("VideosComments"); + }); - b.Navigation("CoachingSession"); + modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => + { + b.Navigation("QuestionVotes"); + }); - b.Navigation("MemberWhoCreate"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.QuestionVote", b => - { - b.HasOne("DevBetterWeb.Core.Entities.Member", "Member") - .WithMany("QuestionVotes") - .HasForeignKey("MemberId") - .IsRequired(); - - b.HasOne("DevBetterWeb.Core.Entities.Question", "Question") - .WithMany("QuestionVotes") - .HasForeignKey("QuestionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Member"); - - b.Navigation("Question"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => - { - b.HasOne("DevBetterWeb.Core.Entities.Member", "MemberWhoCreate") - .WithMany("VideosComments") - .HasForeignKey("MemberId") - .IsRequired(); - - b.HasOne("DevBetterWeb.Core.Entities.VideoComment", "ParentComment") - .WithMany("Replies") - .HasForeignKey("ParentCommentId"); - - b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", "Video") - .WithMany("Comments") - .HasForeignKey("VideoId") - .IsRequired(); - - b.Navigation("MemberWhoCreate"); - - b.Navigation("ParentComment"); - - b.Navigation("Video"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.ValueObjects.MemberFavoriteArchiveVideo", b => - { - b.HasOne("DevBetterWeb.Core.Entities.ArchiveVideo", null) - .WithMany("MemberFavorites") - .HasForeignKey("ArchiveVideoId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("DevBetterWeb.Core.Entities.Member", null) - .WithMany("FavoriteArchiveVideos") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.ArchiveVideo", b => - { - b.Navigation("Comments"); - - b.Navigation("MemberFavorites"); - - b.Navigation("MembersVideoProgress"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.BookCategory", b => - { - b.Navigation("Books"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.CoachingSession", b => - { - b.Navigation("Questions"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.Member", b => - { - b.Navigation("BillingActivities"); - - b.Navigation("FavoriteArchiveVideos"); - - b.Navigation("MemberSubscriptions"); - - b.Navigation("MemberVideosProgress"); - - b.Navigation("QuestionVotes"); - - b.Navigation("Questions"); - - b.Navigation("UploadedBooks"); - - b.Navigation("VideosComments"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.Question", b => - { - b.Navigation("QuestionVotes"); - }); - - modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => - { - b.Navigation("Replies"); - }); + modelBuilder.Entity("DevBetterWeb.Core.Entities.VideoComment", b => + { + b.Navigation("Replies"); + }); #pragma warning restore 612, 618 - } - } + } + } } diff --git a/src/DevBetterWeb.Infrastructure/Handlers/MemberAddressUpdatedHandler.cs b/src/DevBetterWeb.Infrastructure/Handlers/MemberAddressUpdatedHandler.cs index bceef2546..2231f9c27 100644 --- a/src/DevBetterWeb.Infrastructure/Handlers/MemberAddressUpdatedHandler.cs +++ b/src/DevBetterWeb.Infrastructure/Handlers/MemberAddressUpdatedHandler.cs @@ -31,14 +31,14 @@ AdminUpdatesWebhook webhook public async Task Handle(MemberAddressUpdatedEvent addressUpdatedEvent) { var member = addressUpdatedEvent.Member; - if (member.Address is null) return; + if (member.ShippingAddress is null) return; - _logger.LogInformation($"Parsing address for member {member.FirstName} {member.LastName}: {member.Address}"); - var addressParts = member.Address.Split(','); + _logger.LogInformation($"Parsing address for member {member.FirstName} {member.LastName}: {member.ShippingAddress}"); + var addressParts = member.ShippingAddress.ToString().Split(','); if (addressParts is not null) { - string responseString = await _mapCoordinateService.GetMapCoordinates(member.Address); + string responseString = await _mapCoordinateService.GetMapCoordinates(member.ShippingAddress.ToString()); if (!string.IsNullOrEmpty(responseString)) { _logger.LogInformation($"API Response: {responseString}"); @@ -55,7 +55,7 @@ public async Task Handle(MemberAddressUpdatedEvent addressUpdatedEvent) _logger.LogInformation($"Set lat/long to {latitude}/{longitude}."); } - var message = $"Member {member.UserFullName()} change the address to {member.Address}"; + var message = $"Member {member.UserFullName()} change the address to {member.ShippingAddress}"; await _webhook.SendAsync(message); //await _repository.UpdateAsync(member); diff --git a/src/DevBetterWeb.Web/Areas/Identity/Pages/Account/NewMemberRegister.cshtml b/src/DevBetterWeb.Web/Areas/Identity/Pages/Account/NewMemberRegister.cshtml index 32fd88c76..f7ce36cef 100644 --- a/src/DevBetterWeb.Web/Areas/Identity/Pages/Account/NewMemberRegister.cshtml +++ b/src/DevBetterWeb.Web/Areas/Identity/Pages/Account/NewMemberRegister.cshtml @@ -28,8 +28,11 @@
- - + +
diff --git a/src/DevBetterWeb.Web/DevBetterWeb.Web.csproj b/src/DevBetterWeb.Web/DevBetterWeb.Web.csproj index 20343cabe..692bd94b2 100644 --- a/src/DevBetterWeb.Web/DevBetterWeb.Web.csproj +++ b/src/DevBetterWeb.Web/DevBetterWeb.Web.csproj @@ -30,6 +30,7 @@ + diff --git a/src/DevBetterWeb.Web/Models/MemberLinksDTO.cs b/src/DevBetterWeb.Web/Models/MemberLinksDTO.cs index 2e4b1763b..ce90f90aa 100644 --- a/src/DevBetterWeb.Web/Models/MemberLinksDTO.cs +++ b/src/DevBetterWeb.Web/Models/MemberLinksDTO.cs @@ -38,7 +38,7 @@ public static MemberLinksDTO FromMemberEntity(Member member) UserId = member.UserId, PEUsername = member.PEUsername, PEBadgeURL = $"https://projecteuler.net/profile/{member.PEUsername}.png", - Address = member.Address, + Address = member.ShippingAddress?.ToString(), CodinGameUrl = member.CodinGameUrl, SubscribedDays = member.TotalSubscribedDays() }; diff --git a/src/DevBetterWeb.Web/Pages/Admin/User.cshtml b/src/DevBetterWeb.Web/Pages/Admin/User.cshtml index 2c41de9ee..fcb9136c4 100644 --- a/src/DevBetterWeb.Web/Pages/Admin/User.cshtml +++ b/src/DevBetterWeb.Web/Pages/Admin/User.cshtml @@ -117,103 +117,96 @@
-
-
- -
-
- Personal -
- -
-
-
-
- - - -
- -
- - - -
- -
- - - -
- -
- - Only administrators can view this information - include country if non-US - - -
- -
- - Only administrators can view this information - include country if non-US - - -
- -
- - Only administrators can view this information - include country if non-US - - -
- -
- - Only administrators can view this information - include country if non-US - - -
- -
- - Only administrators can view this information - include country if non-US - - -
- -
- - -
- -
- - - -
- -
- - -
- -
- - -
- -
-
- -
+
+
+ +
+
+ Personal +
+ +
+
+
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + +
+ +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+
+ +
+ +
+
-
+
+
+ Shipping Address + +
+ +
+ @if (@Model.UserPersonalUpdateModel.Address != "none") + { +
+ + @Model.UserPersonalUpdateModel.Address + +
+ } + + + City, State (optional), and Country are used for map location. +
+ Full shipping address is only visible to admins and is used for shipping books and other packages to members from time to time. +
+
+
+ Edit +
+
- +
Links @@ -330,7 +323,7 @@ - @foreach (var item in Model.Invoices) + @foreach (var item in Model!.Invoices) { @@ -587,6 +580,42 @@
+// Shipping Address History + + @section scripts{ } diff --git a/src/DevBetterWeb.Web/Pages/Admin/User.cshtml.cs b/src/DevBetterWeb.Web/Pages/Admin/User.cshtml.cs index bf9e48aac..5cde144ee 100644 --- a/src/DevBetterWeb.Web/Pages/Admin/User.cshtml.cs +++ b/src/DevBetterWeb.Web/Pages/Admin/User.cshtml.cs @@ -26,6 +26,7 @@ namespace DevBetterWeb.Web.Pages.Admin; [Authorize(Roles = AuthConstants.Roles.ADMINISTRATORS)] public class UserModel : PageModel { + public List AddressHistory { get; set; } = new List(); [BindProperty] public UserPersonalUpdateModel UserPersonalUpdateModel { get; set; } = new UserPersonalUpdateModel(); [BindProperty] public UserLinksUpdateModel UserLinksUpdateModel { get; set; } = new UserLinksUpdateModel(); @@ -130,6 +131,12 @@ public async Task OnGetAsync(string userId) UserPersonalUpdateModel = new UserPersonalUpdateModel(member); UserLinksUpdateModel = new UserLinksUpdateModel(member); + AddressHistory = member.AddressHistory.OrderByDescending(a => a.UpdatedOn).Select(a => new AddressHistoryViewModel + { + Address = a.Address!.ToString(), + UpdatedOn = a.UpdatedOn + }).ToList(); + MemberSubscriptionPlans = await _subscriptionPlanRepository.ListAsync(); _logger.LogInformation($"MemberSubscriptionPlans Count: {MemberSubscriptionPlans.Count}"); @@ -271,7 +278,6 @@ public async Task OnPostUpdatePersonalInfoAsync(string userId) member.UpdateName(UserPersonalUpdateModel.FirstName, UserPersonalUpdateModel.LastName, false); member.UpdatePEInfo(UserPersonalUpdateModel.PEFriendCode, UserPersonalUpdateModel.PEUsername, false); member.UpdateAboutInfo(UserPersonalUpdateModel.AboutInfo, false); - member.UpdateAddress(UserPersonalUpdateModel.Address, false); member.UpdateShippingAddress(UserPersonalUpdateModel.Address!, UserPersonalUpdateModel.City!, UserPersonalUpdateModel.State!, UserPersonalUpdateModel.PostalCode!, UserPersonalUpdateModel.Country!, false); member.UpdateDiscord(UserPersonalUpdateModel.DiscordUsername, false); member.UpdateEmail(UserPersonalUpdateModel.Email, false); @@ -314,4 +320,10 @@ public class EmailConfirmationModel public string IsConfirmedString { get; set; } = ""; public string EditEmailConfirmationMessage { get; set; } = ""; } + + public class AddressHistoryViewModel + { + public string Address { get; set; } = string.Empty; + public DateTimeOffset UpdatedOn { get; set; } + } } diff --git a/src/DevBetterWeb.Web/Pages/Map/Index.cshtml.cs b/src/DevBetterWeb.Web/Pages/Map/Index.cshtml.cs index e59a4456c..326b18d67 100644 --- a/src/DevBetterWeb.Web/Pages/Map/Index.cshtml.cs +++ b/src/DevBetterWeb.Web/Pages/Map/Index.cshtml.cs @@ -35,7 +35,7 @@ public async Task OnGet() // Handle members that are in the database before map functionality is introduced, so they will not trigger the AddressUpdated event foreach (var member in members) { - if (member.Address is not null && (member.CityLatitude is null || member.CityLongitude is null)) + if (member.ShippingAddress is not null && (member.CityLatitude is null || member.CityLongitude is null)) { _logger.LogInformation($"Updating lat/long for {member.FirstName} {member.LastName}"); // TODO: figure out if we need to update location data here diff --git a/src/DevBetterWeb.Web/Pages/User/Details.cshtml b/src/DevBetterWeb.Web/Pages/User/Details.cshtml index 6f7a1cfc8..b8d82858b 100644 --- a/src/DevBetterWeb.Web/Pages/User/Details.cshtml +++ b/src/DevBetterWeb.Web/Pages/User/Details.cshtml @@ -24,20 +24,7 @@
Shipping Address
- Address: @Model.UserDetailsViewModel.Address -
- City: - @Model.UserDetailsViewModel.City -
- State: - @Model.UserDetailsViewModel.State -
- Country: - @Model.UserDetailsViewModel.Country -
- Postal Code: - @Model.UserDetailsViewModel.PostalCode
diff --git a/src/DevBetterWeb.Web/Pages/User/Details.cshtml.cs b/src/DevBetterWeb.Web/Pages/User/Details.cshtml.cs index 3d55775f8..d123f843a 100644 --- a/src/DevBetterWeb.Web/Pages/User/Details.cshtml.cs +++ b/src/DevBetterWeb.Web/Pages/User/Details.cshtml.cs @@ -41,9 +41,7 @@ public async Task OnGet(string userId) return NotFound(); } -#pragma warning disable CS0436 // Type conflicts with imported type UserDetailsViewModel = new UserDetailsViewModel(member!); -#pragma warning restore CS0436 // Type conflicts with imported type int percentageNum = _memberSubscriptionPeriodCalculationsService.GetPercentageProgressToAlumniStatus(member!); diff --git a/src/DevBetterWeb.Web/Pages/User/Map.cshtml.cs b/src/DevBetterWeb.Web/Pages/User/Map.cshtml.cs index a889ae898..622d35c00 100644 --- a/src/DevBetterWeb.Web/Pages/User/Map.cshtml.cs +++ b/src/DevBetterWeb.Web/Pages/User/Map.cshtml.cs @@ -34,7 +34,7 @@ public async Task OnGet(string userId) // Handle members that are in the database before map functionality is introduced, so they will not trigger the AddressUpdated event foreach (var member in members) { - if (member.Address is not null && (member.CityLatitude is null || member.CityLongitude is null)) + if (member.ShippingAddress is not null && (member.CityLatitude is null || member.CityLongitude is null)) { _logger.LogInformation($"Updating lat/long for {member.FirstName} {member.LastName}"); // TODO: figure out if we need to update location data here diff --git a/src/DevBetterWeb.Web/Pages/User/MyProfile/Index.cshtml b/src/DevBetterWeb.Web/Pages/User/MyProfile/Index.cshtml index 2fcbd77a2..873ef5120 100644 --- a/src/DevBetterWeb.Web/Pages/User/MyProfile/Index.cshtml +++ b/src/DevBetterWeb.Web/Pages/User/MyProfile/Index.cshtml @@ -24,34 +24,6 @@

@Model.UserProfileViewModel.LastName

-
- - Only administrators can view this information -

@Model.UserProfileViewModel.Address

-
- -
- - Only administrators can view this information -

@Model.UserProfileViewModel.City

-
-
- - Only administrators can view this information -

@Model.UserProfileViewModel.State

-
-
- - Only administrators can view this information -

@Model.UserProfileViewModel.Country

-
- -
- - Only administrators can view this information -

@Model.UserProfileViewModel.PostalCode

-
-

@Model.UserProfileViewModel.Birthday

@@ -72,6 +44,33 @@

+
+
+ Shipping Address +
+ +
+ @if (@Model.UserProfileViewModel.Address != "none") + { +
+ + @Model.UserProfileViewModel.Address + +
+ } + + + City, State (optional), and Country are used for map location. +
+ Full shipping address is only visible to admins and is used for shipping books and other packages to members from time to time. +
+
+
+ Edit +
+
+
+
Books You've Read diff --git a/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml b/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml index 32fbd2462..9b0cfbfb9 100644 --- a/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml +++ b/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml @@ -49,52 +49,6 @@
-
- - Only administrators can view this information - include country if - non-US - - -
- -
- - Only administrators can view this information - include country if - non-US - - -
- -
- - - Only administrators can view this information - include country if - non-US - - -
- -
- - Only administrators can view this information - include country if - non-US - - -
- -
- - Only administrators can view this information - include country if - non-US - - -
-

If set, birthday will be visible to other devBetter members and may be used to celebrate your day via Discord, coaching sessions, etc.

diff --git a/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml.cs b/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml.cs index e6cb0da04..9678ddb4a 100644 --- a/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml.cs +++ b/src/DevBetterWeb.Web/Pages/User/MyProfile/Personal.cshtml.cs @@ -80,8 +80,6 @@ public async Task OnPost() member.UpdateName(UserPersonalUpdateModel.FirstName, UserPersonalUpdateModel.LastName); member.UpdatePEInfo(UserPersonalUpdateModel.PEFriendCode, UserPersonalUpdateModel.PEUsername); member.UpdateAboutInfo(UserPersonalUpdateModel.AboutInfo); - member.UpdateAddress(UserPersonalUpdateModel.Address); - member.UpdateShippingAddress(UserPersonalUpdateModel.Address!, UserPersonalUpdateModel.City!, UserPersonalUpdateModel.State!, UserPersonalUpdateModel.PostalCode!, UserPersonalUpdateModel.Country!); member.UpdateBirthday(UserPersonalUpdateModel.BirthdayDay, UserPersonalUpdateModel.BirthdayMonth); member.UpdateDiscord(UserPersonalUpdateModel.DiscordUsername); member.UpdateEmail(UserPersonalUpdateModel.Email); diff --git a/src/DevBetterWeb.Web/Pages/User/MyProfile/ShippingAddress.cshtml b/src/DevBetterWeb.Web/Pages/User/MyProfile/ShippingAddress.cshtml new file mode 100644 index 000000000..02e2d89e1 --- /dev/null +++ b/src/DevBetterWeb.Web/Pages/User/MyProfile/ShippingAddress.cshtml @@ -0,0 +1,66 @@ +@page +@using System.Linq; +@model DevBetterWeb.Web.Pages.User.ShippingAddressModel +@{ + ViewData["Title"] = "Shipping Address"; +} + +

@ViewData["Title"]

+ + +
+
+
+
+ Shipping Address +
+
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+
+
+
+ +
+ +
+
+ + Back + + + \ No newline at end of file diff --git a/src/DevBetterWeb.Web/Pages/User/MyProfile/ShippingAddress.cshtml.cs b/src/DevBetterWeb.Web/Pages/User/MyProfile/ShippingAddress.cshtml.cs new file mode 100644 index 000000000..acd12bfc8 --- /dev/null +++ b/src/DevBetterWeb.Web/Pages/User/MyProfile/ShippingAddress.cshtml.cs @@ -0,0 +1,93 @@ +using System.Security.Claims; +using System.Threading.Tasks; +using DevBetterWeb.Core; +using DevBetterWeb.Core.Entities; +using DevBetterWeb.Core.Exceptions; +using DevBetterWeb.Core.Interfaces; +using DevBetterWeb.Core.Specs; +using DevBetterWeb.Infrastructure.Identity.Data; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace DevBetterWeb.Web.Pages.User; + +[Authorize(Roles = AuthConstants.Roles.ADMINISTRATORS_MEMBERS_ALUMNI)] +public class ShippingAddressModel : PageModel +{ + private readonly UserManager _userManager; + private readonly IMemberRegistrationService _memberRegistrationService; + private readonly IRepository _memberRepository; + + public ShippingAddressModel(UserManager userManager, + IMemberRegistrationService memberRegistrationService, + IRepository memberRepository) + { + _userManager = userManager; + _memberRegistrationService = memberRegistrationService; + _memberRepository = memberRepository; + } + + [BindProperty] + public UserShippingAddressUpdateModel UserShippingAddressUpdateModel { get; set; } = null!; + + public async Task OnGetAsync(string? userId = null) + { + var (member, actualUserId) = await GetMemberAsync(User, userId); + if (member is null && actualUserId is null) return; + if (member == null) + { + member = await _memberRegistrationService.RegisterMemberAsync(actualUserId!); + } + + UserShippingAddressUpdateModel = new UserShippingAddressUpdateModel(member); + } + + public async Task OnPost(string? userId = null) + { + if (!ModelState.IsValid) return; + + var (member, actualUserId) = await GetMemberAsync(User, userId); + if (member is null && actualUserId is null) return; + if (member is null) throw new MemberNotFoundException(actualUserId!); + + member.UpdateShippingAddress( + UserShippingAddressUpdateModel.Street, + UserShippingAddressUpdateModel.City, + UserShippingAddressUpdateModel.State, + UserShippingAddressUpdateModel.PostalCode, + UserShippingAddressUpdateModel.Country); + + await _memberRepository.UpdateAsync(member); + } + + private async Task<(Member? member, string? userId)> GetMemberAsync(ClaimsPrincipal user, string? userId = null) + { + var isAdmin = user.IsInRole(AuthConstants.Roles.ADMINISTRATORS); + + if (isAdmin && !string.IsNullOrEmpty(userId)) + { + var spec = new MemberByUserIdSpec(userId); + var member = await _memberRepository.FirstOrDefaultAsync(spec); + return (member, userId); + } + + var currentUserName = user.Identity?.Name; + if (currentUserName == null) + { + return (null, null); + } + + var applicationUser = await _userManager.FindByNameAsync(currentUserName); + if (applicationUser == null) + { + return (null, null); + } + + var userSpec = new MemberByUserIdSpec(applicationUser.Id); + var currentUserMember = await _memberRepository.FirstOrDefaultAsync(userSpec); + + return (currentUserMember, applicationUser.Id); + } +} diff --git a/src/DevBetterWeb.Web/Pages/User/UserDetailsViewModel.cs b/src/DevBetterWeb.Web/Pages/User/UserDetailsViewModel.cs index 43f2e545e..c5851a71d 100644 --- a/src/DevBetterWeb.Web/Pages/User/UserDetailsViewModel.cs +++ b/src/DevBetterWeb.Web/Pages/User/UserDetailsViewModel.cs @@ -59,16 +59,7 @@ public UserDetailsViewModel(Member member) OtherUrl = member.OtherUrl; AboutInfo = member.AboutInfo; Birthday = member.Birthday?.ToString(); - Address = member.Address; - if (member.ShippingAddress != null) - { - Address = member.ShippingAddress.Street; - City = member.ShippingAddress.City; - Country = member.ShippingAddress.Country; - PostalCode = member.ShippingAddress.PostalCode; - State = member.ShippingAddress.State; - } - + Address = member.ShippingAddress?.ToString(); Name = member.UserFullName(); PEFriendCode = member.PEFriendCode; if (!(string.IsNullOrEmpty(member.PEUsername))) diff --git a/src/DevBetterWeb.Web/Pages/User/UserPersonalUpdateModel.cs b/src/DevBetterWeb.Web/Pages/User/UserPersonalUpdateModel.cs index 516e68509..a75550c7b 100644 --- a/src/DevBetterWeb.Web/Pages/User/UserPersonalUpdateModel.cs +++ b/src/DevBetterWeb.Web/Pages/User/UserPersonalUpdateModel.cs @@ -44,15 +44,7 @@ public UserPersonalUpdateModel(Member member) AboutInfo = member.AboutInfo; FirstName = member.FirstName; LastName = member.LastName; - Address = member.Address; - if (member.ShippingAddress != null) - { - Address = member.ShippingAddress.Street; - City = member.ShippingAddress.City; - Country = member.ShippingAddress.Country; - State = member.ShippingAddress.State; - PostalCode = member.ShippingAddress.PostalCode; - } + Address = member.ShippingAddress?.ToString(); BirthdayDay = member.Birthday?.Day; BirthdayMonth = member.Birthday?.Month; Email = member.Email; diff --git a/src/DevBetterWeb.Web/Pages/User/UserProfileViewModel.cs b/src/DevBetterWeb.Web/Pages/User/UserProfileViewModel.cs index 93d047fef..33fbdfc0a 100644 --- a/src/DevBetterWeb.Web/Pages/User/UserProfileViewModel.cs +++ b/src/DevBetterWeb.Web/Pages/User/UserProfileViewModel.cs @@ -66,16 +66,7 @@ public UserProfileViewModel(Member member) string valueToUseIfNull = "none"; AboutInfo = member.AboutInfo ?? valueToUseIfNull; - Address = member.Address ?? valueToUseIfNull; - if (member.ShippingAddress != null) - { - Address = member.ShippingAddress.Street ?? valueToUseIfNull; - City = member.ShippingAddress.City ?? valueToUseIfNull; - State = member.ShippingAddress.State ?? valueToUseIfNull; - Country = member.ShippingAddress.Country ?? valueToUseIfNull; - PostalCode = member.ShippingAddress.PostalCode ?? valueToUseIfNull; - } - + Address = member.ShippingAddress?.ToString() ?? valueToUseIfNull; Birthday = member.Birthday?.ToString() ?? valueToUseIfNull; BlogUrl = member.BlogUrl ?? valueToUseIfNull; CodinGameUrl = member.CodinGameUrl ?? valueToUseIfNull; diff --git a/src/DevBetterWeb.Web/Pages/User/UserShippingAddressUpdateModel.cs b/src/DevBetterWeb.Web/Pages/User/UserShippingAddressUpdateModel.cs new file mode 100644 index 000000000..a3d64f7d4 --- /dev/null +++ b/src/DevBetterWeb.Web/Pages/User/UserShippingAddressUpdateModel.cs @@ -0,0 +1,37 @@ +using System.ComponentModel.DataAnnotations; +using DevBetterWeb.Core.Entities; + +namespace DevBetterWeb.Web.Pages.User; + +public class UserShippingAddressUpdateModel +{ +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public UserShippingAddressUpdateModel() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + + public UserShippingAddressUpdateModel(Member member) + { +#pragma warning disable CS8602 // Dereference of a possibly null reference. + this.Street = member.ShippingAddress.Street; +#pragma warning restore CS8602 // Dereference of a possibly null reference. + this.City = member.ShippingAddress.City; + this.State = member.ShippingAddress.State; + this.PostalCode = member.ShippingAddress.PostalCode; + this.Country = member.ShippingAddress.Country; + } + + [Required] + public string City { get; set; } + + [Required] + public string Country { get; set; } + + public string State { get; set; } + [Required] + public string Street { get; set; } + [Required] + public string PostalCode { get; set; } + +} diff --git a/tests/DevBetterWeb.UnitTests/Core/Entities/MemberTests/MemberUpdateAddress.cs b/tests/DevBetterWeb.UnitTests/Core/Entities/MemberTests/MemberUpdateAddress.cs index 300ebcd83..493187001 100644 --- a/tests/DevBetterWeb.UnitTests/Core/Entities/MemberTests/MemberUpdateAddress.cs +++ b/tests/DevBetterWeb.UnitTests/Core/Entities/MemberTests/MemberUpdateAddress.cs @@ -8,7 +8,7 @@ namespace DevBetterWeb.UnitTests.Core.Entities.MemberTests; public class MemberUpdateAddress { - private string _initialAddress = ""; + private string _initialStreet = ""; private string _initialCity = ""; private string _initialCountry = ""; private string _initialPostalCode = ""; @@ -16,15 +16,14 @@ public class MemberUpdateAddress private Member GetMemberWithDefaultAddress() { - _initialAddress = Guid.NewGuid().ToString(); + _initialStreet = Guid.NewGuid().ToString(); _initialCity = Guid.NewGuid().ToString(); _initialCountry = Guid.NewGuid().ToString(); _initialPostalCode = Guid.NewGuid().ToString(); _initialState = Guid.NewGuid().ToString(); var member = MemberHelpers.CreateWithDefaultConstructor(); - member.UpdateAddress(_initialAddress); - member.UpdateShippingAddress(_initialAddress, _initialCity, _initialState, _initialPostalCode, _initialCountry); + member.UpdateShippingAddress(_initialStreet, _initialCity, _initialState, _initialPostalCode, _initialCountry); member.Events.Clear(); return member; @@ -33,43 +32,48 @@ private Member GetMemberWithDefaultAddress() [Fact] public void SetsAddress() { - string newAddress = Guid.NewGuid().ToString(); + string newStreet = Guid.NewGuid().ToString(); string newCity = Guid.NewGuid().ToString(); string newCountry = Guid.NewGuid().ToString(); string newPostalCode = Guid.NewGuid().ToString(); string newState = Guid.NewGuid().ToString(); var member = GetMemberWithDefaultAddress(); - member.UpdateAddress(newAddress); - member.UpdateShippingAddress(newAddress, newCity, newState, newPostalCode, newCountry); + member.UpdateShippingAddress(newStreet, newCity, newState, newPostalCode, newCountry); - Assert.Equal(newAddress, member.Address); + Assert.Equal(newStreet, member.ShippingAddress?.Street); + Assert.Equal(newCity, member.ShippingAddress?.City); + Assert.Equal(newCountry, member.ShippingAddress?.Country); + Assert.Equal(newPostalCode, member.ShippingAddress?.PostalCode); + Assert.Equal(newState, member.ShippingAddress?.State); } [Fact] public void RecordsEventIfAddressChanges() { - string newAddress = Guid.NewGuid().ToString(); + string newStreet = Guid.NewGuid().ToString(); string newCity = Guid.NewGuid().ToString(); string newCountry = Guid.NewGuid().ToString(); string newPostalCode = Guid.NewGuid().ToString(); string newState = Guid.NewGuid().ToString(); var member = GetMemberWithDefaultAddress(); - member.UpdateAddress(newAddress); - member.UpdateShippingAddress(newAddress, newCity, newState, newPostalCode, newCountry); - var eventCreated = (MemberHomeAddressUpdatedEvent)member.Events.First(); + member.UpdateShippingAddress(newStreet, newCity, newState, newPostalCode, newCountry); + var eventCreated = (MemberAddressUpdatedEvent)member.Events.First(); Assert.Same(member, eventCreated.Member); - Assert.Equal("Address", eventCreated.UpdateDetails); - } + Assert.Equal(newStreet, member.ShippingAddress?.Street); + Assert.Equal(newCity, member.ShippingAddress?.City); + Assert.Equal(newCountry, member.ShippingAddress?.Country); + Assert.Equal(newPostalCode, member.ShippingAddress?.PostalCode); + Assert.Equal(newState, member.ShippingAddress?.State); + } [Fact] public void RecordsNoEventIfAddressDoesNotChange() { var member = GetMemberWithDefaultAddress(); - member.UpdateAddress(_initialAddress); - member.UpdateShippingAddress(_initialAddress, _initialCity, _initialState, _initialPostalCode, _initialCountry); + member.UpdateShippingAddress(_initialStreet, _initialCity, _initialState, _initialPostalCode, _initialCountry); Assert.Empty(member.Events); }