diff --git a/coffeecard/CoffeeCard.Library/Migrations/20221228163445_Payment Type.Designer.cs b/coffeecard/CoffeeCard.Library/Migrations/20221228163445_Payment Type.Designer.cs new file mode 100644 index 00000000..05d56729 --- /dev/null +++ b/coffeecard/CoffeeCard.Library/Migrations/20221228163445_Payment Type.Designer.cs @@ -0,0 +1,599 @@ +// +using System; +using CoffeeCard.Library.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace CoffeeCard.Library.Migrations +{ + [DbContext(typeof(CoffeeCardContext))] + [Migration("20221228163445_Payment Type")] + partial class PaymentType + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("dbo") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.13") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("CoffeeCard.Models.Entities.LoginAttempt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Time") + .HasColumnType("datetime2"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("LoginAttempts"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("ExperienceWorth") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfTickets") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("Visible") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("Products"); + + b.HasData( + new + { + Id = 1, + Description = "Used for filter coffee brewed with fresh ground coffee", + ExperienceWorth = 10, + Name = "Filter Coffee", + NumberOfTickets = 10, + Price = 80, + Visible = true + }, + new + { + Id = 2, + Description = "Used for specialities like espresso, cappuccino, caffe latte, cortado, americano and chai latte", + ExperienceWorth = 150, + Name = "Espresso Based", + NumberOfTickets = 10, + Price = 150, + Visible = true + }); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.ProductUserGroup", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("UserGroup") + .HasColumnType("int"); + + b.HasKey("ProductId", "UserGroup"); + + b.ToTable("ProductUserGroups"); + + b.HasData( + new + { + ProductId = 1, + UserGroup = 0 + }, + new + { + ProductId = 2, + UserGroup = 0 + }); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("FullName") + .HasColumnType("nvarchar(max)"); + + b.Property("ShortName") + .HasColumnType("nvarchar(max)"); + + b.Property("SortPriority") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Programmes"); + + b.HasData( + new + { + Id = 1, + FullName = "BSc Software Development", + ShortName = "SWU", + SortPriority = 0 + }, + new + { + Id = 2, + FullName = "BSc Global Business Informatics", + ShortName = "GBI", + SortPriority = 0 + }, + new + { + Id = 3, + FullName = "BSc Digital Design and Interactive Technologies", + ShortName = "BDDIT", + SortPriority = 0 + }, + new + { + Id = 4, + FullName = "MSc Digital Design and Interactive Technologies", + ShortName = "KDDIT", + SortPriority = 0 + }, + new + { + Id = 5, + FullName = "MSc Digital Innovation and Management", + ShortName = "DIM", + SortPriority = 0 + }, + new + { + Id = 6, + FullName = "MSc E-Business", + ShortName = "E-BUSS", + SortPriority = 0 + }, + new + { + Id = 7, + FullName = "MSc Games - Design and Theory", + ShortName = "GAMES/DT", + SortPriority = 0 + }, + new + { + Id = 8, + FullName = "MSc Games - Technology", + ShortName = "GAMES/Tech", + SortPriority = 0 + }, + new + { + Id = 9, + FullName = "MSc Computer Science", + ShortName = "CS", + SortPriority = 0 + }, + new + { + Id = 10, + FullName = "MSc Software Development (Design)", + ShortName = "SDT", + SortPriority = 0 + }, + new + { + Id = 11, + FullName = "Employee", + ShortName = "Employee", + SortPriority = 0 + }, + new + { + Id = 12, + FullName = "Other", + ShortName = "Other", + SortPriority = 0 + }, + new + { + Id = 13, + FullName = "BSc Data Science", + ShortName = "DS", + SortPriority = 0 + }); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Completed") + .HasColumnType("bit"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("NumberOfTickets") + .HasColumnType("int"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("PaymentType") + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("ProductName") + .HasColumnType("nvarchar(max)"); + + b.Property("PurchasedBy_Id") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("PurchasedBy_Id"); + + b.HasIndex("TransactionId"); + + b.ToTable("Purchases"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Statistic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ExpiryDate") + .HasColumnType("datetime2"); + + b.Property("LastSwipe") + .HasColumnType("datetime2"); + + b.Property("Preset") + .HasColumnType("int"); + + b.Property("SwipeCount") + .HasColumnType("int"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("Statistics"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUsed") + .HasColumnType("datetime2"); + + b.Property("IsUsed") + .HasColumnType("bit"); + + b.Property("Owner_Id") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("Purchase_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Owner_Id"); + + b.HasIndex("Purchase_Id"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Token", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("TokenHash") + .HasColumnType("nvarchar(max)"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUpdated") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Experience") + .HasColumnType("int"); + + b.Property("IsVerified") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PrivacyActivated") + .HasColumnType("bit"); + + b.Property("Programme_Id") + .HasColumnType("int"); + + b.Property("Salt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserGroup") + .HasColumnType("int"); + + b.Property("UserState") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Programme_Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Voucher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Code") + .HasColumnType("nvarchar(max)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUsed") + .HasColumnType("datetime2"); + + b.Property("Product_Id") + .HasColumnType("int"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Product_Id"); + + b.HasIndex("User_Id"); + + b.ToTable("Vouchers"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.WebhookConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("LastUpdated") + .HasColumnType("datetime2"); + + b.Property("SignatureKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("WebhookConfigurations"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.LoginAttempt", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("LoginAttempts") + .HasForeignKey("User_Id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.ProductUserGroup", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany("ProductUserGroup") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "PurchasedBy") + .WithMany("Purchases") + .HasForeignKey("PurchasedBy_Id"); + + b.Navigation("PurchasedBy"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Statistic", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("Statistics") + .HasForeignKey("User_Id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Ticket", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "Owner") + .WithMany("Tickets") + .HasForeignKey("Owner_Id"); + + b.HasOne("CoffeeCard.Models.Entities.Purchase", "Purchase") + .WithMany("Tickets") + .HasForeignKey("Purchase_Id"); + + b.Navigation("Owner"); + + b.Navigation("Purchase"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Token", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("Tokens") + .HasForeignKey("User_Id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.HasOne("CoffeeCard.Models.Entities.Programme", "Programme") + .WithMany("Users") + .HasForeignKey("Programme_Id"); + + b.Navigation("Programme"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Voucher", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany() + .HasForeignKey("Product_Id"); + + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany() + .HasForeignKey("User_Id"); + + b.Navigation("Product"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Product", b => + { + b.Navigation("ProductUserGroup"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.Navigation("Tickets"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.Navigation("LoginAttempts"); + + b.Navigation("Purchases"); + + b.Navigation("Statistics"); + + b.Navigation("Tickets"); + + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/coffeecard/CoffeeCard.Library/Migrations/20221228163445_Payment Type.cs b/coffeecard/CoffeeCard.Library/Migrations/20221228163445_Payment Type.cs new file mode 100644 index 00000000..676351f4 --- /dev/null +++ b/coffeecard/CoffeeCard.Library/Migrations/20221228163445_Payment Type.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace CoffeeCard.Library.Migrations +{ + public partial class PaymentType : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PaymentType", + schema: "dbo", + table: "Purchases", + type: "nvarchar(max)", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PaymentType", + schema: "dbo", + table: "Purchases"); + } + } +} diff --git a/coffeecard/CoffeeCard.Library/Migrations/20221228170637_Purchase-Product ForeignKey reference.Designer.cs b/coffeecard/CoffeeCard.Library/Migrations/20221228170637_Purchase-Product ForeignKey reference.Designer.cs new file mode 100644 index 00000000..3125efbb --- /dev/null +++ b/coffeecard/CoffeeCard.Library/Migrations/20221228170637_Purchase-Product ForeignKey reference.Designer.cs @@ -0,0 +1,611 @@ +// +using System; +using CoffeeCard.Library.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace CoffeeCard.Library.Migrations +{ + [DbContext(typeof(CoffeeCardContext))] + [Migration("20221228170637_Purchase-Product ForeignKey reference")] + partial class PurchaseProductForeignKeyreference + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("dbo") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.13") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("CoffeeCard.Models.Entities.LoginAttempt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Time") + .HasColumnType("datetime2"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("LoginAttempts"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("ExperienceWorth") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfTickets") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("Visible") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("Products"); + + b.HasData( + new + { + Id = 1, + Description = "Used for filter coffee brewed with fresh ground coffee", + ExperienceWorth = 10, + Name = "Filter Coffee", + NumberOfTickets = 10, + Price = 80, + Visible = true + }, + new + { + Id = 2, + Description = "Used for specialities like espresso, cappuccino, caffe latte, cortado, americano and chai latte", + ExperienceWorth = 150, + Name = "Espresso Based", + NumberOfTickets = 10, + Price = 150, + Visible = true + }); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.ProductUserGroup", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("UserGroup") + .HasColumnType("int"); + + b.HasKey("ProductId", "UserGroup"); + + b.ToTable("ProductUserGroups"); + + b.HasData( + new + { + ProductId = 1, + UserGroup = 0 + }, + new + { + ProductId = 2, + UserGroup = 0 + }); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("FullName") + .HasColumnType("nvarchar(max)"); + + b.Property("ShortName") + .HasColumnType("nvarchar(max)"); + + b.Property("SortPriority") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Programmes"); + + b.HasData( + new + { + Id = 1, + FullName = "BSc Software Development", + ShortName = "SWU", + SortPriority = 0 + }, + new + { + Id = 2, + FullName = "BSc Global Business Informatics", + ShortName = "GBI", + SortPriority = 0 + }, + new + { + Id = 3, + FullName = "BSc Digital Design and Interactive Technologies", + ShortName = "BDDIT", + SortPriority = 0 + }, + new + { + Id = 4, + FullName = "MSc Digital Design and Interactive Technologies", + ShortName = "KDDIT", + SortPriority = 0 + }, + new + { + Id = 5, + FullName = "MSc Digital Innovation and Management", + ShortName = "DIM", + SortPriority = 0 + }, + new + { + Id = 6, + FullName = "MSc E-Business", + ShortName = "E-BUSS", + SortPriority = 0 + }, + new + { + Id = 7, + FullName = "MSc Games - Design and Theory", + ShortName = "GAMES/DT", + SortPriority = 0 + }, + new + { + Id = 8, + FullName = "MSc Games - Technology", + ShortName = "GAMES/Tech", + SortPriority = 0 + }, + new + { + Id = 9, + FullName = "MSc Computer Science", + ShortName = "CS", + SortPriority = 0 + }, + new + { + Id = 10, + FullName = "MSc Software Development (Design)", + ShortName = "SDT", + SortPriority = 0 + }, + new + { + Id = 11, + FullName = "Employee", + ShortName = "Employee", + SortPriority = 0 + }, + new + { + Id = 12, + FullName = "Other", + ShortName = "Other", + SortPriority = 0 + }, + new + { + Id = 13, + FullName = "BSc Data Science", + ShortName = "DS", + SortPriority = 0 + }); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Completed") + .HasColumnType("bit"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("NumberOfTickets") + .HasColumnType("int"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("PaymentType") + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("ProductName") + .HasColumnType("nvarchar(max)"); + + b.Property("PurchasedBy_Id") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("ProductId"); + + b.HasIndex("PurchasedBy_Id"); + + b.HasIndex("TransactionId"); + + b.ToTable("Purchases"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Statistic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ExpiryDate") + .HasColumnType("datetime2"); + + b.Property("LastSwipe") + .HasColumnType("datetime2"); + + b.Property("Preset") + .HasColumnType("int"); + + b.Property("SwipeCount") + .HasColumnType("int"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("Statistics"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUsed") + .HasColumnType("datetime2"); + + b.Property("IsUsed") + .HasColumnType("bit"); + + b.Property("Owner_Id") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("Purchase_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Owner_Id"); + + b.HasIndex("Purchase_Id"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Token", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("TokenHash") + .HasColumnType("nvarchar(max)"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUpdated") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Experience") + .HasColumnType("int"); + + b.Property("IsVerified") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PrivacyActivated") + .HasColumnType("bit"); + + b.Property("Programme_Id") + .HasColumnType("int"); + + b.Property("Salt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserGroup") + .HasColumnType("int"); + + b.Property("UserState") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Programme_Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Voucher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Code") + .HasColumnType("nvarchar(max)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUsed") + .HasColumnType("datetime2"); + + b.Property("Product_Id") + .HasColumnType("int"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Product_Id"); + + b.HasIndex("User_Id"); + + b.ToTable("Vouchers"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.WebhookConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("LastUpdated") + .HasColumnType("datetime2"); + + b.Property("SignatureKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("WebhookConfigurations"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.LoginAttempt", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("LoginAttempts") + .HasForeignKey("User_Id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.ProductUserGroup", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany("ProductUserGroup") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany("Purchases") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CoffeeCard.Models.Entities.User", "PurchasedBy") + .WithMany("Purchases") + .HasForeignKey("PurchasedBy_Id"); + + b.Navigation("Product"); + + b.Navigation("PurchasedBy"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Statistic", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("Statistics") + .HasForeignKey("User_Id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Ticket", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "Owner") + .WithMany("Tickets") + .HasForeignKey("Owner_Id"); + + b.HasOne("CoffeeCard.Models.Entities.Purchase", "Purchase") + .WithMany("Tickets") + .HasForeignKey("Purchase_Id"); + + b.Navigation("Owner"); + + b.Navigation("Purchase"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Token", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("Tokens") + .HasForeignKey("User_Id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.HasOne("CoffeeCard.Models.Entities.Programme", "Programme") + .WithMany("Users") + .HasForeignKey("Programme_Id"); + + b.Navigation("Programme"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Voucher", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany() + .HasForeignKey("Product_Id"); + + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany() + .HasForeignKey("User_Id"); + + b.Navigation("Product"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Product", b => + { + b.Navigation("ProductUserGroup"); + + b.Navigation("Purchases"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.Navigation("Tickets"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.Navigation("LoginAttempts"); + + b.Navigation("Purchases"); + + b.Navigation("Statistics"); + + b.Navigation("Tickets"); + + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/coffeecard/CoffeeCard.Library/Migrations/20221228170637_Purchase-Product ForeignKey reference.cs b/coffeecard/CoffeeCard.Library/Migrations/20221228170637_Purchase-Product ForeignKey reference.cs new file mode 100644 index 00000000..03881747 --- /dev/null +++ b/coffeecard/CoffeeCard.Library/Migrations/20221228170637_Purchase-Product ForeignKey reference.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace CoffeeCard.Library.Migrations +{ + public partial class PurchaseProductForeignKeyreference : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateIndex( + name: "IX_Purchases_ProductId", + schema: "dbo", + table: "Purchases", + column: "ProductId"); + + migrationBuilder.AddForeignKey( + name: "FK_Purchases_Products_ProductId", + schema: "dbo", + table: "Purchases", + column: "ProductId", + principalSchema: "dbo", + principalTable: "Products", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Purchases_Products_ProductId", + schema: "dbo", + table: "Purchases"); + + migrationBuilder.DropIndex( + name: "IX_Purchases_ProductId", + schema: "dbo", + table: "Purchases"); + } + } +} diff --git a/coffeecard/CoffeeCard.Library/Migrations/20240917171840_RemovePaymentType.Designer.cs b/coffeecard/CoffeeCard.Library/Migrations/20240917171840_RemovePaymentType.Designer.cs new file mode 100644 index 00000000..dc732969 --- /dev/null +++ b/coffeecard/CoffeeCard.Library/Migrations/20240917171840_RemovePaymentType.Designer.cs @@ -0,0 +1,653 @@ +// +using System; +using CoffeeCard.Library.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CoffeeCard.Library.Migrations +{ + [DbContext(typeof(CoffeeCardContext))] + [Migration("20240917171840_RemovePaymentType")] + partial class RemovePaymentType + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("dbo") + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CoffeeCard.Models.Entities.LoginAttempt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Time") + .HasColumnType("datetime2"); + + b.Property("User_Id") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("User_Id"); + + b.ToTable("LoginAttempts", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.MenuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Active") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("MenuItems", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.MenuItemProduct", b => + { + b.Property("MenuItemId") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.HasKey("MenuItemId", "ProductId"); + + b.HasIndex("ProductId"); + + b.ToTable("MenuItemProducts", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.PosPurhase", b => + { + b.Property("PurchaseId") + .HasColumnType("int"); + + b.Property("BaristaInitials") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("PurchaseId"); + + b.ToTable("PosPurchases", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ExperienceWorth") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfTickets") + .HasColumnType("int"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("Visible") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("Products", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.ProductUserGroup", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("UserGroup") + .HasColumnType("int"); + + b.HasKey("ProductId", "UserGroup"); + + b.ToTable("ProductUserGroups", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("FullName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SortPriority") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Programmes", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("ExternalTransactionId") + .HasColumnType("nvarchar(450)"); + + b.Property("NumberOfTickets") + .HasColumnType("int"); + + b.Property("OrderId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Price") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("ProductName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PurchasedById") + .HasColumnType("int") + .HasColumnName("PurchasedBy_Id"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ExternalTransactionId"); + + b.HasIndex("OrderId"); + + b.HasIndex("ProductId"); + + b.HasIndex("PurchasedById"); + + b.ToTable("Purchases", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Statistic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ExpiryDate") + .HasColumnType("datetime2"); + + b.Property("LastSwipe") + .HasColumnType("datetime2"); + + b.Property("Preset") + .HasColumnType("int"); + + b.Property("SwipeCount") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("User_Id"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("Preset", "ExpiryDate"); + + b.ToTable("Statistics", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUsed") + .HasColumnType("datetime2"); + + b.Property("IsUsed") + .HasColumnType("bit"); + + b.Property("OwnerId") + .HasColumnType("int") + .HasColumnName("Owner_Id"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("PurchaseId") + .HasColumnType("int") + .HasColumnName("Purchase_Id"); + + b.Property("UsedOnMenuItemId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("UsedOnMenuItemId"); + + b.ToTable("Tickets", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Token", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("TokenHash") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("User_Id"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUpdated") + .HasColumnType("datetime2"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Experience") + .HasColumnType("int"); + + b.Property("IsVerified") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PrivacyActivated") + .HasColumnType("bit"); + + b.Property("ProgrammeId") + .HasColumnType("int") + .HasColumnName("Programme_Id"); + + b.Property("Salt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserGroup") + .HasColumnType("int"); + + b.Property("UserState") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("Name"); + + b.HasIndex("ProgrammeId"); + + b.HasIndex("UserGroup"); + + b.ToTable("Users", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Voucher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("DateCreated") + .HasColumnType("datetime2"); + + b.Property("DateUsed") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("ProductId") + .HasColumnType("int") + .HasColumnName("Product_Id"); + + b.Property("PurchaseId") + .HasColumnType("int"); + + b.Property("Requester") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("User_Id"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("ProductId"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("UserId"); + + b.ToTable("Vouchers", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.WebhookConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("LastUpdated") + .HasColumnType("datetime2"); + + b.Property("SignatureKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("WebhookConfigurations", "dbo"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.LoginAttempt", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("LoginAttempts") + .HasForeignKey("User_Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.MenuItemProduct", b => + { + b.HasOne("CoffeeCard.Models.Entities.MenuItem", "MenuItem") + .WithMany("MenuItemProducts") + .HasForeignKey("MenuItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany("MenuItemProducts") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MenuItem"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.PosPurhase", b => + { + b.HasOne("CoffeeCard.Models.Entities.Purchase", "Purchase") + .WithMany() + .HasForeignKey("PurchaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Purchase"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.ProductUserGroup", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany("ProductUserGroup") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany("Purchases") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CoffeeCard.Models.Entities.User", "PurchasedBy") + .WithMany("Purchases") + .HasForeignKey("PurchasedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + + b.Navigation("PurchasedBy"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Statistic", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("Statistics") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Ticket", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "Owner") + .WithMany("Tickets") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("CoffeeCard.Models.Entities.Purchase", "Purchase") + .WithMany("Tickets") + .HasForeignKey("PurchaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CoffeeCard.Models.Entities.MenuItem", "UsedOnMenuItem") + .WithMany() + .HasForeignKey("UsedOnMenuItemId"); + + b.Navigation("Owner"); + + b.Navigation("Purchase"); + + b.Navigation("UsedOnMenuItem"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Token", b => + { + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany("Tokens") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.HasOne("CoffeeCard.Models.Entities.Programme", "Programme") + .WithMany("Users") + .HasForeignKey("ProgrammeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Programme"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Voucher", b => + { + b.HasOne("CoffeeCard.Models.Entities.Product", "Product") + .WithMany() + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("CoffeeCard.Models.Entities.Purchase", "Purchase") + .WithMany() + .HasForeignKey("PurchaseId"); + + b.HasOne("CoffeeCard.Models.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Product"); + + b.Navigation("Purchase"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.MenuItem", b => + { + b.Navigation("MenuItemProducts"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Product", b => + { + b.Navigation("MenuItemProducts"); + + b.Navigation("ProductUserGroup"); + + b.Navigation("Purchases"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => + { + b.Navigation("Tickets"); + }); + + modelBuilder.Entity("CoffeeCard.Models.Entities.User", b => + { + b.Navigation("LoginAttempts"); + + b.Navigation("Purchases"); + + b.Navigation("Statistics"); + + b.Navigation("Tickets"); + + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/coffeecard/CoffeeCard.Library/Migrations/20240917171840_RemovePaymentType.cs b/coffeecard/CoffeeCard.Library/Migrations/20240917171840_RemovePaymentType.cs new file mode 100644 index 00000000..6c564dc3 --- /dev/null +++ b/coffeecard/CoffeeCard.Library/Migrations/20240917171840_RemovePaymentType.cs @@ -0,0 +1,82 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CoffeeCard.Library.Migrations +{ + /// + public partial class RemovePaymentType : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Purchases_Users_PurchasedBy_Id", + schema: "dbo", + table: "Purchases"); + + migrationBuilder.DropIndex( + name: "IX_Purchases_OrderId", + schema: "dbo", + table: "Purchases"); + + migrationBuilder.DropColumn( + name: "PaymentType", + schema: "dbo", + table: "Purchases"); + + migrationBuilder.CreateIndex( + name: "IX_Purchases_OrderId", + schema: "dbo", + table: "Purchases", + column: "OrderId"); + + migrationBuilder.AddForeignKey( + name: "FK_Purchases_Users_PurchasedBy_Id", + schema: "dbo", + table: "Purchases", + column: "PurchasedBy_Id", + principalSchema: "dbo", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Purchases_Users_PurchasedBy_Id", + schema: "dbo", + table: "Purchases"); + + migrationBuilder.DropIndex( + name: "IX_Purchases_OrderId", + schema: "dbo", + table: "Purchases"); + + migrationBuilder.AddColumn( + name: "PaymentType", + schema: "dbo", + table: "Purchases", + type: "nvarchar(max)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Purchases_OrderId", + schema: "dbo", + table: "Purchases", + column: "OrderId", + unique: true); + + migrationBuilder.AddForeignKey( + name: "FK_Purchases_Users_PurchasedBy_Id", + schema: "dbo", + table: "Purchases", + column: "PurchasedBy_Id", + principalSchema: "dbo", + principalTable: "Users", + principalColumn: "Id"); + } + } +} diff --git a/coffeecard/CoffeeCard.Library/Migrations/CoffeeCardContextModelSnapshot.cs b/coffeecard/CoffeeCard.Library/Migrations/CoffeeCardContextModelSnapshot.cs index a683fc32..3b1d9379 100644 --- a/coffeecard/CoffeeCard.Library/Migrations/CoffeeCardContextModelSnapshot.cs +++ b/coffeecard/CoffeeCard.Library/Migrations/CoffeeCardContextModelSnapshot.cs @@ -213,8 +213,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ExternalTransactionId"); - b.HasIndex("OrderId") - .IsUnique(); + b.HasIndex("OrderId"); b.HasIndex("ProductId"); @@ -514,7 +513,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("CoffeeCard.Models.Entities.Purchase", b => { b.HasOne("CoffeeCard.Models.Entities.Product", "Product") - .WithMany() + .WithMany("Purchases") .HasForeignKey("ProductId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -619,6 +618,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("MenuItemProducts"); b.Navigation("ProductUserGroup"); + + b.Navigation("Purchases"); }); modelBuilder.Entity("CoffeeCard.Models.Entities.Programme", b => diff --git a/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs b/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs index 14db8914..0a2422a5 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs @@ -136,7 +136,7 @@ private static void CheckUserIsAllowedToPurchaseProduct(User user, InitiatePurch ExternalTransactionId = transactionId, PurchasedBy = user, Status = purchaseStatus, - Type = purchaseRequest.PaymentType.toPurchaseType() + // FIXME State management }; return (purchase, paymentDetails); @@ -156,7 +156,16 @@ public async Task GetPurchase(int purchaseId, User user) $"No purchase was found by Purchase Id: {purchaseId} and User Id: {user.Id}"); } - var paymentDetails = await _mobilePayPaymentsService.GetPayment(Guid.Parse(purchase.ExternalTransactionId)); + PaymentDetails paymentDetails; + try + { + paymentDetails = await _mobilePayPaymentsService.GetPayment(Guid.Parse(purchase.ExternalTransactionId)); + } + catch (MobilePay.Exception.v2.MobilePayApiException) + { + paymentDetails = new FreePurchasePaymentDetails(purchase.OrderId); + } + return new SinglePurchaseResponse { @@ -181,7 +190,7 @@ public async Task> GetPurchases(User user) ProductName = p.ProductName, NumberOfTickets = p.NumberOfTickets, TotalAmount = p.Price, - PurchaseStatus = p.Status + PurchaseStatus = p.Status, }) .ToListAsync(); } diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/SimplePurchaseResponse.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/SimplePurchaseResponse.cs index d260f381..239e5fe1 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/SimplePurchaseResponse.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/SimplePurchaseResponse.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json; namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase { @@ -13,7 +14,7 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase /// "productId": 1, /// "productName": "Filter coffee", /// "totalAmount": 300, - /// "purchaseStatus": "Completed" + /// "purchaseStatus": "Completed", /// } /// public class SimplePurchaseResponse diff --git a/coffeecard/CoffeeCard.Models/Entities/Product.cs b/coffeecard/CoffeeCard.Models/Entities/Product.cs index c3fd0140..461dc3e5 100644 --- a/coffeecard/CoffeeCard.Models/Entities/Product.cs +++ b/coffeecard/CoffeeCard.Models/Entities/Product.cs @@ -25,6 +25,8 @@ public sealed class Product : IEquatable public ICollection ProductUserGroup { get; set; } + public ICollection Purchases { get; set; } + /// /// The menu item(s) that this product is eligible to redeem /// diff --git a/coffeecard/CoffeeCard.Models/Entities/Purchase.cs b/coffeecard/CoffeeCard.Models/Entities/Purchase.cs index be03aab8..619bb3e6 100644 --- a/coffeecard/CoffeeCard.Models/Entities/Purchase.cs +++ b/coffeecard/CoffeeCard.Models/Entities/Purchase.cs @@ -6,8 +6,8 @@ namespace CoffeeCard.Models.Entities { - // TODO Should me marked as unique - [Index(nameof(OrderId), IsUnique = true)] + // FIXME Should me marked as unique + [Index(nameof(OrderId))] [Index(nameof(ExternalTransactionId))] public class Purchase { @@ -28,13 +28,14 @@ public class Purchase /// /// Id of Product purchased /// - /// + /// Product Id /// 2 public int ProductId { get; set; } /// - /// Product purchases + /// Product purchased /// + /// Product public Product Product { get; set; } /// @@ -73,7 +74,6 @@ public class Purchase /// 186d2b31-ff25-4414-9fd1-bfe9807fa8b7 public string? ExternalTransactionId { get; set; } - // Status is nullable for migration purposes /// /// Purchase Status. The status should also reflect the status at the external payment provider /// diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs index 4deddf42..7bc98909 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs @@ -252,7 +252,7 @@ public async Task InitiatePurchaseAddsTicketsToUserWhenFree(Product product) }; // Act - var purchaseResponse = await purchaseService.InitiatePurchase(request, user); + await purchaseService.InitiatePurchase(request, user); // Assert var userUpdated = await context.Users.FindAsync(user.Id); @@ -261,6 +261,137 @@ public async Task InitiatePurchaseAddsTicketsToUserWhenFree(Product product) Assert.Equal(product.NumberOfTickets, userUpdated.Tickets.Count); } + [Fact(DisplayName = "GetPurchase calls MobilePay Api when Payment Type is MobilePay")] + public async Task GetPurchaseCallsMobilePayApiWhenPaymentTypeIsMobilePay() + { + // Arrange + var builder = new DbContextOptionsBuilder() + .UseInMemoryDatabase(nameof(GetPurchaseCallsMobilePayApiWhenPaymentTypeIsMobilePay)); + + var databaseSettings = new DatabaseSettings + { + SchemaName = "test" + }; + var environmentSettings = new EnvironmentSettings() + { + EnvironmentType = EnvironmentType.Test + }; + + await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings); + + var user = new User + { + Id = 1, + Name = "User1", + Email = "email@email.test", + Password = "password", + Salt = "salt", + DateCreated = new DateTime(year: 2020, month: 11, day: 11), + IsVerified = true, + PrivacyActivated = false, + UserGroup = UserGroup.Customer, + UserState = UserState.Active + }; + await context.AddAsync(user); + + var purchase = new Purchase() + { + Id = 1, + ProductName = "Coffee clip card", + ProductId = 1, + Price = 100, + NumberOfTickets = 10, + DateCreated = DateTime.UtcNow, + OrderId = Guid.NewGuid().ToString(), + ExternalTransactionId = Guid.NewGuid().ToString(), + Status = PurchaseStatus.Completed, + PurchasedBy = user + }; + await context.AddAsync(purchase); + await context.SaveChangesAsync(); + + var mobilePayService = new Mock(); + mobilePayService.Setup(mp => mp.GetPayment(Guid.Parse(purchase.ExternalTransactionId))).ReturnsAsync( + new MobilePayPaymentDetails(purchase.OrderId, "redirect", purchase.ExternalTransactionId)); + + var mailService = new Mock(); + var productService = new ProductService(context); + var ticketService = new TicketService(context, new Mock().Object); + + var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, + mailService.Object, productService); + + // Act + var result = await purchaseService.GetPurchase(purchase.Id, user); + + // Assert + mobilePayService.Verify(mp => mp.GetPayment(Guid.Parse(purchase.ExternalTransactionId)), Times.Once); + } + + [Fact(DisplayName = "GetPurchase doesnt calls MobilePay Api when Payment Type is FreePurchase")] + public async Task GetPurchaseDoesntCallsMobilePayApiWhenPaymentTypeIsFreePurchase() + { + // Arrange + var builder = new DbContextOptionsBuilder() + .UseInMemoryDatabase(nameof(GetPurchaseDoesntCallsMobilePayApiWhenPaymentTypeIsFreePurchase)); + + var databaseSettings = new DatabaseSettings + { + SchemaName = "test" + }; + var environmentSettings = new EnvironmentSettings() + { + EnvironmentType = EnvironmentType.Test + }; + + await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings); + + var user = new User + { + Id = 1, + Name = "User1", + Email = "email@email.test", + Password = "password", + Salt = "salt", + DateCreated = new DateTime(year: 2020, month: 11, day: 11), + IsVerified = true, + PrivacyActivated = false, + UserGroup = UserGroup.Customer, + UserState = UserState.Active + }; + await context.AddAsync(user); + + var purchase = new Purchase() + { + Id = 1, + ProductName = "Coffee clip card", + ProductId = 1, + Price = 100, + NumberOfTickets = 10, + DateCreated = DateTime.UtcNow, + OrderId = Guid.NewGuid().ToString(), + ExternalTransactionId = Guid.NewGuid().ToString(), + Status = PurchaseStatus.Completed, + PurchasedBy = user + }; + await context.AddAsync(purchase); + await context.SaveChangesAsync(); + + var mobilePayService = new Mock(); + var mailService = new Mock(); + var productService = new ProductService(context); + var ticketService = new TicketService(context, new Mock().Object); + + var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, + mailService.Object, productService); + + // Act + var result = await purchaseService.GetPurchase(purchase.Id, user); + + // Assert + mobilePayService.Verify(mp => mp.GetPayment(Guid.Parse(purchase.ExternalTransactionId)), Times.Never); + } + public static IEnumerable ProductGenerator() { var pug = new List { new ProductUserGroup { ProductId = 1 } }; diff --git a/coffeecard/CoffeeCard.WebApi/Controllers/MobilePayController.cs b/coffeecard/CoffeeCard.WebApi/Controllers/MobilePayController.cs deleted file mode 100644 index 97a25799..00000000 --- a/coffeecard/CoffeeCard.WebApi/Controllers/MobilePayController.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Threading.Tasks; -using CoffeeCard.Models.DataTransferObjects; -using CoffeeCard.Models.DataTransferObjects.MobilePay; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace CoffeeCard.WebApi.Controllers -{ - // TODO: Remove this Controller after June 2023 - - /// - /// Controller for initiating and completing a purchase with MobilePay - /// - [ApiController] - [ApiVersion("1")] - [Route("api/v{version:apiVersion}/[controller]")] - [Authorize] - public class MobilePayController : ControllerBase - { - /// - /// Initializes a new instance of the class. - /// - public MobilePayController() - { - } - - /// - /// Initiates a purchase from the given productId and returns an orderId - /// - /// Initiate purchase request - /// Response with order id - /// Deprecated - [HttpPost("initiate")] - [Obsolete(message: "Replaced by Purchases API v2")] - [ProducesResponseType(typeof(void), StatusCodes.Status410Gone)] - public ActionResult InitiatePurchase([FromBody] InitiatePurchaseDto initiatePurchaseDto) - { - return StatusCode(StatusCodes.Status410Gone); - } - - /// - /// Validates the purchase against MobilePay and delivers the tickets if succeeded - /// - /// Complete purchase request with MobilePay reference - /// Deprecated - [HttpPost("complete")] - [Obsolete(message: "Replaced by Purchases API v2")] - [ProducesResponseType(typeof(void), StatusCodes.Status410Gone)] - public ActionResult CompletePurchase([FromBody] CompletePurchaseDto dto) - { - return StatusCode(StatusCodes.Status410Gone); - } - } -} \ No newline at end of file