From 86bec71c3ea22fa24fabb50931cad50a7104b857 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Mon, 18 Sep 2023 01:35:49 +0700 Subject: [PATCH 01/53] Update new database --- src/Domain/Entities/Customer.cs | 28 +- src/Domain/Entities/LaundryStore.cs | 31 +- src/Domain/Entities/Order.cs | 37 +- src/Domain/Entities/OrderHistory.cs | 25 +- src/Domain/Entities/PaymentMethod.cs | 2 +- src/Domain/Entities/Staff.cs | 24 +- .../Entities/{StaffTrip.cs => Staff_Trip.cs} | 29 +- src/Domain/Entities/Transaction.cs | 20 +- src/Domain/Entities/Validation/Validate.cs | 36 +- .../Identity/ApplicationUser.cs | 3 +- src/Infrastructure/Infrastructure.csproj | 4 + .../Persistence/ApplicationDbContext.cs | 8 +- .../00000000000000_InitialCreate.Designer.cs | 539 --------- .../00000000000000_InitialCreate.cs | 380 ------ .../20230914161433_InitMigration.Designer.cs | 540 --------- .../20230914161433_InitMigration.cs | 22 - .../20230914220515_InitialDatabase.cs | 413 ------- ...0230914221506_InitialDatabase2.Designer.cs | 1072 ----------------- .../20230914221506_InitialDatabase2.cs | 48 - ...20230917182804_OptimizeEntity.Designer.cs} | 169 ++- .../20230917182804_OptimizeEntity.cs | 782 ++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 315 ++--- src/WebUI/appsettings.json | 2 +- 23 files changed, 1148 insertions(+), 3381 deletions(-) rename src/Domain/Entities/{StaffTrip.cs => Staff_Trip.cs} (60%) delete mode 100644 src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.Designer.cs delete mode 100644 src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.cs delete mode 100644 src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.Designer.cs delete mode 100644 src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.cs delete mode 100644 src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.cs delete mode 100644 src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.Designer.cs delete mode 100644 src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.cs rename src/Infrastructure/Persistence/Migrations/{20230914220515_InitialDatabase.Designer.cs => 20230917182804_OptimizeEntity.Designer.cs} (91%) create mode 100644 src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs diff --git a/src/Domain/Entities/Customer.cs b/src/Domain/Entities/Customer.cs index c7c988e..2e2ef54 100644 --- a/src/Domain/Entities/Customer.cs +++ b/src/Domain/Entities/Customer.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using System.Text.RegularExpressions; using SWD_Laundry_Backend.Domain.Entities.Validation; using SWD_Laundry_Backend.Domain.IdentityModel; @@ -9,25 +8,28 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Customer : BaseAuditableEntity { - public string Address { get; set; } + public string Name { get; set; } + //public string Address { get; set; } + + #region Relationship + + [ForeignKey("Building")] + public int BuildingID { get; set; } - /// - /// Relationship - /// - /// [ForeignKey("Wallet")] public int WalletID { get; set; } [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } + public Building Building { get; set; } public Wallet Wallet { get; set; } public ApplicationUser ApplicationUser { get; set; } - /// - /// Special attributes - /// - /// + #endregion Relationship + + #region Special Attribute + private string _email; private string _phone; @@ -39,7 +41,7 @@ public string Email { _email = new Validate().IsValidEmail(value) ? value - : throw new ArgumentException("Not valid mail."); + : throw new ArgumentException("Invalid email."); } } @@ -50,7 +52,9 @@ public string Phone { _phone = new Validate().IsValidPhone(value) ? value - : throw new ArgumentException("Not valid phone."); + : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); } } + + #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs index b87c98e..33163d5 100644 --- a/src/Domain/Entities/LaundryStore.cs +++ b/src/Domain/Entities/LaundryStore.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SWD_Laundry_Backend.Domain.Entities.Validation; +using SWD_Laundry_Backend.Domain.Entities.Validation; using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Domain.Entities; @@ -11,12 +6,14 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class LaundryStore : BaseAuditableEntity { + public string Name { get; set; } public string Address { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public bool Status { get; set; } + + #region Relationship - /// - /// Relationship - /// - /// public string ApplicationUserID { get; set; } public int WalletID { get; set; } @@ -24,10 +21,10 @@ public class LaundryStore : BaseAuditableEntity public ApplicationUser ApplicationUser { get; set; } public Wallet Wallet { get; set; } - /// - /// Special attributes - /// - /// + #endregion Relationship + + #region Special Attribute + private string _email; private string _phone; @@ -39,7 +36,7 @@ public string Email { _email = new Validate().IsValidEmail(value) ? value - : throw new ArgumentException("Not valid mail."); + : throw new ArgumentException("Invalid email."); } } @@ -50,7 +47,9 @@ public string Phone { _phone = new Validate().IsValidPhone(value) ? value - : throw new ArgumentException("Not valid phone."); + : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); } } + + #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs index 9e7e1cb..71869b5 100644 --- a/src/Domain/Entities/Order.cs +++ b/src/Domain/Entities/Order.cs @@ -12,24 +12,41 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Order : BaseAuditableEntity { + public DateTime OrderDate { get; set; } - public DateTime ShipDate { get; set; } - public decimal Amount { get; set; } + public DateTime ExpectedFinishDate { get; set; } + public string Address { get; set; } // Address = Customer's building location + public short Amount { get; set; } + public bool IsWhiteClothes { get; set; } + public double TotalPrice { get; set; } + + #region Relationship - /// - /// Relationship - /// - /// [ForeignKey("PaymentMethod")] public int PaymentMethodID { get; set; } - [ForeignKey("Building")] - public int BuildingID { get; set; } - [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } public ApplicationUser ApplicationUser { get; set; } public PaymentMethod PaymentMethod { get; set; } - public Building Building { get; set; } + + #endregion Relationship + + #region Special Attribute + + private string _orderType; + + public string OrderType + { + get => _orderType; + set + { + _orderType = new Validate().IsValidOrderType(value) + ? value + : throw new Exception("Invalid order type {ONEWAY, TWOWAY}"); + } + } + + #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/OrderHistory.cs b/src/Domain/Entities/OrderHistory.cs index a698815..a5a820a 100644 --- a/src/Domain/Entities/OrderHistory.cs +++ b/src/Domain/Entities/OrderHistory.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations.Schema; using SWD_Laundry_Backend.Domain.Entities.Validation; namespace SWD_Laundry_Backend.Domain.Entities; @@ -11,19 +6,17 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class OrderHistory : BaseAuditableEntity { - /// - /// Relationship - /// - /// + #region Relationship + [ForeignKey("Order")] public int OrderID { get; set; } public Order Order { get; set; } - /// - /// Special attributes - /// - /// + #endregion Relationship + + #region Special attributes + private string _orderstatus; public string Status @@ -33,7 +26,9 @@ public string Status { _orderstatus = new Validate().IsValidTripStatus(value) ? value - : throw new ArgumentException("Not valid order status."); + : throw new ArgumentException("Invalid order status {FINISHED, PROCESSING, CANCELLED}."); } } + + #endregion Special attributes } \ No newline at end of file diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 5c5e901..065a6ac 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -19,7 +19,7 @@ public string PaymentType { _type = new Validate().IsValidPayment(value) ? value - : throw new ArgumentException("Not valid payment type."); + : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); } } } \ No newline at end of file diff --git a/src/Domain/Entities/Staff.cs b/src/Domain/Entities/Staff.cs index ea738ed..f20bc7b 100644 --- a/src/Domain/Entities/Staff.cs +++ b/src/Domain/Entities/Staff.cs @@ -9,12 +9,10 @@ public class Staff : BaseAuditableEntity { public DateTime Dob { get; set; } public string Address { get; set; } - public decimal Salary { get; set; } + public double Salary { get; set; } + + #region Relationship - /// - /// Relationship - /// - /// [ForeignKey("Wallet")] public int WalletID { get; set; } @@ -24,10 +22,10 @@ public class Staff : BaseAuditableEntity public ApplicationUser ApplicationUser { get; set; } public Wallet Wallet { get; set; } - /// - /// Special attributes - /// - /// + #endregion Relationship + + #region Special Attribute + private string _email; private string _phone; @@ -40,7 +38,7 @@ public string Role { _role = new Validate().IsValidStaffRole(value) ? value - : throw new ArgumentException("Not valid staff role."); + : throw new ArgumentException("Invalid staff role {COLLECTOR, RECEIVER}."); } } @@ -51,7 +49,7 @@ public string Email { _email = new Validate().IsValidEmail(value) ? value - : throw new ArgumentException("Not valid mail."); + : throw new ArgumentException("Invalid email."); } } @@ -62,7 +60,9 @@ public string Phone { _phone = new Validate().IsValidPhone(value) ? value - : throw new ArgumentException("Not valid phone."); + : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); } } + + #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/StaffTrip.cs b/src/Domain/Entities/Staff_Trip.cs similarity index 60% rename from src/Domain/Entities/StaffTrip.cs rename to src/Domain/Entities/Staff_Trip.cs index bd7baf3..c4f5c27 100644 --- a/src/Domain/Entities/StaffTrip.cs +++ b/src/Domain/Entities/Staff_Trip.cs @@ -1,37 +1,32 @@ using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; using SWD_Laundry_Backend.Domain.Entities.Validation; namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable -public class StaffTrip : BaseAuditableEntity +public class Staff_Trip : BaseAuditableEntity { - //public DateOnly TripDate { get; set; } + public string Address { get; set; } public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } public decimal TripCollect { get; set; } = 0; - - /// - /// Relationship - /// - /// - [ForeignKey("Building")] - public int BuildingID { get; set; } + #region Relationship [ForeignKey("Staff")] public int StaffID { get; set; } - public Building Building { get; set; } - public Staff Staff { get; set; } - /// - /// Special attributes - /// - /// + #endregion Relationship + + #region Special Attribute + private string _tripstatus; + public string TripStatus { get { return _tripstatus; } @@ -39,7 +34,9 @@ public string TripStatus { _tripstatus = new Validate().IsValidTripStatus(value) ? value - : throw new ArgumentException("Not valid trip status."); + : throw new ArgumentException("Invalid trip status {FINISHED, PROCESSING, CANCELLED}."); } } + + #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs index 9a1dd76..6a3e82d 100644 --- a/src/Domain/Entities/Transaction.cs +++ b/src/Domain/Entities/Transaction.cs @@ -9,18 +9,16 @@ public class Transaction : BaseAuditableEntity public decimal Amount { get; set; } public string Description { get; set; } - /// - /// Relationship - /// - /// + #region Relationship + public int WalletID { get; set; } public List Wallet { get; set; } - /// - /// Special attribute - /// - /// + #endregion Relationship + + #region Special Attribute + private string _transactiontype; private string _status; @@ -31,7 +29,7 @@ public string TransactionType set { if (!new Validate().IsValidTransactionType(value)) - throw new ArgumentException("Not valid transaction type."); + throw new ArgumentException("Invalid transaction type {DEPOSIT, WITHDRAWAL, DEBT, PAID}."); _transactiontype = value; } } @@ -42,8 +40,10 @@ public string Status set { if (!new Validate().IsValidTransactionStatus(value)) - throw new ArgumentException("Not valid transaction status."); + throw new ArgumentException("Invalid transaction status {FINISHED, PROCESSING, CANCELLED}."); _status = value; } } + + #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Validation/Validate.cs b/src/Domain/Entities/Validation/Validate.cs index ed593fa..32b1227 100644 --- a/src/Domain/Entities/Validation/Validate.cs +++ b/src/Domain/Entities/Validation/Validate.cs @@ -17,7 +17,7 @@ public bool IsValidTransactionType(string type) public bool IsValidTransactionStatus(string status) { - return TransactionStatus.Contains(status); + return Status.Contains(status); } public bool IsValidPhone(string phone) @@ -34,37 +34,45 @@ public bool IsValidEmail(string email) public bool IsValidTripStatus(string status) { - return TripStatus.Contains(status); + return Status.Contains(status); } public bool IsValidPayment(string payment) { return Payment.Contains(payment); } + + public bool IsValidOrderType(string value) + { + return OrderType.Contains(value); + } + //======================================================= - public string[] Payment = new string[] + private readonly string[] OrderType = new string[] + { + "ONEWAY","TWOWAY" + }; + + private readonly string[] Payment = new string[] { - "Cash","Paypal" + "CASH","PAYPAL" }; - public string[] TripStatus = new string[] + private readonly string[] Status = new string[] { - "Finished","Processing","Cancelled" + "FINISHED","PROCESSING","CANCELLED" }; - public string[] StaffRole = new string[] + private readonly string[] StaffRole = new string[] { - "Collector","Receiver" + "COLLECTOR","RECEIVER" }; - public string[] AllowedTransactionType = new string[] + private readonly string[] AllowedTransactionType = new string[] { - "Deposit","Withdrawal", "Debt", "Paid" + "DEPOSIT","WITHDRAWAL", "DEBT", "PAID" }; - public string[] TransactionStatus = new string[] - { - "Success","Processing","Fail" - }; + } \ No newline at end of file diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs index 6072d61..a65ac7b 100644 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ b/src/Infrastructure/Identity/ApplicationUser.cs @@ -4,5 +4,4 @@ namespace SWD_Laundry_Backend.Infrastructure.Identity; public class ApplicationUser : IdentityUser { - public string? Name { get; set; } -} +} \ No newline at end of file diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index e6dfee7..5503c3a 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index 2b1328e..157d6b2 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -6,8 +6,9 @@ using Microsoft.Extensions.Options; using SWD_Laundry_Backend.Application.Common.Interfaces; using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.IdentityModel; -//using SWD_Laundry_Backend.Infrastructure.Identity; + +//using SWD_Laundry_Backend.Domain.IdentityModel; +using SWD_Laundry_Backend.Infrastructure.Identity; using SWD_Laundry_Backend.Infrastructure.Persistence.Interceptors; namespace SWD_Laundry_Backend.Infrastructure.Persistence; @@ -40,8 +41,9 @@ public ApplicationDbContext( public DbSet Orders => Set(); public DbSet OrderHistory => Set(); public DbSet PaymentMethods => Set(); + public DbSet Staff_Trips => Set(); public DbSet Staffs => Set(); - public DbSet Stasts => Set(); + public DbSet Transactions => Set(); public DbSet Wallets => Set(); diff --git a/src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.Designer.cs b/src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.Designer.cs deleted file mode 100644 index 1850070..0000000 --- a/src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.Designer.cs +++ /dev/null @@ -1,539 +0,0 @@ -// -using System; -using SWD_Laundry_Backend.Infrastructure.Persistence; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("00000000000000_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.OwnsOne("SWD_Laundry_Backend.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.cs b/src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.cs deleted file mode 100644 index 68facc0..0000000 --- a/src/Infrastructure/Persistence/Migrations/00000000000000_InitialCreate.cs +++ /dev/null @@ -1,380 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: false), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Version = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Use = table.Column(type: "nvarchar(450)", nullable: true), - Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - IsX509Certificate = table.Column(type: "bit", nullable: false), - DataProtected = table.Column(type: "bit", nullable: false), - Data = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - ConsumedTime = table.Column(type: "datetime2", nullable: true), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - - migrationBuilder.CreateTable( - name: "TodoLists", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Colour_Code = table.Column(type: "nvarchar(max)", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoLists", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), - UserId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - RoleId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ListId = table.Column(type: "int", nullable: false), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Note = table.Column(type: "nvarchar(max)", nullable: true), - Priority = table.Column(type: "int", nullable: false), - Reminder = table.Column(type: "datetime2", nullable: true), - Done = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - table.ForeignKey( - name: "FK_TodoItems_TodoLists_ListId", - column: x => x.ListId, - principalTable: "TodoLists", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_TodoItems_ListId", - table: "TodoItems", - column: "ListId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - - migrationBuilder.DropTable( - name: "TodoItems"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - - migrationBuilder.DropTable( - name: "TodoLists"); - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.Designer.cs b/src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.Designer.cs deleted file mode 100644 index bfcc2c5..0000000 --- a/src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.Designer.cs +++ /dev/null @@ -1,540 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SWD_Laundry_Backend.Infrastructure.Persistence; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20230914161433_InitMigration")] - partial class InitMigration - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.OwnsOne("SWD_Laundry_Backend.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.cs b/src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.cs deleted file mode 100644 index bb66b0d..0000000 --- a/src/Infrastructure/Persistence/Migrations/20230914161433_InitMigration.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - /// - public partial class InitMigration : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.cs b/src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.cs deleted file mode 100644 index d6701ba..0000000 --- a/src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.cs +++ /dev/null @@ -1,413 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - /// - public partial class InitialDatabase : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Name", - table: "AspNetUsers", - type: "nvarchar(max)", - nullable: true); - - migrationBuilder.CreateTable( - name: "Buildings", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Buildings", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PaymentMethods", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Description = table.Column(type: "nvarchar(max)", nullable: true), - PaymentType = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_PaymentMethods", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Transactions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "decimal(18,2)", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - TransactionType = table.Column(type: "nvarchar(max)", nullable: true), - Status = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Transactions", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Orders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderDate = table.Column(type: "datetime2", nullable: false), - ShipDate = table.Column(type: "datetime2", nullable: false), - Amount = table.Column(type: "decimal(18,2)", nullable: false), - PaymentMethodID = table.Column(type: "int", nullable: false), - BuildingID = table.Column(type: "int", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Orders", x => x.Id); - table.ForeignKey( - name: "FK_Orders_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Orders_Buildings_BuildingID", - column: x => x.BuildingID, - principalTable: "Buildings", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_PaymentMethods_PaymentMethodID", - column: x => x.PaymentMethodID, - principalTable: "PaymentMethods", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Wallets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Balance = table.Column(type: "decimal(18,2)", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - TransactionId = table.Column(type: "int", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Wallets", x => x.Id); - table.ForeignKey( - name: "FK_Wallets_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Wallets_Transactions_TransactionId", - column: x => x.TransactionId, - principalTable: "Transactions", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "OrderHistory", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderID = table.Column(type: "int", nullable: false), - Status = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OrderHistory", x => x.Id); - table.ForeignKey( - name: "FK_OrderHistory_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Customers", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Address = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Email = table.Column(type: "nvarchar(max)", nullable: true), - Phone = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Customers", x => x.Id); - table.ForeignKey( - name: "FK_Customers_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Customers_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "LaundryStores", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Address = table.Column(type: "nvarchar(max)", nullable: true), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - Email = table.Column(type: "nvarchar(max)", nullable: true), - Phone = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStores", x => x.Id); - table.ForeignKey( - name: "FK_LaundryStores_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_LaundryStores_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Staffs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Dob = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Salary = table.Column(type: "decimal(18,2)", nullable: false), - WalletID = table.Column(type: "int", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Role = table.Column(type: "nvarchar(max)", nullable: true), - Email = table.Column(type: "nvarchar(max)", nullable: true), - Phone = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Staffs", x => x.Id); - table.ForeignKey( - name: "FK_Staffs_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Staffs_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Stasts", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - StartTime = table.Column(type: "datetime2", nullable: false), - EndTime = table.Column(type: "datetime2", nullable: false), - TripCollect = table.Column(type: "decimal(18,2)", nullable: false), - BuildingID = table.Column(type: "int", nullable: false), - StaffID = table.Column(type: "int", nullable: false), - TripStatus = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Stasts", x => x.Id); - table.ForeignKey( - name: "FK_Stasts_Buildings_BuildingID", - column: x => x.BuildingID, - principalTable: "Buildings", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Stasts_Staffs_StaffID", - column: x => x.StaffID, - principalTable: "Staffs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Customers_ApplicationUserID", - table: "Customers", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_Customers_WalletID", - table: "Customers", - column: "WalletID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStores_ApplicationUserID", - table: "LaundryStores", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStores_WalletID", - table: "LaundryStores", - column: "WalletID"); - - migrationBuilder.CreateIndex( - name: "IX_OrderHistory_OrderID", - table: "OrderHistory", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_ApplicationUserID", - table: "Orders", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_BuildingID", - table: "Orders", - column: "BuildingID"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_PaymentMethodID", - table: "Orders", - column: "PaymentMethodID"); - - migrationBuilder.CreateIndex( - name: "IX_Staffs_ApplicationUserID", - table: "Staffs", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_Staffs_WalletID", - table: "Staffs", - column: "WalletID"); - - migrationBuilder.CreateIndex( - name: "IX_Stasts_BuildingID", - table: "Stasts", - column: "BuildingID"); - - migrationBuilder.CreateIndex( - name: "IX_Stasts_StaffID", - table: "Stasts", - column: "StaffID"); - - migrationBuilder.CreateIndex( - name: "IX_Wallets_ApplicationUserID", - table: "Wallets", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_Wallets_TransactionId", - table: "Wallets", - column: "TransactionId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Customers"); - - migrationBuilder.DropTable( - name: "LaundryStores"); - - migrationBuilder.DropTable( - name: "OrderHistory"); - - migrationBuilder.DropTable( - name: "Stasts"); - - migrationBuilder.DropTable( - name: "Orders"); - - migrationBuilder.DropTable( - name: "Staffs"); - - migrationBuilder.DropTable( - name: "Buildings"); - - migrationBuilder.DropTable( - name: "PaymentMethods"); - - migrationBuilder.DropTable( - name: "Wallets"); - - migrationBuilder.DropTable( - name: "Transactions"); - - migrationBuilder.DropColumn( - name: "Name", - table: "AspNetUsers"); - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.Designer.cs b/src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.Designer.cs deleted file mode 100644 index 54e8a98..0000000 --- a/src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.Designer.cs +++ /dev/null @@ -1,1072 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SWD_Laundry_Backend.Infrastructure.Persistence; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20230914221506_InitialDatabase2")] - partial class InitialDatabase2 - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Buildings"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("WalletID"); - - b.ToTable("Customers"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("WalletID"); - - b.ToTable("LaundryStores"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderDate") - .HasColumnType("datetime2"); - - b.Property("PaymentMethodID") - .HasColumnType("int"); - - b.Property("ShipDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("BuildingID"); - - b.HasIndex("PaymentMethodID"); - - b.ToTable("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("Status") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.ToTable("OrderHistory"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("PaymentType") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("PaymentMethods"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Dob") - .HasColumnType("datetime2"); - - b.Property("Email") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - - b.Property("Role") - .HasColumnType("nvarchar(max)"); - - b.Property("Salary") - .HasColumnType("decimal(18,2)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("WalletID"); - - b.ToTable("Staffs"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffTrip", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("TripCollect") - .HasColumnType("decimal(18,2)"); - - b.Property("TripStatus") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("BuildingID"); - - b.HasIndex("StaffID"); - - b.ToTable("Stasts"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("decimal(18,2)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("PaymentMethod") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasColumnType("nvarchar(max)"); - - b.Property("TransactionType") - .HasColumnType("nvarchar(max)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Transactions"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Balance") - .HasColumnType("decimal(18,2)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("TransactionId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("TransactionId"); - - b.ToTable("Wallets"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") - .WithMany() - .HasForeignKey("PaymentMethodID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Building"); - - b.Navigation("PaymentMethod"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany() - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffTrip", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany() - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Building"); - - b.Navigation("Staff"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.OwnsOne("SWD_Laundry_Backend.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Transaction", null) - .WithMany("Wallet") - .HasForeignKey("TransactionId"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.Navigation("Wallet"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.cs b/src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.cs deleted file mode 100644 index b7142cb..0000000 --- a/src/Infrastructure/Persistence/Migrations/20230914221506_InitialDatabase2.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations -{ - /// - public partial class InitialDatabase2 : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Wallets_AspNetUsers_ApplicationUserID", - table: "Wallets"); - - migrationBuilder.DropIndex( - name: "IX_Wallets_ApplicationUserID", - table: "Wallets"); - - migrationBuilder.DropColumn( - name: "ApplicationUserID", - table: "Wallets"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ApplicationUserID", - table: "Wallets", - type: "nvarchar(450)", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_Wallets_ApplicationUserID", - table: "Wallets", - column: "ApplicationUserID"); - - migrationBuilder.AddForeignKey( - name: "FK_Wallets_AspNetUsers_ApplicationUserID", - table: "Wallets", - column: "ApplicationUserID", - principalTable: "AspNetUsers", - principalColumn: "Id"); - } - } -} diff --git a/src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.Designer.cs b/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.Designer.cs similarity index 91% rename from src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.Designer.cs rename to src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.Designer.cs index a84d995..90a7c67 100644 --- a/src/Infrastructure/Persistence/Migrations/20230914220515_InitialDatabase.Designer.cs +++ b/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.Designer.cs @@ -12,8 +12,8 @@ namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230914220515_InitialDatabase")] - partial class InitialDatabase + [Migration("20230917182804_OptimizeEntity")] + partial class OptimizeEntity { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -345,12 +345,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") - .HasColumnType("nvarchar(max)"); - b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); + b.Property("BuildingID") + .HasColumnType("int"); + b.Property("Created") .HasColumnType("datetime2"); @@ -366,6 +366,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + b.Property("Phone") .HasColumnType("nvarchar(max)"); @@ -376,6 +379,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); + b.HasIndex("BuildingID"); + b.HasIndex("WalletID"); b.ToTable("Customers"); @@ -404,15 +409,27 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Email") .HasColumnType("nvarchar(max)"); + b.Property("EndTime") + .HasColumnType("datetime2"); + b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + b.Property("Phone") .HasColumnType("nvarchar(max)"); + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + b.Property("WalletID") .HasColumnType("int"); @@ -433,21 +450,27 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Amount") - .HasColumnType("decimal(18,2)"); + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); - b.Property("BuildingID") - .HasColumnType("int"); - b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("IsWhiteClothes") + .HasColumnType("bit"); + b.Property("LastModified") .HasColumnType("datetime2"); @@ -457,18 +480,19 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("OrderDate") .HasColumnType("datetime2"); + b.Property("OrderType") + .HasColumnType("nvarchar(max)"); + b.Property("PaymentMethodID") .HasColumnType("int"); - b.Property("ShipDate") - .HasColumnType("datetime2"); + b.Property("TotalPrice") + .HasColumnType("float"); b.HasKey("Id"); b.HasIndex("ApplicationUserID"); - b.HasIndex("BuildingID"); - b.HasIndex("PaymentMethodID"); b.ToTable("Orders"); @@ -576,8 +600,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Role") .HasColumnType("nvarchar(max)"); - b.Property("Salary") - .HasColumnType("decimal(18,2)"); + b.Property("Salary") + .HasColumnType("float"); b.Property("WalletID") .HasColumnType("int"); @@ -591,7 +615,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Staffs"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffTrip", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -599,8 +623,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("BuildingID") - .HasColumnType("int"); + b.Property("Address") + .HasColumnType("nvarchar(max)"); b.Property("Created") .HasColumnType("datetime2"); @@ -631,11 +655,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.HasIndex("BuildingID"); - b.HasIndex("StaffID"); - b.ToTable("Stasts"); + b.ToTable("Staff_Trips"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => @@ -766,9 +788,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - b.Property("Balance") .HasColumnType("decimal(18,2)"); @@ -789,8 +808,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); - b.HasIndex("TransactionId"); b.ToTable("Wallets"); @@ -805,12 +822,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); + .HasColumnType("nvarchar(max)"); b.Property("EmailConfirmed") .HasColumnType("bit"); @@ -824,6 +839,60 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Name") .HasColumnType("nvarchar(max)"); + 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("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + b.Property("NormalizedEmail") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -875,7 +944,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -884,7 +953,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -899,7 +968,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -908,7 +977,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -921,6 +990,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") + .WithMany() + .HasForeignKey("BuildingID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") .WithMany() .HasForeignKey("WalletID") @@ -929,6 +1004,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("ApplicationUser"); + b.Navigation("Building"); + b.Navigation("Wallet"); }); @@ -955,12 +1032,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") .WithMany() .HasForeignKey("PaymentMethodID") @@ -969,8 +1040,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("ApplicationUser"); - b.Navigation("Building"); - b.Navigation("PaymentMethod"); }); @@ -1002,22 +1071,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Wallet"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffTrip", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") .WithMany() .HasForeignKey("StaffID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Building"); - b.Navigation("Staff"); }); @@ -1057,15 +1118,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Transaction", null) .WithMany("Wallet") .HasForeignKey("TransactionId"); - - b.Navigation("ApplicationUser"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => diff --git a/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs b/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs new file mode 100644 index 0000000..b524372 --- /dev/null +++ b/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs @@ -0,0 +1,782 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations +{ + /// + public partial class OptimizeEntity : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicationUser", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), + UserName = table.Column(type: "nvarchar(max)", nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(max)", nullable: true), + Email = table.Column(type: "nvarchar(max)", nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(max)", nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationUser", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Buildings", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: true), + Address = table.Column(type: "nvarchar(max)", nullable: true), + Description = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Buildings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "DeviceCodes", + columns: table => new + { + UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + Expiration = table.Column(type: "datetime2", nullable: false), + Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); + }); + + migrationBuilder.CreateTable( + name: "Keys", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Version = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + Use = table.Column(type: "nvarchar(450)", nullable: true), + Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + IsX509Certificate = table.Column(type: "bit", nullable: false), + DataProtected = table.Column(type: "bit", nullable: false), + Data = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Keys", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PaymentMethods", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Description = table.Column(type: "nvarchar(max)", nullable: true), + PaymentType = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PaymentMethods", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PersistedGrants", + columns: table => new + { + Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + ConsumedTime = table.Column(type: "datetime2", nullable: true), + Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedGrants", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "TodoLists", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Colour_Code = table.Column(type: "nvarchar(max)", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoLists", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Transactions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), + Amount = table.Column(type: "decimal(18,2)", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + WalletID = table.Column(type: "int", nullable: false), + TransactionType = table.Column(type: "nvarchar(max)", nullable: true), + Status = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Transactions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + OrderDate = table.Column(type: "datetime2", nullable: false), + ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), + Address = table.Column(type: "nvarchar(max)", nullable: true), + Amount = table.Column(type: "smallint", nullable: false), + IsWhiteClothes = table.Column(type: "bit", nullable: false), + TotalPrice = table.Column(type: "float", nullable: false), + PaymentMethodID = table.Column(type: "int", nullable: false), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + OrderType = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Orders_PaymentMethods_PaymentMethodID", + column: x => x.PaymentMethodID, + principalTable: "PaymentMethods", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "TodoItems", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ListId = table.Column(type: "int", nullable: false), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Note = table.Column(type: "nvarchar(max)", nullable: true), + Priority = table.Column(type: "int", nullable: false), + Reminder = table.Column(type: "datetime2", nullable: true), + Done = table.Column(type: "bit", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoItems", x => x.Id); + table.ForeignKey( + name: "FK_TodoItems_TodoLists_ListId", + column: x => x.ListId, + principalTable: "TodoLists", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Wallets", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Balance = table.Column(type: "decimal(18,2)", nullable: false), + TransactionId = table.Column(type: "int", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Wallets", x => x.Id); + table.ForeignKey( + name: "FK_Wallets_Transactions_TransactionId", + column: x => x.TransactionId, + principalTable: "Transactions", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "OrderHistory", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + OrderID = table.Column(type: "int", nullable: false), + Status = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OrderHistory", x => x.Id); + table.ForeignKey( + name: "FK_OrderHistory_Orders_OrderID", + column: x => x.OrderID, + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Customers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: true), + BuildingID = table.Column(type: "int", nullable: false), + WalletID = table.Column(type: "int", nullable: false), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + Email = table.Column(type: "nvarchar(max)", nullable: true), + Phone = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Customers", x => x.Id); + table.ForeignKey( + name: "FK_Customers_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Customers_Buildings_BuildingID", + column: x => x.BuildingID, + principalTable: "Buildings", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Customers_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "LaundryStores", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: true), + Address = table.Column(type: "nvarchar(max)", nullable: true), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false), + Status = table.Column(type: "bit", nullable: false), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + WalletID = table.Column(type: "int", nullable: false), + Email = table.Column(type: "nvarchar(max)", nullable: true), + Phone = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_LaundryStores", x => x.Id); + table.ForeignKey( + name: "FK_LaundryStores_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_LaundryStores_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Staffs", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Dob = table.Column(type: "datetime2", nullable: false), + Address = table.Column(type: "nvarchar(max)", nullable: true), + Salary = table.Column(type: "float", nullable: false), + WalletID = table.Column(type: "int", nullable: false), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + Role = table.Column(type: "nvarchar(max)", nullable: true), + Email = table.Column(type: "nvarchar(max)", nullable: true), + Phone = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Staffs", x => x.Id); + table.ForeignKey( + name: "FK_Staffs_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Staffs_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Staff_Trips", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Address = table.Column(type: "nvarchar(max)", nullable: true), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false), + TripCollect = table.Column(type: "decimal(18,2)", nullable: false), + StaffID = table.Column(type: "int", nullable: false), + TripStatus = table.Column(type: "nvarchar(max)", nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Staff_Trips", x => x.Id); + table.ForeignKey( + name: "FK_Staff_Trips_Staffs_StaffID", + column: x => x.StaffID, + principalTable: "Staffs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_Customers_ApplicationUserID", + table: "Customers", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_Customers_BuildingID", + table: "Customers", + column: "BuildingID"); + + migrationBuilder.CreateIndex( + name: "IX_Customers_WalletID", + table: "Customers", + column: "WalletID"); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_DeviceCode", + table: "DeviceCodes", + column: "DeviceCode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_Expiration", + table: "DeviceCodes", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_Keys_Use", + table: "Keys", + column: "Use"); + + migrationBuilder.CreateIndex( + name: "IX_LaundryStores_ApplicationUserID", + table: "LaundryStores", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_LaundryStores_WalletID", + table: "LaundryStores", + column: "WalletID"); + + migrationBuilder.CreateIndex( + name: "IX_OrderHistory_OrderID", + table: "OrderHistory", + column: "OrderID"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_ApplicationUserID", + table: "Orders", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_PaymentMethodID", + table: "Orders", + column: "PaymentMethodID"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_ConsumedTime", + table: "PersistedGrants", + column: "ConsumedTime"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_Expiration", + table: "PersistedGrants", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_ClientId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "ClientId", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_SessionId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "SessionId", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_Staff_Trips_StaffID", + table: "Staff_Trips", + column: "StaffID"); + + migrationBuilder.CreateIndex( + name: "IX_Staffs_ApplicationUserID", + table: "Staffs", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_Staffs_WalletID", + table: "Staffs", + column: "WalletID"); + + migrationBuilder.CreateIndex( + name: "IX_TodoItems_ListId", + table: "TodoItems", + column: "ListId"); + + migrationBuilder.CreateIndex( + name: "IX_Wallets_TransactionId", + table: "Wallets", + column: "TransactionId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "Customers"); + + migrationBuilder.DropTable( + name: "DeviceCodes"); + + migrationBuilder.DropTable( + name: "Keys"); + + migrationBuilder.DropTable( + name: "LaundryStores"); + + migrationBuilder.DropTable( + name: "OrderHistory"); + + migrationBuilder.DropTable( + name: "PersistedGrants"); + + migrationBuilder.DropTable( + name: "Staff_Trips"); + + migrationBuilder.DropTable( + name: "TodoItems"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + + migrationBuilder.DropTable( + name: "Buildings"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "Staffs"); + + migrationBuilder.DropTable( + name: "TodoLists"); + + migrationBuilder.DropTable( + name: "PaymentMethods"); + + migrationBuilder.DropTable( + name: "ApplicationUser"); + + migrationBuilder.DropTable( + name: "Wallets"); + + migrationBuilder.DropTable( + name: "Transactions"); + } + } +} diff --git a/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs index 8be44c0..ac6ffb3 100644 --- a/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs @@ -308,7 +308,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") .HasColumnType("nvarchar(max)"); @@ -319,7 +318,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Description") - .HasColumnType("nvarchar(max)"); b.Property("LastModified") @@ -328,7 +326,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Name") .HasColumnType("nvarchar(max)"); @@ -345,12 +342,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") - .HasColumnType("nvarchar(max)"); - b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); + b.Property("BuildingID") + .HasColumnType("int"); + b.Property("Created") .HasColumnType("datetime2"); @@ -366,6 +363,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + b.Property("Phone") .HasColumnType("nvarchar(max)"); @@ -376,14 +376,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); + b.HasIndex("BuildingID"); + b.HasIndex("WalletID"); b.ToTable("Customers"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { b.Property("Id") .ValueGeneratedOnAdd() @@ -406,15 +406,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Email") .HasColumnType("nvarchar(max)"); + b.Property("EndTime") + .HasColumnType("datetime2"); + b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + b.Property("Phone") .HasColumnType("nvarchar(max)"); + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + b.Property("WalletID") .HasColumnType("int"); @@ -435,21 +447,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Amount") - .HasColumnType("decimal(18,2)"); + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); - b.Property("BuildingID") - .HasColumnType("int"); - b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("IsWhiteClothes") + .HasColumnType("bit"); + b.Property("LastModified") .HasColumnType("datetime2"); @@ -459,18 +477,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("OrderDate") .HasColumnType("datetime2"); + b.Property("OrderType") + .HasColumnType("nvarchar(max)"); + b.Property("PaymentMethodID") .HasColumnType("int"); - b.Property("ShipDate") - .HasColumnType("datetime2"); + b.Property("TotalPrice") + .HasColumnType("float"); b.HasKey("Id"); b.HasIndex("ApplicationUserID"); - b.HasIndex("BuildingID"); - b.HasIndex("PaymentMethodID"); b.ToTable("Orders"); @@ -578,8 +597,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Role") .HasColumnType("nvarchar(max)"); - b.Property("Salary") - .HasColumnType("decimal(18,2)"); + b.Property("Salary") + .HasColumnType("float"); b.Property("WalletID") .HasColumnType("int"); @@ -593,7 +612,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Staffs"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffTrip", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -601,8 +620,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("BuildingID") - .HasColumnType("int"); + b.Property("Address") + .HasColumnType("nvarchar(max)"); b.Property("Created") .HasColumnType("datetime2"); @@ -633,11 +652,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.HasIndex("BuildingID"); - b.HasIndex("StaffID"); - b.ToTable("Stasts"); + b.ToTable("Staff_Trips"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => @@ -802,12 +819,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); + .HasColumnType("nvarchar(max)"); b.Property("EmailConfirmed") .HasColumnType("bit"); @@ -821,6 +836,60 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .HasColumnType("nvarchar(max)"); + 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("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + b.Property("NormalizedEmail") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -872,7 +941,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -881,7 +950,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -896,7 +965,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -905,7 +974,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -918,6 +987,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") + .WithMany() + .HasForeignKey("BuildingID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") .WithMany() .HasForeignKey("WalletID") @@ -926,6 +1001,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApplicationUser"); + b.Navigation("Building"); + b.Navigation("Wallet"); }); @@ -952,12 +1029,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") .WithMany() .HasForeignKey("PaymentMethodID") @@ -966,8 +1037,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ApplicationUser"); - b.Navigation("Building"); - b.Navigation("PaymentMethod"); }); @@ -999,174 +1068,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Wallet"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffTrip", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") .WithMany() .HasForeignKey("StaffID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Building"); - b.Navigation("Staff"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Transaction", null) - .WithMany("Wallet") - .HasForeignKey("TransactionId"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => { b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") @@ -1201,6 +1113,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Transaction", null) + .WithMany("Wallet") + .HasForeignKey("TransactionId"); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => { b.Navigation("Items"); diff --git a/src/WebUI/appsettings.json b/src/WebUI/appsettings.json index 63f5e42..0dab0a7 100644 --- a/src/WebUI/appsettings.json +++ b/src/WebUI/appsettings.json @@ -1,7 +1,7 @@ { "UseInMemoryDatabase": false, "ConnectionStrings": { - "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=Laundry;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=12345" + "DefaultConnection": "Server=LEWIS;Database=SWD_Laundry_BackendDb;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=123456;TrustServerCertificate=true" }, "Logging": { From 34d4912a77d92145b24c197eaa48295119c2bfe7 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 18 Sep 2023 06:15:19 +0700 Subject: [PATCH 02/53] fix database --- src/Domain/Entities/Order.cs | 2 - .../Identity/ApplicationIdentity.cs | 14 --- .../Identity/ApplicationUser.cs | 10 --- src/Infrastructure/Infrastructure.csproj | 10 ++- .../Persistence/ApplicationDbContext.cs | 4 +- ... 20230917231227_InitMigration.Designer.cs} | 87 ++++--------------- ...ity.cs => 20230917231227_InitMigration.cs} | 59 ++++--------- .../ApplicationDbContextModelSnapshot.cs | 83 ++++-------------- src/WebUI/Program.cs | 10 +-- src/WebUI/appsettings.json | 2 +- 10 files changed, 65 insertions(+), 216 deletions(-) delete mode 100644 src/Infrastructure/Identity/ApplicationIdentity.cs delete mode 100644 src/Infrastructure/Identity/ApplicationUser.cs rename src/Infrastructure/Persistence/Migrations/{20230917182804_OptimizeEntity.Designer.cs => 20230917231227_InitMigration.Designer.cs} (93%) rename src/Infrastructure/Persistence/Migrations/{20230917182804_OptimizeEntity.cs => 20230917231227_InitMigration.cs} (93%) diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs index 6b7b488..ccf52e3 100644 --- a/src/Domain/Entities/Order.cs +++ b/src/Domain/Entities/Order.cs @@ -14,9 +14,7 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Order : BaseAuditableEntity { - public DateTime OrderDate { get; set; } public DateTime ShipDate { get; set; } - public int Amount { get; set; } public DateTime OrderDate { get; set; } diff --git a/src/Infrastructure/Identity/ApplicationIdentity.cs b/src/Infrastructure/Identity/ApplicationIdentity.cs deleted file mode 100644 index 1b48dbf..0000000 --- a/src/Infrastructure/Identity/ApplicationIdentity.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; - -namespace SWD_Laundry_Backend.Infrastructure.Identity; -#nullable disable - -public class ApplicationIdentity : IdentityRole -{ - public string Description { get; set; } -} \ No newline at end of file diff --git a/src/Infrastructure/Identity/ApplicationUser.cs b/src/Infrastructure/Identity/ApplicationUser.cs deleted file mode 100644 index 3e3ae94..0000000 --- a/src/Infrastructure/Identity/ApplicationUser.cs +++ /dev/null @@ -1,10 +0,0 @@ -//using Microsoft.AspNetCore.Identity; - -//namespace SWD_Laundry_Backend.Infrastructure.Identity; - - -//public class ApplicationUser : IdentityUser -//{ -// public string? Name { get; set; } -//} - diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 5503c3a..1220f15 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -8,6 +8,12 @@ enable + + + + + + @@ -22,8 +28,4 @@ - - - - diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index 157d6b2..33a227d 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -7,8 +7,8 @@ using SWD_Laundry_Backend.Application.Common.Interfaces; using SWD_Laundry_Backend.Domain.Entities; -//using SWD_Laundry_Backend.Domain.IdentityModel; -using SWD_Laundry_Backend.Infrastructure.Identity; +using SWD_Laundry_Backend.Domain.IdentityModel; +//using SWD_Laundry_Backend.Infrastructure.Identity; using SWD_Laundry_Backend.Infrastructure.Persistence.Interceptors; namespace SWD_Laundry_Backend.Infrastructure.Persistence; diff --git a/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.Designer.cs b/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.Designer.cs similarity index 93% rename from src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.Designer.cs rename to src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.Designer.cs index 90a7c67..dd27a0a 100644 --- a/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.Designer.cs +++ b/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.Designer.cs @@ -9,11 +9,11 @@ #nullable disable -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations +namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230917182804_OptimizeEntity")] - partial class OptimizeEntity + [Migration("20230917231227_InitMigration")] + partial class InitMigration { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -486,6 +486,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); + b.Property("ShipDate") + .HasColumnType("datetime2"); + b.Property("TotalPrice") .HasColumnType("float"); @@ -647,8 +650,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("StartTime") .HasColumnType("datetime2"); - b.Property("TripCollect") - .HasColumnType("decimal(18,2)"); + b.Property("TripCollect") + .HasColumnType("int"); b.Property("TripStatus") .HasColumnType("nvarchar(max)"); @@ -745,8 +748,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Amount") - .HasColumnType("decimal(18,2)"); + b.Property("Amount") + .HasColumnType("int"); b.Property("Created") .HasColumnType("datetime2"); @@ -788,8 +791,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Balance") - .HasColumnType("decimal(18,2)"); + b.Property("Balance") + .HasColumnType("float"); b.Property("Created") .HasColumnType("datetime2"); @@ -814,61 +817,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - 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("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => { b.Property("Id") .HasColumnType("nvarchar(450)"); @@ -893,6 +841,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LockoutEnd") .HasColumnType("datetimeoffset"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + b.Property("NormalizedEmail") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -944,7 +895,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -953,7 +904,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -968,7 +919,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -977,7 +928,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) diff --git a/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs b/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.cs similarity index 93% rename from src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs rename to src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.cs index b524372..b75f302 100644 --- a/src/Infrastructure/Persistence/Migrations/20230917182804_OptimizeEntity.cs +++ b/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.cs @@ -3,40 +3,14 @@ #nullable disable -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations +namespace SWD_Laundry_Backend.Infrastructure.Migrations { /// - public partial class OptimizeEntity : Migration + public partial class InitMigration : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.CreateTable( - name: "ApplicationUser", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: true), - UserName = table.Column(type: "nvarchar(max)", nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(max)", nullable: true), - Email = table.Column(type: "nvarchar(max)", nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(max)", nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApplicationUser", x => x.Id); - }); - migrationBuilder.CreateTable( name: "AspNetRoles", columns: table => new @@ -56,6 +30,7 @@ protected override void Up(MigrationBuilder migrationBuilder) columns: table => new { Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), @@ -195,7 +170,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "decimal(18,2)", nullable: false), + Amount = table.Column(type: "int", nullable: false), Description = table.Column(type: "nvarchar(max)", nullable: true), WalletID = table.Column(type: "int", nullable: false), TransactionType = table.Column(type: "nvarchar(max)", nullable: true), @@ -322,6 +297,7 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), + ShipDate = table.Column(type: "datetime2", nullable: false), OrderDate = table.Column(type: "datetime2", nullable: false), ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), Address = table.Column(type: "nvarchar(max)", nullable: true), @@ -340,9 +316,9 @@ protected override void Up(MigrationBuilder migrationBuilder) { table.PrimaryKey("PK_Orders", x => x.Id); table.ForeignKey( - name: "FK_Orders_ApplicationUser_ApplicationUserID", + name: "FK_Orders_AspNetUsers_ApplicationUserID", column: x => x.ApplicationUserID, - principalTable: "ApplicationUser", + principalTable: "AspNetUsers", principalColumn: "Id"); table.ForeignKey( name: "FK_Orders_PaymentMethods_PaymentMethodID", @@ -386,7 +362,7 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - Balance = table.Column(type: "decimal(18,2)", nullable: false), + Balance = table.Column(type: "float", nullable: false), TransactionId = table.Column(type: "int", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), @@ -448,9 +424,9 @@ protected override void Up(MigrationBuilder migrationBuilder) { table.PrimaryKey("PK_Customers", x => x.Id); table.ForeignKey( - name: "FK_Customers_ApplicationUser_ApplicationUserID", + name: "FK_Customers_AspNetUsers_ApplicationUserID", column: x => x.ApplicationUserID, - principalTable: "ApplicationUser", + principalTable: "AspNetUsers", principalColumn: "Id"); table.ForeignKey( name: "FK_Customers_Buildings_BuildingID", @@ -490,9 +466,9 @@ protected override void Up(MigrationBuilder migrationBuilder) { table.PrimaryKey("PK_LaundryStores", x => x.Id); table.ForeignKey( - name: "FK_LaundryStores_ApplicationUser_ApplicationUserID", + name: "FK_LaundryStores_AspNetUsers_ApplicationUserID", column: x => x.ApplicationUserID, - principalTable: "ApplicationUser", + principalTable: "AspNetUsers", principalColumn: "Id"); table.ForeignKey( name: "FK_LaundryStores_Wallets_WalletID", @@ -525,9 +501,9 @@ protected override void Up(MigrationBuilder migrationBuilder) { table.PrimaryKey("PK_Staffs", x => x.Id); table.ForeignKey( - name: "FK_Staffs_ApplicationUser_ApplicationUserID", + name: "FK_Staffs_AspNetUsers_ApplicationUserID", column: x => x.ApplicationUserID, - principalTable: "ApplicationUser", + principalTable: "AspNetUsers", principalColumn: "Id"); table.ForeignKey( name: "FK_Staffs_Wallets_WalletID", @@ -546,7 +522,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Address = table.Column(type: "nvarchar(max)", nullable: true), StartTime = table.Column(type: "datetime2", nullable: false), EndTime = table.Column(type: "datetime2", nullable: false), - TripCollect = table.Column(type: "decimal(18,2)", nullable: false), + TripCollect = table.Column(type: "int", nullable: false), StaffID = table.Column(type: "int", nullable: false), TripStatus = table.Column(type: "nvarchar(max)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), @@ -751,9 +727,6 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "AspNetRoles"); - migrationBuilder.DropTable( - name: "AspNetUsers"); - migrationBuilder.DropTable( name: "Buildings"); @@ -770,7 +743,7 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "PaymentMethods"); migrationBuilder.DropTable( - name: "ApplicationUser"); + name: "AspNetUsers"); migrationBuilder.DropTable( name: "Wallets"); diff --git a/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs index ac6ffb3..b3b4b4a 100644 --- a/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs @@ -8,7 +8,7 @@ #nullable disable -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Migrations +namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] partial class ApplicationDbContextModelSnapshot : ModelSnapshot @@ -483,6 +483,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); + b.Property("ShipDate") + .HasColumnType("datetime2"); + b.Property("TotalPrice") .HasColumnType("float"); @@ -644,8 +647,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StartTime") .HasColumnType("datetime2"); - b.Property("TripCollect") - .HasColumnType("decimal(18,2)"); + b.Property("TripCollect") + .HasColumnType("int"); b.Property("TripStatus") .HasColumnType("nvarchar(max)"); @@ -742,8 +745,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Amount") - .HasColumnType("decimal(18,2)"); + b.Property("Amount") + .HasColumnType("int"); b.Property("Created") .HasColumnType("datetime2"); @@ -785,8 +788,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Balance") - .HasColumnType("decimal(18,2)"); + b.Property("Balance") + .HasColumnType("float"); b.Property("Created") .HasColumnType("datetime2"); @@ -811,61 +814,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasColumnType("nvarchar(max)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - 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("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", b => { b.Property("Id") .HasColumnType("nvarchar(450)"); @@ -890,6 +838,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LockoutEnd") .HasColumnType("datetimeoffset"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + b.Property("NormalizedEmail") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -941,7 +892,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -950,7 +901,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -965,7 +916,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -974,7 +925,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("SWD_Laundry_Backend.Infrastructure.Identity.ApplicationUser", null) + b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) diff --git a/src/WebUI/Program.cs b/src/WebUI/Program.cs index f538093..9bd391b 100644 --- a/src/WebUI/Program.cs +++ b/src/WebUI/Program.cs @@ -18,12 +18,10 @@ app.UseMigrationsEndPoint(); // Initialise and seed database - using (var scope = app.Services.CreateScope()) - { - var initialiser = scope.ServiceProvider.GetRequiredService(); - await initialiser.InitialiseAsync(); - await initialiser.SeedAsync(); - } + using var scope = app.Services.CreateScope(); + var initialiser = scope.ServiceProvider.GetRequiredService(); + await initialiser.InitialiseAsync(); + await initialiser.SeedAsync(); } else { diff --git a/src/WebUI/appsettings.json b/src/WebUI/appsettings.json index 0dab0a7..63f5e42 100644 --- a/src/WebUI/appsettings.json +++ b/src/WebUI/appsettings.json @@ -1,7 +1,7 @@ { "UseInMemoryDatabase": false, "ConnectionStrings": { - "DefaultConnection": "Server=LEWIS;Database=SWD_Laundry_BackendDb;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=123456;TrustServerCertificate=true" + "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=Laundry;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=12345" }, "Logging": { From 98b1ca69180a17c18f1de0b282e520e673db71e9 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:03:56 +0700 Subject: [PATCH 03/53] Update Enum, Update Database, Template Command and Query --- .../CreateBuilding/CreateBuildingCommand.cs | 36 +++++++++ .../CreateBuildingCommandValidator.cs | 17 +++++ .../DeleteBuilding/DeleteBuildingCommand.cs | 24 ++++++ .../UpdateBuilding/UpdateBuildingCommand.cs | 33 ++++++++ .../UpdateBuildingCommandValidator.cs | 17 +++++ .../Building/Queries/BuildingViewModel.cs | 9 +++ .../Building/Queries/GetAllBuildingQuery.cs | 29 +++++++ .../Interfaces/IApplicationDbContext.cs | 4 +- .../GetWeatherForecastsQuery.cs | 27 ------- .../GetWeatherForecasts/WeatherForecast.cs | 12 --- src/Domain/Entities/Building.cs | 8 +- src/Domain/Entities/Customer.cs | 52 ++++++------- src/Domain/Entities/Order.cs | 26 ++++--- src/Domain/Entities/PaymentMethod.cs | 23 +++--- src/Domain/Entities/Staff.cs | 76 ++++++++++--------- src/Domain/Entities/Transaction.cs | 41 ++++------ src/Domain/Entities/Wallet.cs | 11 +-- src/Domain/Enums/AllowedTransactionType.cs | 8 ++ src/Domain/Enums/OrderType.cs | 6 ++ src/Domain/Enums/PaymentType.cs | 8 ++ src/Domain/Enums/StaffRole.cs | 6 ++ src/Domain/Enums/Status.cs | 8 ++ .../Persistence/ApplicationDbContext.cs | 4 +- .../Controllers/WeatherForecastController.cs | 13 ---- src/WebUI/Pages/Shared/_LoginPartial.cshtml | 1 - src/WebUI/wwwroot/api/specification.json | 45 ----------- 26 files changed, 316 insertions(+), 228 deletions(-) create mode 100644 src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs create mode 100644 src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs create mode 100644 src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs create mode 100644 src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs create mode 100644 src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs create mode 100644 src/Application/Building/Queries/BuildingViewModel.cs create mode 100644 src/Application/Building/Queries/GetAllBuildingQuery.cs delete mode 100644 src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs delete mode 100644 src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs create mode 100644 src/Domain/Enums/AllowedTransactionType.cs create mode 100644 src/Domain/Enums/OrderType.cs create mode 100644 src/Domain/Enums/PaymentType.cs create mode 100644 src/Domain/Enums/StaffRole.cs create mode 100644 src/Domain/Enums/Status.cs delete mode 100644 src/WebUI/Controllers/WeatherForecastController.cs delete mode 100644 src/WebUI/Pages/Shared/_LoginPartial.cshtml diff --git a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs b/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs new file mode 100644 index 0000000..9c9fbb7 --- /dev/null +++ b/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs @@ -0,0 +1,36 @@ +using MediatR; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; +public class CreateBuildingCommand : IRequest +{ + public string Name { get; set; } + public string Address { get; set; } + public string Description { get; set; } +} + +public class CreateBuildingCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public CreateBuildingCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(CreateBuildingCommand request, CancellationToken cancellationToken) + { + var entity = new Domain.Entities.Building + { + Name = request.Name, + Address = request.Address, + Description = request.Description + }; + + _context.Get().Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} \ No newline at end of file diff --git a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs b/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs new file mode 100644 index 0000000..8ddf47c --- /dev/null +++ b/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs @@ -0,0 +1,17 @@ +using FluentValidation; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; +public class CreateBuildingCommandValidator : AbstractValidator +{ + private readonly IApplicationDbContext _context; + + public CreateBuildingCommandValidator(IApplicationDbContext context) + { + _context = context; + + RuleFor(v => v.Name).NotEmpty(); + RuleFor(v => v.Description).NotEmpty(); + RuleFor(v => v.Address).NotEmpty(); + } +} diff --git a/src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs b/src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs new file mode 100644 index 0000000..d50e9d8 --- /dev/null +++ b/src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs @@ -0,0 +1,24 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Commands.DeleteBuilding; +public class DeleteBuildingCommand : IRequest +{ + public int Id { get; set; } +} + +public class DeleteBuildingCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + public DeleteBuildingCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(DeleteBuildingCommand request, CancellationToken cancellationToken) + { + var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken); + return affectedRow; + } +} diff --git a/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs b/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs new file mode 100644 index 0000000..284b7e5 --- /dev/null +++ b/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs @@ -0,0 +1,33 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Exceptions; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Commands.UpdateBuilding; +public class UpdateBuildingCommand : IRequest +{ + public int Id { get; set; } + public string Name { get; set; } = null!; + public string Address { get; set; } = null!; + public string Description { get; set; } = null!; +} + +public class UpdateBuildingCommandHandler : IRequestHandler +{ + + private readonly IApplicationDbContext _context; + public UpdateBuildingCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(UpdateBuildingCommand request, CancellationToken cancellationToken) + { + var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => + x.SetProperty(y => y.Name, request.Name) + .SetProperty(y => y.Address, request.Address) + .SetProperty(y => y.Description, request.Description), cancellationToken: cancellationToken); + return affectedRow; + } +} + diff --git a/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs b/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs new file mode 100644 index 0000000..8c62e9e --- /dev/null +++ b/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs @@ -0,0 +1,17 @@ +using FluentValidation; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Commands.UpdateBuilding; +public class UpdateBuildingCommandValidator : AbstractValidator +{ + private readonly IApplicationDbContext _context; + + public UpdateBuildingCommandValidator(IApplicationDbContext context) + { + _context = context; + + RuleFor(v => v.Name); + RuleFor(v => v.Address); + RuleFor(v => v.Description); + } +} diff --git a/src/Application/Building/Queries/BuildingViewModel.cs b/src/Application/Building/Queries/BuildingViewModel.cs new file mode 100644 index 0000000..72e94b5 --- /dev/null +++ b/src/Application/Building/Queries/BuildingViewModel.cs @@ -0,0 +1,9 @@ +using SWD_Laundry_Backend.Application.Common.Mappings; + +namespace SWD_Laundry_Backend.Application.Building.Queries; +public class BuildingViewModel : IMapFrom +{ + public string Name { get; set; } + public string Address { get; set; } + public string Description { get; set; } +} diff --git a/src/Application/Building/Queries/GetAllBuildingQuery.cs b/src/Application/Building/Queries/GetAllBuildingQuery.cs new file mode 100644 index 0000000..ae2403e --- /dev/null +++ b/src/Application/Building/Queries/GetAllBuildingQuery.cs @@ -0,0 +1,29 @@ +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Queries; +public class GetAllBuildingQuery : IRequest> +{ + +} + +public class GetAllBuildingQueryHandler : IRequestHandler> +{ + + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + public GetAllBuildingQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task> Handle(GetAllBuildingQuery request, CancellationToken cancellationToken) + { + var buildingList = await _context.Get().AsNoTracking().ToListAsync(cancellationToken); + return _mapper.Map>(buildingList); + } + +} diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index ce11bb6..54e69f7 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -1,5 +1,6 @@ using SWD_Laundry_Backend.Domain.Entities; using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Domain.Common; namespace SWD_Laundry_Backend.Application.Common.Interfaces; @@ -8,6 +9,7 @@ public interface IApplicationDbContext DbSet TodoLists { get; } DbSet TodoItems { get; } - + DbSet Get() where T : BaseAuditableEntity; Task SaveChangesAsync(CancellationToken cancellationToken); + } diff --git a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs deleted file mode 100644 index e3618b7..0000000 --- a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/GetWeatherForecastsQuery.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; - -namespace SWD_Laundry_Backend.Application.WeatherForecasts.Queries.GetWeatherForecasts; - -public record GetWeatherForecastsQuery : IRequest>; - -public class GetWeatherForecastsQueryHandler : IRequestHandler> -{ - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - public async Task> Handle(GetWeatherForecastsQuery request, CancellationToken cancellationToken) -#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - { - var rng = new Random(); - - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateTime.Now.AddDays(index), - TemperatureC = rng.Next(-20, 55), - Summary = Summaries[rng.Next(Summaries.Length)] - }); - } -} diff --git a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs b/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs deleted file mode 100644 index 0d41b8a..0000000 --- a/src/Application/WeatherForecasts/Queries/GetWeatherForecasts/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SWD_Laundry_Backend.Application.WeatherForecasts.Queries.GetWeatherForecasts; - -public class WeatherForecast -{ - public DateTime Date { get; init; } - - public int TemperatureC { get; init; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; init; } -} diff --git a/src/Domain/Entities/Building.cs b/src/Domain/Entities/Building.cs index e596d9c..0df9893 100644 --- a/src/Domain/Entities/Building.cs +++ b/src/Domain/Entities/Building.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Domain.Entities; +namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable public class Building : BaseAuditableEntity diff --git a/src/Domain/Entities/Customer.cs b/src/Domain/Entities/Customer.cs index 2e2ef54..10e5166 100644 --- a/src/Domain/Entities/Customer.cs +++ b/src/Domain/Entities/Customer.cs @@ -8,7 +8,7 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Customer : BaseAuditableEntity { - public string Name { get; set; } + //public string Name { get; set; } //public string Address { get; set; } #region Relationship @@ -30,31 +30,31 @@ public class Customer : BaseAuditableEntity #region Special Attribute - private string _email; - - private string _phone; - - public string Email - { - get { return _email; } - set - { - _email = new Validate().IsValidEmail(value) - ? value - : throw new ArgumentException("Invalid email."); - } - } - - public string Phone - { - get { return _phone; } - set - { - _phone = new Validate().IsValidPhone(value) - ? value - : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - } - } + //private string _email; + + //private string _phone; + + //public string Email + //{ + // get { return _email; } + // set + // { + // _email = new Validate().IsValidEmail(value) + // ? value + // : throw new ArgumentException("Invalid email."); + // } + //} + + //public string Phone + //{ + // get { return _phone; } + // set + // { + // _phone = new Validate().IsValidPhone(value) + // ? value + // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); + // } + //} #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs index ccf52e3..ace9e7c 100644 --- a/src/Domain/Entities/Order.cs +++ b/src/Domain/Entities/Order.cs @@ -39,18 +39,20 @@ public class Order : BaseAuditableEntity #region Special Attribute - private string _orderType; - - public string OrderType - { - get => _orderType; - set - { - _orderType = new Validate().IsValidOrderType(value) - ? value - : throw new Exception("Invalid order type {ONEWAY, TWOWAY}"); - } - } + //private string _orderType; + + //public string OrderType + //{ + // get => _orderType; + // set + // { + // _orderType = new Validate().IsValidOrderType(value) + // ? value + // : throw new Exception("Invalid order type {ONEWAY, TWOWAY}"); + // } + //} + + public OrderType OrderType { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 065a6ac..e3259e1 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -10,16 +10,17 @@ public class PaymentMethod : BaseAuditableEntity /// /// Special attributes /// - private string _type; + //private string _type; - public string PaymentType - { - get { return _type; } - set - { - _type = new Validate().IsValidPayment(value) - ? value - : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); - } - } + //public string PaymentType + //{ + // get { return _type; } + // set + // { + // _type = new Validate().IsValidPayment(value) + // ? value + // : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); + // } + //} + public PaymentType PaymentType { get; set; } } \ No newline at end of file diff --git a/src/Domain/Entities/Staff.cs b/src/Domain/Entities/Staff.cs index f67a2c5..e96c0ec 100644 --- a/src/Domain/Entities/Staff.cs +++ b/src/Domain/Entities/Staff.cs @@ -27,43 +27,45 @@ public class Staff : BaseAuditableEntity #region Special Attribute - private string _email; - - private string _phone; - private string _role; - - public string Role - { - get { return _role; } - set - { - _role = new Validate().IsValidStaffRole(value) - ? value - : throw new ArgumentException("Invalid staff role {COLLECTOR, RECEIVER}."); - } - } - - public string Email - { - get { return _email; } - set - { - _email = new Validate().IsValidEmail(value) - ? value - : throw new ArgumentException("Invalid email."); - } - } - - public string Phone - { - get { return _phone; } - set - { - _phone = new Validate().IsValidPhone(value) - ? value - : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - } - } + public StaffRole StaffRole { get; set; } + + //private string _email; + + //private string _phone; + //private string _role; + + //public string Role + //{ + // get { return _role; } + // set + // { + // _role = new Validate().IsValidStaffRole(value) + // ? value + // : throw new ArgumentException("Invalid staff role {COLLECTOR, RECEIVER}."); + // } + //} + + //public string Email + //{ + // get { return _email; } + // set + // { + // _email = new Validate().IsValidEmail(value) + // ? value + // : throw new ArgumentException("Invalid email."); + // } + //} + + //public string Phone + //{ + // get { return _phone; } + // set + // { + // _phone = new Validate().IsValidPhone(value) + // ? value + // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); + // } + //} #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs index fea27c2..e8ec326 100644 --- a/src/Domain/Entities/Transaction.cs +++ b/src/Domain/Entities/Transaction.cs @@ -19,31 +19,22 @@ public class Transaction : BaseAuditableEntity #region Special Attribute - private string _transactiontype; - - private string _status; - - public string TransactionType - { - get { return _transactiontype; } - set - { - if (!new Validate().IsValidTransactionType(value)) - throw new ArgumentException("Invalid transaction type {DEPOSIT, WITHDRAWAL, DEBT, PAID}."); - _transactiontype = value; - } - } - - public string Status - { - get { return _status; } - set - { - if (!new Validate().IsValidTransactionStatus(value)) - throw new ArgumentException("Invalid transaction status {FINISHED, PROCESSING, CANCELLED}."); - _status = value; - } - } + //private string _transactiontype; + + //public string TransactionType + //{ + // get { return _transactiontype; } + // set + // { + // if (!new Validate().IsValidTransactionType(value)) + // throw new ArgumentException("Invalid transaction type {DEPOSIT, WITHDRAWAL, DEBT, PAID}."); + // _transactiontype = value; + // } + //} + + public AllowedTransactionType TransactionType { get; set; } + + public Status Status { get; set;} #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Wallet.cs b/src/Domain/Entities/Wallet.cs index b79a011..c93653c 100644 --- a/src/Domain/Entities/Wallet.cs +++ b/src/Domain/Entities/Wallet.cs @@ -1,17 +1,8 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Domain.Entities; +namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable public class Wallet : BaseAuditableEntity { public double Balance { get; set; } - } \ No newline at end of file diff --git a/src/Domain/Enums/AllowedTransactionType.cs b/src/Domain/Enums/AllowedTransactionType.cs new file mode 100644 index 0000000..eb2fbbb --- /dev/null +++ b/src/Domain/Enums/AllowedTransactionType.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Domain.Enums; +public enum AllowedTransactionType +{ + Deposit = 1, + Withdraw = 2, + Debt = 3, + Paid = 4 +} diff --git a/src/Domain/Enums/OrderType.cs b/src/Domain/Enums/OrderType.cs new file mode 100644 index 0000000..cb5aa61 --- /dev/null +++ b/src/Domain/Enums/OrderType.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Domain.Enums; +public enum OrderType +{ + OneWay = 1, + TwoWay = 2 +} diff --git a/src/Domain/Enums/PaymentType.cs b/src/Domain/Enums/PaymentType.cs new file mode 100644 index 0000000..1c5fe8c --- /dev/null +++ b/src/Domain/Enums/PaymentType.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Domain.Enums; +public enum PaymentType +{ + Cash = 1, + CreditCard = 2, + DebitCard = 3, + EWallet = 4 +} diff --git a/src/Domain/Enums/StaffRole.cs b/src/Domain/Enums/StaffRole.cs new file mode 100644 index 0000000..708fd15 --- /dev/null +++ b/src/Domain/Enums/StaffRole.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Domain.Enums; +public enum StaffRole +{ + COLLECTOR = 1, + RECIEVER = 2, +} diff --git a/src/Domain/Enums/Status.cs b/src/Domain/Enums/Status.cs new file mode 100644 index 0000000..9f5770b --- /dev/null +++ b/src/Domain/Enums/Status.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Domain.Enums; +public enum Status +{ + Pending = 1, + Processing = 2, + Completed = 3, + Cancelled = 4 +} diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index 33a227d..c6169ce 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -5,10 +5,10 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Common; using SWD_Laundry_Backend.Domain.Entities; using SWD_Laundry_Backend.Domain.IdentityModel; -//using SWD_Laundry_Backend.Infrastructure.Identity; using SWD_Laundry_Backend.Infrastructure.Persistence.Interceptors; namespace SWD_Laundry_Backend.Infrastructure.Persistence; @@ -65,4 +65,6 @@ public override async Task SaveChangesAsync(CancellationToken cancellationT return await base.SaveChangesAsync(cancellationToken); } + + public DbSet Get() where T : BaseAuditableEntity => Set(); } \ No newline at end of file diff --git a/src/WebUI/Controllers/WeatherForecastController.cs b/src/WebUI/Controllers/WeatherForecastController.cs deleted file mode 100644 index c0b97ae..0000000 --- a/src/WebUI/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,13 +0,0 @@ -using SWD_Laundry_Backend.Application.WeatherForecasts.Queries.GetWeatherForecasts; -using Microsoft.AspNetCore.Mvc; - -namespace SWD_Laundry_Backend.WebUI.Controllers; - -public class WeatherForecastController : ApiControllerBase -{ - [HttpGet] - public async Task> Get() - { - return await Mediator.Send(new GetWeatherForecastsQuery()); - } -} diff --git a/src/WebUI/Pages/Shared/_LoginPartial.cshtml b/src/WebUI/Pages/Shared/_LoginPartial.cshtml deleted file mode 100644 index 5f28270..0000000 --- a/src/WebUI/Pages/Shared/_LoginPartial.cshtml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/WebUI/wwwroot/api/specification.json b/src/WebUI/wwwroot/api/specification.json index 56e159e..af7a019 100644 --- a/src/WebUI/wwwroot/api/specification.json +++ b/src/WebUI/wwwroot/api/specification.json @@ -403,29 +403,6 @@ } } } - }, - "/api/WeatherForecast": { - "get": { - "tags": [ - "WeatherForecast" - ], - "operationId": "WeatherForecast_Get", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WeatherForecast" - } - } - } - } - } - } - } } }, "components": { @@ -706,28 +683,6 @@ "nullable": false } } - }, - "WeatherForecast": { - "type": "object", - "additionalProperties": false, - "properties": { - "date": { - "type": "string", - "format": "date-time" - }, - "temperatureC": { - "type": "integer", - "format": "int32" - }, - "temperatureF": { - "type": "integer", - "format": "int32" - }, - "summary": { - "type": "string", - "nullable": true - } - } } }, "securitySchemes": { From 39521915681f743b816a5b02e691ee71ea96051b Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:07:10 +0700 Subject: [PATCH 04/53] Migration --- .../20230918120532_InitMigration.Designer.cs} | 39 ++++++------------- .../20230918120532_InitMigration.cs} | 15 +++---- .../ApplicationDbContextModelSnapshot.cs | 37 ++++++------------ 3 files changed, 28 insertions(+), 63 deletions(-) rename src/Infrastructure/{Persistence/Migrations/20230917231227_InitMigration.Designer.cs => Migrations/20230918120532_InitMigration.Designer.cs} (97%) rename src/Infrastructure/{Persistence/Migrations/20230917231227_InitMigration.cs => Migrations/20230918120532_InitMigration.cs} (97%) rename src/Infrastructure/{Persistence => }/Migrations/ApplicationDbContextModelSnapshot.cs (97%) diff --git a/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.Designer.cs b/src/Infrastructure/Migrations/20230918120532_InitMigration.Designer.cs similarity index 97% rename from src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.Designer.cs rename to src/Infrastructure/Migrations/20230918120532_InitMigration.Designer.cs index dd27a0a..e8940ca 100644 --- a/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.Designer.cs +++ b/src/Infrastructure/Migrations/20230918120532_InitMigration.Designer.cs @@ -12,7 +12,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230917231227_InitMigration")] + [Migration("20230918120532_InitMigration")] partial class InitMigration { /// @@ -357,21 +357,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); - b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - b.Property("WalletID") .HasColumnType("int"); @@ -480,8 +471,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("OrderDate") .HasColumnType("datetime2"); - b.Property("OrderType") - .HasColumnType("nvarchar(max)"); + b.Property("OrderType") + .HasColumnType("int"); b.Property("PaymentMethodID") .HasColumnType("int"); @@ -557,8 +548,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("PaymentType") - .HasColumnType("nvarchar(max)"); + b.Property("PaymentType") + .HasColumnType("int"); b.HasKey("Id"); @@ -588,24 +579,18 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Dob") .HasColumnType("datetime2"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); - b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - - b.Property("Role") - .HasColumnType("nvarchar(max)"); - b.Property("Salary") .HasColumnType("float"); + b.Property("StaffRole") + .HasColumnType("int"); + b.Property("WalletID") .HasColumnType("int"); @@ -769,11 +754,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PaymentMethod") .HasColumnType("nvarchar(max)"); - b.Property("Status") - .HasColumnType("nvarchar(max)"); + b.Property("Status") + .HasColumnType("int"); - b.Property("TransactionType") - .HasColumnType("nvarchar(max)"); + b.Property("TransactionType") + .HasColumnType("int"); b.Property("WalletID") .HasColumnType("int"); diff --git a/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.cs b/src/Infrastructure/Migrations/20230918120532_InitMigration.cs similarity index 97% rename from src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.cs rename to src/Infrastructure/Migrations/20230918120532_InitMigration.cs index b75f302..fb6ae3a 100644 --- a/src/Infrastructure/Persistence/Migrations/20230917231227_InitMigration.cs +++ b/src/Infrastructure/Migrations/20230918120532_InitMigration.cs @@ -114,7 +114,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Description = table.Column(type: "nvarchar(max)", nullable: true), - PaymentType = table.Column(type: "nvarchar(max)", nullable: true), + PaymentType = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -173,8 +173,8 @@ protected override void Up(MigrationBuilder migrationBuilder) Amount = table.Column(type: "int", nullable: false), Description = table.Column(type: "nvarchar(max)", nullable: true), WalletID = table.Column(type: "int", nullable: false), - TransactionType = table.Column(type: "nvarchar(max)", nullable: true), - Status = table.Column(type: "nvarchar(max)", nullable: true), + TransactionType = table.Column(type: "int", nullable: false), + Status = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -306,7 +306,7 @@ protected override void Up(MigrationBuilder migrationBuilder) TotalPrice = table.Column(type: "float", nullable: false), PaymentMethodID = table.Column(type: "int", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - OrderType = table.Column(type: "nvarchar(max)", nullable: true), + OrderType = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -409,12 +409,9 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), BuildingID = table.Column(type: "int", nullable: false), WalletID = table.Column(type: "int", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Email = table.Column(type: "nvarchar(max)", nullable: true), - Phone = table.Column(type: "nvarchar(max)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -489,9 +486,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Salary = table.Column(type: "float", nullable: false), WalletID = table.Column(type: "int", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Role = table.Column(type: "nvarchar(max)", nullable: true), - Email = table.Column(type: "nvarchar(max)", nullable: true), - Phone = table.Column(type: "nvarchar(max)", nullable: true), + StaffRole = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), diff --git a/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs similarity index 97% rename from src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs rename to src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index b3b4b4a..7d1fd09 100644 --- a/src/Infrastructure/Persistence/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -354,21 +354,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); - b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - b.Property("WalletID") .HasColumnType("int"); @@ -477,8 +468,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("OrderDate") .HasColumnType("datetime2"); - b.Property("OrderType") - .HasColumnType("nvarchar(max)"); + b.Property("OrderType") + .HasColumnType("int"); b.Property("PaymentMethodID") .HasColumnType("int"); @@ -554,8 +545,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("PaymentType") - .HasColumnType("nvarchar(max)"); + b.Property("PaymentType") + .HasColumnType("int"); b.HasKey("Id"); @@ -585,24 +576,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Dob") .HasColumnType("datetime2"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); - b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - - b.Property("Role") - .HasColumnType("nvarchar(max)"); - b.Property("Salary") .HasColumnType("float"); + b.Property("StaffRole") + .HasColumnType("int"); + b.Property("WalletID") .HasColumnType("int"); @@ -766,11 +751,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PaymentMethod") .HasColumnType("nvarchar(max)"); - b.Property("Status") - .HasColumnType("nvarchar(max)"); + b.Property("Status") + .HasColumnType("int"); - b.Property("TransactionType") - .HasColumnType("nvarchar(max)"); + b.Property("TransactionType") + .HasColumnType("int"); b.Property("WalletID") .HasColumnType("int"); From 62cdd93f73279ff466329feb9f25600a695fe766 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:11:52 +0700 Subject: [PATCH 05/53] Migration --- src/Infrastructure/Infrastructure.csproj | 6 ------ ...Designer.cs => 20230918121016_InitMigration.Designer.cs} | 2 +- ...532_InitMigration.cs => 20230918121016_InitMigration.cs} | 0 3 files changed, 1 insertion(+), 7 deletions(-) rename src/Infrastructure/Migrations/{20230918120532_InitMigration.Designer.cs => 20230918121016_InitMigration.Designer.cs} (99%) rename src/Infrastructure/Migrations/{20230918120532_InitMigration.cs => 20230918121016_InitMigration.cs} (100%) diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 1220f15..e6dfee7 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -8,12 +8,6 @@ enable - - - - - - diff --git a/src/Infrastructure/Migrations/20230918120532_InitMigration.Designer.cs b/src/Infrastructure/Migrations/20230918121016_InitMigration.Designer.cs similarity index 99% rename from src/Infrastructure/Migrations/20230918120532_InitMigration.Designer.cs rename to src/Infrastructure/Migrations/20230918121016_InitMigration.Designer.cs index e8940ca..75b1d3d 100644 --- a/src/Infrastructure/Migrations/20230918120532_InitMigration.Designer.cs +++ b/src/Infrastructure/Migrations/20230918121016_InitMigration.Designer.cs @@ -12,7 +12,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230918120532_InitMigration")] + [Migration("20230918121016_InitMigration")] partial class InitMigration { /// diff --git a/src/Infrastructure/Migrations/20230918120532_InitMigration.cs b/src/Infrastructure/Migrations/20230918121016_InitMigration.cs similarity index 100% rename from src/Infrastructure/Migrations/20230918120532_InitMigration.cs rename to src/Infrastructure/Migrations/20230918121016_InitMigration.cs From 93bde4e129bde61a067ee93be4176f64eedec140 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 18 Sep 2023 21:48:20 +0700 Subject: [PATCH 06/53] Update Entities, Building Controller --- .../CreateBuilding/CreateBuildingCommand.cs | 6 +- .../Building/Queries/GetBuildingQuery.cs | 27 ++ src/Domain/Entities/LaundryStore.cs | 50 +-- src/Domain/Entities/OrderHistory.cs | 25 +- src/Domain/Entities/Staff_Trip.cs | 26 +- ... 20230918144740_InitMigration.Designer.cs} | 16 +- ...ion.cs => 20230918144740_InitMigration.cs} | 6 +- .../ApplicationDbContextModelSnapshot.cs | 14 +- src/WebUI/Controllers/BuildingController.cs | 56 ++++ src/WebUI/Controllers/TodoItemsController.cs | 2 - src/WebUI/WebUI.csproj | 1 + src/WebUI/wwwroot/api/specification.json | 302 ++++++++++++++++-- 12 files changed, 423 insertions(+), 108 deletions(-) create mode 100644 src/Application/Building/Queries/GetBuildingQuery.cs rename src/Infrastructure/Migrations/{20230918121016_InitMigration.Designer.cs => 20230918144740_InitMigration.Designer.cs} (98%) rename src/Infrastructure/Migrations/{20230918121016_InitMigration.cs => 20230918144740_InitMigration.cs} (99%) create mode 100644 src/WebUI/Controllers/BuildingController.cs diff --git a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs b/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs index 9c9fbb7..56992ad 100644 --- a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs +++ b/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs @@ -4,9 +4,9 @@ namespace SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; public class CreateBuildingCommand : IRequest { - public string Name { get; set; } - public string Address { get; set; } - public string Description { get; set; } + public string? Name { get; set; } + public string? Address { get; set; } + public string? Description { get; set; } } public class CreateBuildingCommandHandler : IRequestHandler diff --git a/src/Application/Building/Queries/GetBuildingQuery.cs b/src/Application/Building/Queries/GetBuildingQuery.cs new file mode 100644 index 0000000..f654f05 --- /dev/null +++ b/src/Application/Building/Queries/GetBuildingQuery.cs @@ -0,0 +1,27 @@ +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Building.Queries; +public class GetBuildingQuery : IRequest +{ + public int Id { init; get; } +} + +public class GetBuildingQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + public GetBuildingQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(GetBuildingQuery request, CancellationToken cancellationToken) + { + var building = await _context.Get().AsNoTracking().FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); + return _mapper.Map(building); + } +} \ No newline at end of file diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs index 33163d5..d89bf16 100644 --- a/src/Domain/Entities/LaundryStore.cs +++ b/src/Domain/Entities/LaundryStore.cs @@ -25,31 +25,31 @@ public class LaundryStore : BaseAuditableEntity #region Special Attribute - private string _email; - - private string _phone; - - public string Email - { - get { return _email; } - set - { - _email = new Validate().IsValidEmail(value) - ? value - : throw new ArgumentException("Invalid email."); - } - } - - public string Phone - { - get { return _phone; } - set - { - _phone = new Validate().IsValidPhone(value) - ? value - : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - } - } + //private string _email; + + //private string _phone; + + //public string Email + //{ + // get { return _email; } + // set + // { + // _email = new Validate().IsValidEmail(value) + // ? value + // : throw new ArgumentException("Invalid email."); + // } + //} + + //public string Phone + //{ + // get { return _phone; } + // set + // { + // _phone = new Validate().IsValidPhone(value) + // ? value + // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); + // } + //} #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/OrderHistory.cs b/src/Domain/Entities/OrderHistory.cs index a5a820a..f660ac5 100644 --- a/src/Domain/Entities/OrderHistory.cs +++ b/src/Domain/Entities/OrderHistory.cs @@ -17,18 +17,19 @@ public class OrderHistory : BaseAuditableEntity #region Special attributes - private string _orderstatus; - - public string Status - { - get { return _orderstatus; } - set - { - _orderstatus = new Validate().IsValidTripStatus(value) - ? value - : throw new ArgumentException("Invalid order status {FINISHED, PROCESSING, CANCELLED}."); - } - } + //private string _orderstatus; + + //public string Status + //{ + // get { return _orderstatus; } + // set + // { + // _orderstatus = new Validate().IsValidTripStatus(value) + // ? value + // : throw new ArgumentException("Invalid order status {FINISHED, PROCESSING, CANCELLED}."); + // } + //} + public Status Status { get; set;} #endregion Special attributes } \ No newline at end of file diff --git a/src/Domain/Entities/Staff_Trip.cs b/src/Domain/Entities/Staff_Trip.cs index ced3743..0b06afa 100644 --- a/src/Domain/Entities/Staff_Trip.cs +++ b/src/Domain/Entities/Staff_Trip.cs @@ -28,18 +28,20 @@ public class Staff_Trip : BaseAuditableEntity #region Special Attribute - private string _tripstatus; - - public string TripStatus - { - get { return _tripstatus; } - set - { - _tripstatus = new Validate().IsValidTripStatus(value) - ? value - : throw new ArgumentException("Invalid trip status {FINISHED, PROCESSING, CANCELLED}."); - } - } + //private string _tripstatus; + + //public string TripStatus + //{ + // get { return _tripstatus; } + // set + // { + // _tripstatus = new Validate().IsValidTripStatus(value) + // ? value + // : throw new ArgumentException("Invalid trip status {FINISHED, PROCESSING, CANCELLED}."); + // } + //} + + public Status TripStatus { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/Infrastructure/Migrations/20230918121016_InitMigration.Designer.cs b/src/Infrastructure/Migrations/20230918144740_InitMigration.Designer.cs similarity index 98% rename from src/Infrastructure/Migrations/20230918121016_InitMigration.Designer.cs rename to src/Infrastructure/Migrations/20230918144740_InitMigration.Designer.cs index 75b1d3d..c98c812 100644 --- a/src/Infrastructure/Migrations/20230918121016_InitMigration.Designer.cs +++ b/src/Infrastructure/Migrations/20230918144740_InitMigration.Designer.cs @@ -12,7 +12,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230918121016_InitMigration")] + [Migration("20230918144740_InitMigration")] partial class InitMigration { /// @@ -397,9 +397,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); - b.Property("EndTime") .HasColumnType("datetime2"); @@ -412,9 +409,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Name") .HasColumnType("nvarchar(max)"); - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - b.Property("StartTime") .HasColumnType("datetime2"); @@ -515,8 +509,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("OrderID") .HasColumnType("int"); - b.Property("Status") - .HasColumnType("nvarchar(max)"); + b.Property("Status") + .HasColumnType("int"); b.HasKey("Id"); @@ -638,8 +632,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("TripCollect") .HasColumnType("int"); - b.Property("TripStatus") - .HasColumnType("nvarchar(max)"); + b.Property("TripStatus") + .HasColumnType("int"); b.HasKey("Id"); diff --git a/src/Infrastructure/Migrations/20230918121016_InitMigration.cs b/src/Infrastructure/Migrations/20230918144740_InitMigration.cs similarity index 99% rename from src/Infrastructure/Migrations/20230918121016_InitMigration.cs rename to src/Infrastructure/Migrations/20230918144740_InitMigration.cs index fb6ae3a..75fab74 100644 --- a/src/Infrastructure/Migrations/20230918121016_InitMigration.cs +++ b/src/Infrastructure/Migrations/20230918144740_InitMigration.cs @@ -386,7 +386,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), OrderID = table.Column(type: "int", nullable: false), - Status = table.Column(type: "nvarchar(max)", nullable: true), + Status = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -452,8 +452,6 @@ protected override void Up(MigrationBuilder migrationBuilder) Status = table.Column(type: "bit", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), WalletID = table.Column(type: "int", nullable: false), - Email = table.Column(type: "nvarchar(max)", nullable: true), - Phone = table.Column(type: "nvarchar(max)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -519,7 +517,7 @@ protected override void Up(MigrationBuilder migrationBuilder) EndTime = table.Column(type: "datetime2", nullable: false), TripCollect = table.Column(type: "int", nullable: false), StaffID = table.Column(type: "int", nullable: false), - TripStatus = table.Column(type: "nvarchar(max)", nullable: true), + TripStatus = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 7d1fd09..f6022f9 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -394,9 +394,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Email") - .HasColumnType("nvarchar(max)"); - b.Property("EndTime") .HasColumnType("datetime2"); @@ -409,9 +406,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .HasColumnType("nvarchar(max)"); - b.Property("Phone") - .HasColumnType("nvarchar(max)"); - b.Property("StartTime") .HasColumnType("datetime2"); @@ -512,8 +506,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("OrderID") .HasColumnType("int"); - b.Property("Status") - .HasColumnType("nvarchar(max)"); + b.Property("Status") + .HasColumnType("int"); b.HasKey("Id"); @@ -635,8 +629,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("TripCollect") .HasColumnType("int"); - b.Property("TripStatus") - .HasColumnType("nvarchar(max)"); + b.Property("TripStatus") + .HasColumnType("int"); b.HasKey("Id"); diff --git a/src/WebUI/Controllers/BuildingController.cs b/src/WebUI/Controllers/BuildingController.cs new file mode 100644 index 0000000..3b78109 --- /dev/null +++ b/src/WebUI/Controllers/BuildingController.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; +using SWD_Laundry_Backend.Application.Building.Commands.DeleteBuilding; +using SWD_Laundry_Backend.Application.Building.Commands.UpdateBuilding; +using SWD_Laundry_Backend.Application.Building.Queries; +using SWD_Laundry_Backend.WebUI.Controllers; +using Microsoft.AspNetCore.Http; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace WebUI.Controllers; +[ApiController] +public class BuildingController : ApiControllerBase +{ + // GET: api/ + [HttpGet] + public async Task>> Get() + { + return await Mediator.Send(new GetAllBuildingQuery()); + } + + // GET api//5 + [HttpGet("{id}")] + public async Task> Get(int id) + { + return await Mediator.Send(new GetBuildingQuery { Id = id }); + } + + // POST api/ + [HttpPost] + public async Task> Post([FromBody] CreateBuildingCommand command) + { + return await Mediator.Send(command); + } + + // PUT api//5 + [HttpPut] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesDefaultResponseType] + public async Task> Put([FromBody] UpdateBuildingCommand command) + { + return await Mediator.Send(command); + } + + // DELETE api//5 + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesDefaultResponseType] + public async Task> Delete(int id) + { + return await Mediator.Send(new DeleteBuildingCommand { Id = id }); + } +} diff --git a/src/WebUI/Controllers/TodoItemsController.cs b/src/WebUI/Controllers/TodoItemsController.cs index b7d532f..bec3bf3 100644 --- a/src/WebUI/Controllers/TodoItemsController.cs +++ b/src/WebUI/Controllers/TodoItemsController.cs @@ -4,9 +4,7 @@ using SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItem; using SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItemDetail; using SWD_Laundry_Backend.Application.TodoItems.Queries.GetTodoItemsWithPagination; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Http; namespace SWD_Laundry_Backend.WebUI.Controllers; diff --git a/src/WebUI/WebUI.csproj b/src/WebUI/WebUI.csproj index 3f81ae1..8d10436 100644 --- a/src/WebUI/WebUI.csproj +++ b/src/WebUI/WebUI.csproj @@ -30,6 +30,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + all diff --git a/src/WebUI/wwwroot/api/specification.json b/src/WebUI/wwwroot/api/specification.json index af7a019..85b94f0 100644 --- a/src/WebUI/wwwroot/api/specification.json +++ b/src/WebUI/wwwroot/api/specification.json @@ -6,6 +6,190 @@ "version": "1.0.0" }, "paths": { + "/api/Building": { + "get": { + "tags": [ + "Building" + ], + "operationId": "Building_GetAll", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BuildingViewModel" + } + } + } + } + } + } + }, + "post": { + "tags": [ + "Building" + ], + "operationId": "Building_Post", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBuildingCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "put": { + "tags": [ + "Building" + ], + "operationId": "Building_Put", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateBuildingCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "204": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + } + } + }, + "/api/Building/{id}": { + "get": { + "tags": [ + "Building" + ], + "operationId": "Building_Get", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BuildingViewModel" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Building" + ], + "operationId": "Building_Delete", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "204": { + "description": "" + }, + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + } + } + }, "/api/TodoItems": { "get": { "tags": [ @@ -407,6 +591,95 @@ }, "components": { "schemas": { + "BuildingViewModel": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "address": { + "type": "string" + }, + "description": { + "type": "string" + } + } + }, + "CreateBuildingCommand": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "address", + "description" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "nullable": false + }, + "address": { + "type": "string", + "minLength": 1, + "nullable": false + }, + "description": { + "type": "string", + "minLength": 1, + "nullable": false + } + } + }, + "ProblemDetails": { + "type": "object", + "additionalProperties": { + "nullable": true + }, + "properties": { + "type": { + "type": "string", + "nullable": true + }, + "title": { + "type": "string", + "nullable": true + }, + "status": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "detail": { + "type": "string", + "nullable": true + }, + "instance": { + "type": "string", + "nullable": true + } + } + }, + "UpdateBuildingCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "address": { + "type": "string" + }, + "description": { + "type": "string" + } + } + }, "PaginatedListOfTodoItemBriefDto": { "type": "object", "additionalProperties": false, @@ -477,35 +750,6 @@ } } }, - "ProblemDetails": { - "type": "object", - "additionalProperties": { - "nullable": true - }, - "properties": { - "type": { - "type": "string", - "nullable": true - }, - "title": { - "type": "string", - "nullable": true - }, - "status": { - "type": "integer", - "format": "int32", - "nullable": true - }, - "detail": { - "type": "string", - "nullable": true - }, - "instance": { - "type": "string", - "nullable": true - } - } - }, "UpdateTodoItemCommand": { "type": "object", "additionalProperties": false, From 2c542952408761dbc4fd1eb37e349f097d54ef2a Mon Sep 17 00:00:00 2001 From: Nero Date: Mon, 18 Sep 2023 22:21:00 +0700 Subject: [PATCH 07/53] Update aws.yml --- .github/workflows/aws.yml | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/aws.yml b/.github/workflows/aws.yml index 3584da7..aa52363 100644 --- a/.github/workflows/aws.yml +++ b/.github/workflows/aws.yml @@ -1,33 +1,33 @@ -# name: Deploy to Amazon EC2 + name: Build Test -# on: -# pull_request: -# branches: [ "master" ] + on: + pull_request: + branches: [ "master" ] -# permissions: -# contents: read + permissions: + contents: read # env: # DEPLOYMENT_FOLDER: C:\inetpub\wwwroot\SWD-Laundry-Project\ -# jobs: -# build: -# name: Publish and Deploy -# runs-on: windows-latest -# environment: production -# steps: -# - name: Checkout -# uses: actions/checkout@v3 + jobs: + build: + name: Build + runs-on: windows-latest + environment: production + steps: + - name: Checkout + uses: actions/checkout@v3 -# - name: Setup .NET SDK -# uses: actions/setup-dotnet@v3 -# with: -# dotnet-version: '7.0.401' # replace with your .NET version -# - name: Install dependencies -# run: dotnet restore -# - name: Build -# run: dotnet build --configuration Release --no-restore + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7.0.401' # replace with your .NET version + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore # - name: Publish # run: dotnet publish --configuration Release --output ./publish /p:RuntimeIdentifier=win-x64 /p:TargetFramework=net7.0 # - name: Archive Artifacts From 475e5dc8da6d74c5cc7c19ee360de3be5d5896d9 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Tue, 19 Sep 2023 03:02:42 +0700 Subject: [PATCH 08/53] Update --- src/Application/Application.csproj | 5 + .../CreateBuilding/CreateBuildingCommand.cs | 5 +- .../CreateBuildingCommandValidator.cs | 2 +- .../DeleteBuilding/DeleteBuildingCommand.cs | 5 +- .../UpdateBuilding/UpdateBuildingCommand.cs | 12 +- .../UpdateBuildingCommandValidator.cs | 2 +- .../Queries/BuildingViewModel.cs | 5 +- .../Queries/GetAllBuildingQuery.cs | 5 +- .../Queries/GetBuildingQuery.cs | 5 +- .../CreatePaymentMethodCommand.cs | 36 +++ .../Queries/GetAllPaymentMethods.cs | 38 +++ .../Queries/GetPaymentMethod.cs | 38 +++ .../Queries/PaymentMethodDto.cs | 10 + .../PaymentMethods/Queries/PaymentMethodVm.cs | 6 + .../PaymentMethods/Queries/PaymentTypeDto.cs | 6 + .../CreateWallet/CreateWalletCommand.cs | 32 +++ .../CreateWalletCommandValidator.cs | 15 ++ .../DeleteWallet/DeleteWalletCommand.cs | 25 ++ .../UpdateWallet/UpdateWalletCommand.cs | 27 +++ .../UpdateWalletCommandValidator.cs | 10 + .../Wallets/Queries/GetAllWalletQuery.cs | 30 +++ .../Wallets/Queries/GetWalletQuery.cs | 29 +++ .../Wallets/Queries/WalletViewModel.cs | 8 + src/Domain/Entities/PaymentMethod.cs | 4 +- src/WebUI/Controllers/BuildingController.cs | 9 +- src/WebUI/Controllers/WalletController.cs | 53 +++++ src/WebUI/wwwroot/api/specification.json | 222 ++++++++++++++++++ 27 files changed, 618 insertions(+), 26 deletions(-) rename src/Application/{Building => Buildings}/Commands/CreateBuilding/CreateBuildingCommand.cs (84%) rename src/Application/{Building => Buildings}/Commands/CreateBuilding/CreateBuildingCommandValidator.cs (86%) rename src/Application/{Building => Buildings}/Commands/DeleteBuilding/DeleteBuildingCommand.cs (70%) rename src/Application/{Building => Buildings}/Commands/UpdateBuilding/UpdateBuildingCommand.cs (64%) rename src/Application/{Building => Buildings}/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs (85%) rename src/Application/{Building => Buildings}/Queries/BuildingViewModel.cs (54%) rename src/Application/{Building => Buildings}/Queries/GetAllBuildingQuery.cs (78%) rename src/Application/{Building => Buildings}/Queries/GetBuildingQuery.cs (75%) create mode 100644 src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs create mode 100644 src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs create mode 100644 src/Application/PaymentMethods/Queries/GetPaymentMethod.cs create mode 100644 src/Application/PaymentMethods/Queries/PaymentMethodDto.cs create mode 100644 src/Application/PaymentMethods/Queries/PaymentMethodVm.cs create mode 100644 src/Application/PaymentMethods/Queries/PaymentTypeDto.cs create mode 100644 src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs create mode 100644 src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs create mode 100644 src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs create mode 100644 src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs create mode 100644 src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs create mode 100644 src/Application/Wallets/Queries/GetAllWalletQuery.cs create mode 100644 src/Application/Wallets/Queries/GetWalletQuery.cs create mode 100644 src/Application/Wallets/Queries/WalletViewModel.cs create mode 100644 src/WebUI/Controllers/WalletController.cs diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index 19aacde..fb6ef03 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -18,4 +18,9 @@ + + + + + diff --git a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs similarity index 84% rename from src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs rename to src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs index 56992ad..54ac321 100644 --- a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommand.cs +++ b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs @@ -1,7 +1,8 @@ using MediatR; using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; -namespace SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; +namespace SWD_Laundry_Backend.Application.Buildings.Commands.CreateBuilding; public class CreateBuildingCommand : IRequest { public string? Name { get; set; } @@ -27,7 +28,7 @@ public async Task Handle(CreateBuildingCommand request, CancellationToken c Description = request.Description }; - _context.Get().Add(entity); + _context.Get().Add(entity); await _context.SaveChangesAsync(cancellationToken); diff --git a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs similarity index 86% rename from src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs rename to src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs index 8ddf47c..be0b759 100644 --- a/src/Application/Building/Commands/CreateBuilding/CreateBuildingCommandValidator.cs +++ b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs @@ -1,7 +1,7 @@ using FluentValidation; using SWD_Laundry_Backend.Application.Common.Interfaces; -namespace SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; +namespace SWD_Laundry_Backend.Application.Buildings.Commands.CreateBuilding; public class CreateBuildingCommandValidator : AbstractValidator { private readonly IApplicationDbContext _context; diff --git a/src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs b/src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs similarity index 70% rename from src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs rename to src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs index d50e9d8..7ced21d 100644 --- a/src/Application/Building/Commands/DeleteBuilding/DeleteBuildingCommand.cs +++ b/src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs @@ -1,8 +1,9 @@ using MediatR; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; -namespace SWD_Laundry_Backend.Application.Building.Commands.DeleteBuilding; +namespace SWD_Laundry_Backend.Application.Buildings.Commands.DeleteBuilding; public class DeleteBuildingCommand : IRequest { public int Id { get; set; } @@ -18,7 +19,7 @@ public DeleteBuildingCommandHandler(IApplicationDbContext context) public async Task Handle(DeleteBuildingCommand request, CancellationToken cancellationToken) { - var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken); + var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken); return affectedRow; } } diff --git a/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs b/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs similarity index 64% rename from src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs rename to src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs index 284b7e5..bdeff0b 100644 --- a/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommand.cs +++ b/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs @@ -1,9 +1,9 @@ using MediatR; using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Exceptions; using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; -namespace SWD_Laundry_Backend.Application.Building.Commands.UpdateBuilding; +namespace SWD_Laundry_Backend.Application.Buildings.Commands.UpdateBuilding; public class UpdateBuildingCommand : IRequest { public int Id { get; set; } @@ -23,10 +23,10 @@ public UpdateBuildingCommandHandler(IApplicationDbContext context) public async Task Handle(UpdateBuildingCommand request, CancellationToken cancellationToken) { - var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => - x.SetProperty(y => y.Name, request.Name) - .SetProperty(y => y.Address, request.Address) - .SetProperty(y => y.Description, request.Description), cancellationToken: cancellationToken); + var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => + x.SetProperty(y => y.Name, y => request.Name ?? y.Name) + .SetProperty(y => y.Address, y => request.Address ?? y.Address) + .SetProperty(y => y.Description, y => request.Description ?? y.Description), cancellationToken: cancellationToken); return affectedRow; } } diff --git a/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs b/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs similarity index 85% rename from src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs rename to src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs index 8c62e9e..22f9da0 100644 --- a/src/Application/Building/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs +++ b/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs @@ -1,7 +1,7 @@ using FluentValidation; using SWD_Laundry_Backend.Application.Common.Interfaces; -namespace SWD_Laundry_Backend.Application.Building.Commands.UpdateBuilding; +namespace SWD_Laundry_Backend.Application.Buildings.Commands.UpdateBuilding; public class UpdateBuildingCommandValidator : AbstractValidator { private readonly IApplicationDbContext _context; diff --git a/src/Application/Building/Queries/BuildingViewModel.cs b/src/Application/Buildings/Queries/BuildingViewModel.cs similarity index 54% rename from src/Application/Building/Queries/BuildingViewModel.cs rename to src/Application/Buildings/Queries/BuildingViewModel.cs index 72e94b5..590af13 100644 --- a/src/Application/Building/Queries/BuildingViewModel.cs +++ b/src/Application/Buildings/Queries/BuildingViewModel.cs @@ -1,7 +1,8 @@ using SWD_Laundry_Backend.Application.Common.Mappings; +using SWD_Laundry_Backend.Domain.Entities; -namespace SWD_Laundry_Backend.Application.Building.Queries; -public class BuildingViewModel : IMapFrom +namespace SWD_Laundry_Backend.Application.Buildings.Queries; +public class BuildingViewModel : IMapFrom { public string Name { get; set; } public string Address { get; set; } diff --git a/src/Application/Building/Queries/GetAllBuildingQuery.cs b/src/Application/Buildings/Queries/GetAllBuildingQuery.cs similarity index 78% rename from src/Application/Building/Queries/GetAllBuildingQuery.cs rename to src/Application/Buildings/Queries/GetAllBuildingQuery.cs index ae2403e..72f6241 100644 --- a/src/Application/Building/Queries/GetAllBuildingQuery.cs +++ b/src/Application/Buildings/Queries/GetAllBuildingQuery.cs @@ -2,8 +2,9 @@ using MediatR; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; -namespace SWD_Laundry_Backend.Application.Building.Queries; +namespace SWD_Laundry_Backend.Application.Buildings.Queries; public class GetAllBuildingQuery : IRequest> { @@ -22,7 +23,7 @@ public GetAllBuildingQueryHandler(IApplicationDbContext context, IMapper mapper) public async Task> Handle(GetAllBuildingQuery request, CancellationToken cancellationToken) { - var buildingList = await _context.Get().AsNoTracking().ToListAsync(cancellationToken); + var buildingList = await _context.Get().AsNoTracking().ToListAsync(cancellationToken); return _mapper.Map>(buildingList); } diff --git a/src/Application/Building/Queries/GetBuildingQuery.cs b/src/Application/Buildings/Queries/GetBuildingQuery.cs similarity index 75% rename from src/Application/Building/Queries/GetBuildingQuery.cs rename to src/Application/Buildings/Queries/GetBuildingQuery.cs index f654f05..d188b04 100644 --- a/src/Application/Building/Queries/GetBuildingQuery.cs +++ b/src/Application/Buildings/Queries/GetBuildingQuery.cs @@ -2,8 +2,9 @@ using MediatR; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; -namespace SWD_Laundry_Backend.Application.Building.Queries; +namespace SWD_Laundry_Backend.Application.Buildings.Queries; public class GetBuildingQuery : IRequest { public int Id { init; get; } @@ -21,7 +22,7 @@ public GetBuildingQueryHandler(IApplicationDbContext context, IMapper mapper) public async Task Handle(GetBuildingQuery request, CancellationToken cancellationToken) { - var building = await _context.Get().AsNoTracking().FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); + var building = await _context.Get().AsNoTracking().FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); return _mapper.Map(building); } } \ No newline at end of file diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs new file mode 100644 index 0000000..810fc6e --- /dev/null +++ b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs @@ -0,0 +1,36 @@ +using MediatR; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; +using SWD_Laundry_Backend.Domain.Enums; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; +public class CreatePaymentMethodCommand : IRequest +{ + public PaymentType PaymentType { get; set; } + public string Description { get; set; } +} + +public class CreatePaymentMethodCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public CreatePaymentMethodCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(CreatePaymentMethodCommand request, CancellationToken cancellationToken) + { + var entity = new PaymentMethod + { + PaymentType = request.PaymentType, + Description = request.Description + }; + + _context.Get().Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} diff --git a/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs b/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs new file mode 100644 index 0000000..d02b231 --- /dev/null +++ b/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs @@ -0,0 +1,38 @@ +using AutoMapper; +using AutoMapper.QueryableExtensions; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; +using SWD_Laundry_Backend.Domain.Enums; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +public class GetAllPaymentMethods +{ + public class GetAllPaymentMethodsQuery : IRequest + { + } + + public class GetAllPaymentMethodsQueryHandler : IRequestHandler + { + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public GetAllPaymentMethodsQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(GetAllPaymentMethodsQuery request, CancellationToken cancellationToken) + { + var paymentMethods = await _context.Get().ProjectTo(_mapper.ConfigurationProvider).ToListAsync(cancellationToken); + var result = new PaymentMethodVm + { + PaymentTypes = Enum.GetValues(typeof(PaymentType)).Cast().Select(p => new PaymentTypeDto { Value = (int)p, Name = p.ToString() }).ToList(), + PaymentMethods = _mapper.Map>(paymentMethods) + }; + return result; + } + } +} diff --git a/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs b/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs new file mode 100644 index 0000000..5a207d0 --- /dev/null +++ b/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs @@ -0,0 +1,38 @@ +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; +using SWD_Laundry_Backend.Domain.Enums; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +public class GetPaymentMethod : IRequest +{ + public int Id { get; init; } +} + +public class GetPaymentMethodHandler : IRequestHandler +{ + + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + public GetPaymentMethodHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(GetPaymentMethod request, CancellationToken cancellationToken) + { + var paymentMethod = await _context.Get().Where(x => x.Id == request.Id).AsNoTracking().FirstOrDefaultAsync(cancellationToken); + + var result = new PaymentMethodVm() + { + PaymentTypes = Enum.GetValues(typeof(PaymentType)).Cast().Select(p => new PaymentTypeDto { Value = (int)p, Name = p.ToString() }).OrderBy(x => x.Value).ToList(), + PaymentMethods = _mapper.Map(paymentMethod) + }; + + return result; + } + +} \ No newline at end of file diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs new file mode 100644 index 0000000..cdf1455 --- /dev/null +++ b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs @@ -0,0 +1,10 @@ +using SWD_Laundry_Backend.Application.Common.Mappings; +using SWD_Laundry_Backend.Domain.Entities; +using SWD_Laundry_Backend.Domain.Enums; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +public class PaymentMethodDto : IMapFrom +{ + public PaymentType PaymentType { get; set; } + public string? Description { get; set; } +} diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs b/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs new file mode 100644 index 0000000..64cbcdd --- /dev/null +++ b/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +public class PaymentMethodVm +{ + public required IReadOnlyCollection PaymentTypes { get; init; } = Array.Empty(); + public required dynamic PaymentMethods { get; init; } +} diff --git a/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs b/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs new file mode 100644 index 0000000..3d445e4 --- /dev/null +++ b/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +public class PaymentTypeDto +{ + public int Value { get; init; } + public string? Name { get; init; } +} diff --git a/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs b/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs new file mode 100644 index 0000000..33bff09 --- /dev/null +++ b/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs @@ -0,0 +1,32 @@ +using MediatR; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.Wallets.Commands.CreateWallet; +public class CreateWalletCommand : IRequest +{ + public double Balance { get; init; } +} + +public class CreateWalletCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public CreateWalletCommandHandler(IApplicationDbContext context) + { + _context = context; + } + public async Task Handle(CreateWalletCommand request, CancellationToken cancellationToken) + { + var entity = new Wallet + { + Balance = request.Balance + }; + + _context.Get().Add(entity); + + await _context.SaveChangesAsync(cancellationToken); + + return entity.Id; + } +} \ No newline at end of file diff --git a/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs b/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs new file mode 100644 index 0000000..526ea01 --- /dev/null +++ b/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs @@ -0,0 +1,15 @@ +using FluentValidation; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Wallets.Commands.CreateWallet; +public class CreateWalletCommandValidator : AbstractValidator +{ + private readonly IApplicationDbContext _context; + + public CreateWalletCommandValidator(IApplicationDbContext context) + { + _context = context; + + RuleFor(v => v.Balance).GreaterThan(0); + } +} diff --git a/src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs b/src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs new file mode 100644 index 0000000..018219b --- /dev/null +++ b/src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs @@ -0,0 +1,25 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.Wallets.Commands.DeleteWallet; +public class DeleteWalletCommand : IRequest +{ + public int Id { get; init; } +} + +public class DeleteWalletCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + public DeleteWalletCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(DeleteWalletCommand request, CancellationToken cancellationToken) + { + var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken); + return affectedRow; + } +} diff --git a/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs b/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs new file mode 100644 index 0000000..5bf1d36 --- /dev/null +++ b/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs @@ -0,0 +1,27 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.Wallets.Commands.UpdateWallet; +public class UpdateWalletCommand : IRequest +{ + public int Id { get; set; } + public double Balance { get; set; } +} + +public class UpdateWalletCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + public UpdateWalletCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(UpdateWalletCommand request, CancellationToken cancellationToken) + { + int affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => + x.SetProperty(y => y.Balance, request.Balance), cancellationToken: cancellationToken); + return affectedRow; + } +} \ No newline at end of file diff --git a/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs b/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs new file mode 100644 index 0000000..b13a861 --- /dev/null +++ b/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs @@ -0,0 +1,10 @@ +using FluentValidation; + +namespace SWD_Laundry_Backend.Application.Wallets.Commands.UpdateWallet; +public class UpdateWalletCommandValidator : AbstractValidator +{ + public UpdateWalletCommandValidator() + { + RuleFor(v => v.Balance).GreaterThan(0); + } +} diff --git a/src/Application/Wallets/Queries/GetAllWalletQuery.cs b/src/Application/Wallets/Queries/GetAllWalletQuery.cs new file mode 100644 index 0000000..ca0406f --- /dev/null +++ b/src/Application/Wallets/Queries/GetAllWalletQuery.cs @@ -0,0 +1,30 @@ +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.Wallets.Queries; +public class GetAllWalletQuery : IRequest> +{ + +} + +public class GetAllWalletQueryHandler : IRequestHandler> +{ + + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + public GetAllWalletQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task> Handle(GetAllWalletQuery request, CancellationToken cancellationToken) + { + var walletList = await _context.Get().AsNoTracking().ToListAsync(cancellationToken); + return _mapper.Map>(walletList); + } + +} diff --git a/src/Application/Wallets/Queries/GetWalletQuery.cs b/src/Application/Wallets/Queries/GetWalletQuery.cs new file mode 100644 index 0000000..a2c0168 --- /dev/null +++ b/src/Application/Wallets/Queries/GetWalletQuery.cs @@ -0,0 +1,29 @@ +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.Wallets.Queries; +public class GetWalletQuery : IRequest +{ + public int Id { get; set; } +} + +public class GetWalletQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public GetWalletQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(GetWalletQuery request, CancellationToken cancellationToken) + { + var entity = await _context.Get().FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); + return _mapper.Map(entity); + } +} diff --git a/src/Application/Wallets/Queries/WalletViewModel.cs b/src/Application/Wallets/Queries/WalletViewModel.cs new file mode 100644 index 0000000..67d4f7f --- /dev/null +++ b/src/Application/Wallets/Queries/WalletViewModel.cs @@ -0,0 +1,8 @@ +using SWD_Laundry_Backend.Application.Common.Mappings; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.Wallets.Queries; +public class WalletViewModel : IMapFrom +{ + public double Balance { get; set; } +} diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index e3259e1..081c223 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -1,6 +1,4 @@ -using SWD_Laundry_Backend.Domain.Entities.Validation; - -namespace SWD_Laundry_Backend.Domain.Entities; +namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable public class PaymentMethod : BaseAuditableEntity diff --git a/src/WebUI/Controllers/BuildingController.cs b/src/WebUI/Controllers/BuildingController.cs index 3b78109..1fa3117 100644 --- a/src/WebUI/Controllers/BuildingController.cs +++ b/src/WebUI/Controllers/BuildingController.cs @@ -1,10 +1,9 @@ using Microsoft.AspNetCore.Mvc; -using SWD_Laundry_Backend.Application.Building.Commands.CreateBuilding; -using SWD_Laundry_Backend.Application.Building.Commands.DeleteBuilding; -using SWD_Laundry_Backend.Application.Building.Commands.UpdateBuilding; -using SWD_Laundry_Backend.Application.Building.Queries; +using SWD_Laundry_Backend.Application.Buildings.Commands.CreateBuilding; +using SWD_Laundry_Backend.Application.Buildings.Commands.DeleteBuilding; +using SWD_Laundry_Backend.Application.Buildings.Commands.UpdateBuilding; +using SWD_Laundry_Backend.Application.Buildings.Queries; using SWD_Laundry_Backend.WebUI.Controllers; -using Microsoft.AspNetCore.Http; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 diff --git a/src/WebUI/Controllers/WalletController.cs b/src/WebUI/Controllers/WalletController.cs new file mode 100644 index 0000000..8ca569d --- /dev/null +++ b/src/WebUI/Controllers/WalletController.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Application.Wallets.Commands.CreateWallet; +using SWD_Laundry_Backend.Application.Wallets.Commands.DeleteWallet; +using SWD_Laundry_Backend.Application.Wallets.Commands.UpdateWallet; +using SWD_Laundry_Backend.Application.Wallets.Queries; +using SWD_Laundry_Backend.WebUI.Controllers; + +namespace WebUI.Controllers; + +public class WalletController : ApiControllerBase +{ + // GET: api/ + [HttpGet] + public async Task>> Get() + { + return await Mediator.Send(new GetAllWalletQuery()); + } + + // GET api//5 + [HttpGet("{id}")] + public async Task> Get(int id) + { + return await Mediator.Send(new GetWalletQuery { Id = id }); + } + + // POST api/ + [HttpPost] + public async Task> Post([FromBody] CreateWalletCommand command) + { + return await Mediator.Send(command); + } + + // PUT api//5 + [HttpPut] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesDefaultResponseType] + public async Task> Put([FromBody] UpdateWalletCommand command) + { + return await Mediator.Send(command); + } + + // DELETE api//5 + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesDefaultResponseType] + public async Task> Delete(int id) + { + return await Mediator.Send(new DeleteWalletCommand { Id = id }); + } +} diff --git a/src/WebUI/wwwroot/api/specification.json b/src/WebUI/wwwroot/api/specification.json index 85b94f0..8bb1168 100644 --- a/src/WebUI/wwwroot/api/specification.json +++ b/src/WebUI/wwwroot/api/specification.json @@ -190,6 +190,190 @@ } } }, + "/api/Wallet": { + "get": { + "tags": [ + "Wallet" + ], + "operationId": "Wallet_GetAll", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WalletViewModel" + } + } + } + } + } + } + }, + "post": { + "tags": [ + "Wallet" + ], + "operationId": "Wallet_Post", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWalletCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "put": { + "tags": [ + "Wallet" + ], + "operationId": "Wallet_Put", + "requestBody": { + "x-name": "command", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateWalletCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "204": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + } + } + }, + "/api/Wallet/{id}": { + "get": { + "tags": [ + "Wallet" + ], + "operationId": "Wallet_Get", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WalletViewModel" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Wallet" + ], + "operationId": "Wallet_Delete", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "x-position": 1 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + } + }, + "204": { + "description": "" + }, + "default": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + } + } + }, "/api/TodoItems": { "get": { "tags": [ @@ -680,6 +864,44 @@ } } }, + "WalletViewModel": { + "type": "object", + "additionalProperties": false, + "properties": { + "balance": { + "type": "number", + "format": "double" + } + } + }, + "CreateWalletCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "balance": { + "type": "number", + "format": "double", + "minimum": 0.0, + "exclusiveMinimum": true + } + } + }, + "UpdateWalletCommand": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "balance": { + "type": "number", + "format": "double", + "minimum": 0.0, + "exclusiveMinimum": true + } + } + }, "PaginatedListOfTodoItemBriefDto": { "type": "object", "additionalProperties": false, From aeeb3506cb392bbc47bfd65c6a2732a1b35ecd44 Mon Sep 17 00:00:00 2001 From: Nero Date: Tue, 19 Sep 2023 18:21:52 +0700 Subject: [PATCH 09/53] Update Payment --- .../CreatePaymentMethodCommand.cs | 4 ++-- .../Queries/GetAllPaymentMethods.cs | 12 ++++-------- .../PaymentMethods/Queries/GetPaymentMethod.cs | 12 ++++-------- .../PaymentMethods/Queries/PaymentMethodDto.cs | 2 +- .../PaymentMethods/Queries/PaymentMethodVm.cs | 12 ++++++------ .../PaymentMethods/Queries/PaymentTypeDto.cs | 12 ++++++------ src/Domain/Entities/PaymentMethod.cs | 2 +- src/Domain/Entities/Staff.cs | 1 - src/Domain/Enums/PaymentType.cs | 16 ++++++++-------- 9 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs index 810fc6e..b67439e 100644 --- a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs +++ b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs @@ -6,7 +6,7 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; public class CreatePaymentMethodCommand : IRequest { - public PaymentType PaymentType { get; set; } + public string Name { get; set; } public string Description { get; set; } } @@ -23,7 +23,7 @@ public async Task Handle(CreatePaymentMethodCommand request, CancellationTo { var entity = new PaymentMethod { - PaymentType = request.PaymentType, + Name = request.Name, Description = request.Description }; diff --git a/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs b/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs index d02b231..5a28e9d 100644 --- a/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs +++ b/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs @@ -9,11 +9,11 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; public class GetAllPaymentMethods { - public class GetAllPaymentMethodsQuery : IRequest + public class GetAllPaymentMethodsQuery : IRequest { } - public class GetAllPaymentMethodsQueryHandler : IRequestHandler + public class GetAllPaymentMethodsQueryHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly IMapper _mapper; @@ -24,14 +24,10 @@ public GetAllPaymentMethodsQueryHandler(IApplicationDbContext context, IMapper m _mapper = mapper; } - public async Task Handle(GetAllPaymentMethodsQuery request, CancellationToken cancellationToken) + public async Task Handle(GetAllPaymentMethodsQuery request, CancellationToken cancellationToken) { var paymentMethods = await _context.Get().ProjectTo(_mapper.ConfigurationProvider).ToListAsync(cancellationToken); - var result = new PaymentMethodVm - { - PaymentTypes = Enum.GetValues(typeof(PaymentType)).Cast().Select(p => new PaymentTypeDto { Value = (int)p, Name = p.ToString() }).ToList(), - PaymentMethods = _mapper.Map>(paymentMethods) - }; + var result = _mapper.Map(paymentMethods); return result; } } diff --git a/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs b/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs index 5a207d0..5f7dd05 100644 --- a/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs +++ b/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs @@ -6,12 +6,12 @@ using SWD_Laundry_Backend.Domain.Enums; namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -public class GetPaymentMethod : IRequest +public class GetPaymentMethod : IRequest { public int Id { get; init; } } -public class GetPaymentMethodHandler : IRequestHandler +public class GetPaymentMethodHandler : IRequestHandler { private readonly IApplicationDbContext _context; @@ -22,15 +22,11 @@ public GetPaymentMethodHandler(IApplicationDbContext context, IMapper mapper) _mapper = mapper; } - public async Task Handle(GetPaymentMethod request, CancellationToken cancellationToken) + public async Task Handle(GetPaymentMethod request, CancellationToken cancellationToken) { var paymentMethod = await _context.Get().Where(x => x.Id == request.Id).AsNoTracking().FirstOrDefaultAsync(cancellationToken); - var result = new PaymentMethodVm() - { - PaymentTypes = Enum.GetValues(typeof(PaymentType)).Cast().Select(p => new PaymentTypeDto { Value = (int)p, Name = p.ToString() }).OrderBy(x => x.Value).ToList(), - PaymentMethods = _mapper.Map(paymentMethod) - }; + var result = _mapper.Map(paymentMethod); return result; } diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs index cdf1455..b282b1d 100644 --- a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs +++ b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs @@ -5,6 +5,6 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; public class PaymentMethodDto : IMapFrom { - public PaymentType PaymentType { get; set; } + public string Name { get; init; } public string? Description { get; set; } } diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs b/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs index 64cbcdd..b2c903d 100644 --- a/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs +++ b/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs @@ -1,6 +1,6 @@ -namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -public class PaymentMethodVm -{ - public required IReadOnlyCollection PaymentTypes { get; init; } = Array.Empty(); - public required dynamic PaymentMethods { get; init; } -} +//namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +//public class PaymentMethodVm +//{ +// public required IReadOnlyCollection PaymentTypes { get; init; } = Array.Empty(); +// public required dynamic PaymentMethods { get; init; } +//} diff --git a/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs b/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs index 3d445e4..c7f23d3 100644 --- a/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs +++ b/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs @@ -1,6 +1,6 @@ -namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -public class PaymentTypeDto -{ - public int Value { get; init; } - public string? Name { get; init; } -} +//namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; +//public class PaymentTypeDto +//{ +// public int Value { get; init; } +// public string? Name { get; init; } +//} diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 081c223..2f119fe 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -20,5 +20,5 @@ public class PaymentMethod : BaseAuditableEntity // : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); // } //} - public PaymentType PaymentType { get; set; } + public string Name { get; set; } } \ No newline at end of file diff --git a/src/Domain/Entities/Staff.cs b/src/Domain/Entities/Staff.cs index e96c0ec..5b6fce9 100644 --- a/src/Domain/Entities/Staff.cs +++ b/src/Domain/Entities/Staff.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.Entities.Validation; using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Domain.Entities; diff --git a/src/Domain/Enums/PaymentType.cs b/src/Domain/Enums/PaymentType.cs index 1c5fe8c..5779958 100644 --- a/src/Domain/Enums/PaymentType.cs +++ b/src/Domain/Enums/PaymentType.cs @@ -1,8 +1,8 @@ -namespace SWD_Laundry_Backend.Domain.Enums; -public enum PaymentType -{ - Cash = 1, - CreditCard = 2, - DebitCard = 3, - EWallet = 4 -} +//namespace SWD_Laundry_Backend.Domain.Enums; +//public enum PaymentType +//{ +// Cash = 1, +// CreditCard = 2, +// DebitCard = 3, +// EWallet = 4 +//} From fced052bca64fe369fd1077d04f298be0557fcaf Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Wed, 20 Sep 2023 02:28:52 +0700 Subject: [PATCH 10/53] Update Entity 2 --- .../Interfaces/IApplicationDbContext.cs | 17 +- .../GetTodoItemsWithPaginationQuery.cs | 7 +- src/Domain/Entities/Building.cs | 5 + src/Domain/Entities/Customer.cs | 1 + src/Domain/Entities/LaundryStore.cs | 39 +- src/Domain/Entities/Order.cs | 49 ++- src/Domain/Entities/PaymentMethod.cs | 23 +- src/Domain/Entities/Service.cs | 21 ++ src/Domain/Entities/Staff.cs | 46 +-- src/Domain/Entities/Staff_Trip.cs | 28 +- src/Domain/Entities/TimeSchedule.cs | 15 + src/Domain/Entities/Transaction.cs | 8 +- src/Domain/Entities/Wallet.cs | 8 + src/Domain/Enums/TimeFrame.cs | 13 + src/Infrastructure/Infrastructure.csproj | 4 + ...0230919183842_UpdateDatabase3.Designer.cs} | 261 +++++++++++--- ...n.cs => 20230919183842_UpdateDatabase3.cs} | 337 ++++++++++++------ .../ApplicationDbContextModelSnapshot.cs | 257 ++++++++++--- src/WebUI/WebUI.csproj | 4 +- src/WebUI/appsettings.json | 2 +- 20 files changed, 789 insertions(+), 356 deletions(-) create mode 100644 src/Domain/Entities/Service.cs create mode 100644 src/Domain/Entities/TimeSchedule.cs create mode 100644 src/Domain/Enums/TimeFrame.cs rename src/Infrastructure/Migrations/{20230918144740_InitMigration.Designer.cs => 20230919183842_UpdateDatabase3.Designer.cs} (83%) rename src/Infrastructure/Migrations/{20230918144740_InitMigration.cs => 20230919183842_UpdateDatabase3.cs} (85%) diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 54e69f7..be24d29 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -1,6 +1,7 @@ using SWD_Laundry_Backend.Domain.Entities; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Domain.Common; +using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Application.Common.Interfaces; @@ -9,7 +10,19 @@ public interface IApplicationDbContext DbSet TodoLists { get; } DbSet TodoItems { get; } + DbSet Customers { get; } + DbSet Buildings { get; } + DbSet ApplicationUsers { get; } + DbSet LaundryStores { get; } + DbSet Orders { get; } + DbSet OrdersHistory { get; } + DbSet PaymentMethods { get; } + DbSet Staff_Trips { get; } + DbSet Staffs { get; } + DbSet Transactions { get; } + DbSet Wallets { get; } + DbSet Get() where T : BaseAuditableEntity; - Task SaveChangesAsync(CancellationToken cancellationToken); -} + Task SaveChangesAsync(CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs index f6f9833..e22c477 100644 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs @@ -18,13 +18,18 @@ public class GetTodoItemsWithPaginationQueryHandler : IRequestHandler c.LaundryStore.Id == 1).ToList(); + } + public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) { return await _context.TodoItems diff --git a/src/Domain/Entities/Building.cs b/src/Domain/Entities/Building.cs index 0df9893..b775634 100644 --- a/src/Domain/Entities/Building.cs +++ b/src/Domain/Entities/Building.cs @@ -6,4 +6,9 @@ public class Building : BaseAuditableEntity public string Name { get; set; } public string Address { get; set; } public string Description { get; set; } + + #region Relationship + public List Customers { get; set; } + public List Staff_Trips { get; set; } + #endregion } \ No newline at end of file diff --git a/src/Domain/Entities/Customer.cs b/src/Domain/Entities/Customer.cs index 10e5166..220ba40 100644 --- a/src/Domain/Entities/Customer.cs +++ b/src/Domain/Entities/Customer.cs @@ -25,6 +25,7 @@ public class Customer : BaseAuditableEntity public Building Building { get; set; } public Wallet Wallet { get; set; } public ApplicationUser ApplicationUser { get; set; } + //public virtual List Order { get; set; } #endregion Relationship diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs index d89bf16..fe8f488 100644 --- a/src/Domain/Entities/LaundryStore.cs +++ b/src/Domain/Entities/LaundryStore.cs @@ -1,4 +1,5 @@ -using SWD_Laundry_Backend.Domain.Entities.Validation; +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Domain.Entities.Validation; using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Domain.Entities; @@ -8,48 +9,24 @@ public class LaundryStore : BaseAuditableEntity { public string Name { get; set; } public string Address { get; set; } + public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } public bool Status { get; set; } #region Relationship + [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } + [ForeignKey("Wallet")] public int WalletID { get; set; } public ApplicationUser ApplicationUser { get; set; } public Wallet Wallet { get; set; } - #endregion Relationship - #region Special Attribute - - //private string _email; - - //private string _phone; - - //public string Email - //{ - // get { return _email; } - // set - // { - // _email = new Validate().IsValidEmail(value) - // ? value - // : throw new ArgumentException("Invalid email."); - // } - //} - - //public string Phone - //{ - // get { return _phone; } - // set - // { - // _phone = new Validate().IsValidPhone(value) - // ? value - // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - // } - //} - - #endregion Special Attribute + public virtual List Orders { get; set; } + + #endregion Relationship } \ No newline at end of file diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs index ace9e7c..b228f8a 100644 --- a/src/Domain/Entities/Order.cs +++ b/src/Domain/Entities/Order.cs @@ -1,27 +1,19 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SWD_Laundry_Backend.Domain.Entities.Validation; +using System.ComponentModel.DataAnnotations.Schema; using SWD_Laundry_Backend.Domain.IdentityModel; - namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable public class Order : BaseAuditableEntity { + public DateTime OrderDate { get; set; } = DateTime.Now; public DateTime ShipDate { get; set; } - - public DateTime OrderDate { get; set; } public DateTime ExpectedFinishDate { get; set; } public string Address { get; set; } // Address = Customer's building location public short Amount { get; set; } - public bool IsWhiteClothes { get; set; } + public double TotalPrice { get; set; } #region Relationship @@ -29,29 +21,32 @@ public class Order : BaseAuditableEntity [ForeignKey("PaymentMethod")] public int PaymentMethodID { get; set; } - [ForeignKey("ApplicationUser")] - public string ApplicationUserID { get; set; } + [ForeignKey("Customer")] + public int CustomerID { get; set; } + + //[ForeignKey("LaundryStore")] + //public int LaundryStoreID { get; set; } + + ////[ForeignKey("Staff")] + ////public int StaffID { get; set; } + + //[ForeignKey("Service")] + //public int ServiceID { get; set; } + + ////=========================== + public Service Service { get; set; } + + public virtual LaundryStore LaundryStore { get; set; } + public virtual Customer Customer { get; set; } + public virtual Staff Staff { get; set; } - public ApplicationUser ApplicationUser { get; set; } public PaymentMethod PaymentMethod { get; set; } + public List OrderHistories { get; set; } #endregion Relationship #region Special Attribute - //private string _orderType; - - //public string OrderType - //{ - // get => _orderType; - // set - // { - // _orderType = new Validate().IsValidOrderType(value) - // ? value - // : throw new Exception("Invalid order type {ONEWAY, TWOWAY}"); - // } - //} - public OrderType OrderType { get; set; } #endregion Special Attribute diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 081c223..eb8c6c7 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -5,20 +5,15 @@ public class PaymentMethod : BaseAuditableEntity { public string Description { get; set; } - /// - /// Special attributes - /// - //private string _type; + #region Relationship + + public List Orders { get; set; } + + #endregion Relationship + + #region Special Attributes - //public string PaymentType - //{ - // get { return _type; } - // set - // { - // _type = new Validate().IsValidPayment(value) - // ? value - // : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); - // } - //} public PaymentType PaymentType { get; set; } + + #endregion Special Attributes } \ No newline at end of file diff --git a/src/Domain/Entities/Service.cs b/src/Domain/Entities/Service.cs new file mode 100644 index 0000000..21146d4 --- /dev/null +++ b/src/Domain/Entities/Service.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Domain.Entities; +#nullable disable + +public class Service : BaseAuditableEntity +{ + public string Name { get; set; } + public string Description { get; set; } + public double Price { get; set; } + + #region Relationship + + public List Order { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/Domain/Entities/Staff.cs b/src/Domain/Entities/Staff.cs index e96c0ec..3168fe2 100644 --- a/src/Domain/Entities/Staff.cs +++ b/src/Domain/Entities/Staff.cs @@ -7,13 +7,12 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Staff : BaseAuditableEntity { - public DateTime Dob { get; set; } - public string Address { get; set; } + //public DateTime Dob { get; set; } + //public string Address { get; set; } public double Salary { get; set; } #region Relationship - [ForeignKey("Wallet")] public int WalletID { get; set; } @@ -23,49 +22,14 @@ public class Staff : BaseAuditableEntity public ApplicationUser ApplicationUser { get; set; } public Wallet Wallet { get; set; } + public List Order { get; set; } + public List Staff_Trips { get; set; } + #endregion Relationship #region Special Attribute public StaffRole StaffRole { get; set; } - //private string _email; - - //private string _phone; - //private string _role; - - //public string Role - //{ - // get { return _role; } - // set - // { - // _role = new Validate().IsValidStaffRole(value) - // ? value - // : throw new ArgumentException("Invalid staff role {COLLECTOR, RECEIVER}."); - // } - //} - - //public string Email - //{ - // get { return _email; } - // set - // { - // _email = new Validate().IsValidEmail(value) - // ? value - // : throw new ArgumentException("Invalid email."); - // } - //} - - //public string Phone - //{ - // get { return _phone; } - // set - // { - // _phone = new Validate().IsValidPhone(value) - // ? value - // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - // } - //} - #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Staff_Trip.cs b/src/Domain/Entities/Staff_Trip.cs index 0b06afa..5fc617d 100644 --- a/src/Domain/Entities/Staff_Trip.cs +++ b/src/Domain/Entities/Staff_Trip.cs @@ -8,39 +8,27 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Staff_Trip : BaseAuditableEntity { - public string Address { get; set; } - public DateTime StartTime { get; set; } - - public DateTime EndTime { get; set; } - public int TripCollect { get; set; } = 0; - - #region Relationship [ForeignKey("Staff")] public int StaffID { get; set; } + [ForeignKey("TimeSchedule")] + public int TimeScheduleID { get; set; } + + [ForeignKey("Building")] + public int BuildingID { get; set; } + + public Building Building { get; set; } public Staff Staff { get; set; } + public TimeSchedule TimeSchedule { get; set; } #endregion Relationship #region Special Attribute - //private string _tripstatus; - - //public string TripStatus - //{ - // get { return _tripstatus; } - // set - // { - // _tripstatus = new Validate().IsValidTripStatus(value) - // ? value - // : throw new ArgumentException("Invalid trip status {FINISHED, PROCESSING, CANCELLED}."); - // } - //} - public Status TripStatus { get; set; } #endregion Special Attribute diff --git a/src/Domain/Entities/TimeSchedule.cs b/src/Domain/Entities/TimeSchedule.cs new file mode 100644 index 0000000..b2e777c --- /dev/null +++ b/src/Domain/Entities/TimeSchedule.cs @@ -0,0 +1,15 @@ +namespace SWD_Laundry_Backend.Domain.Entities; + +public class TimeSchedule : BaseAuditableEntity +{ + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + + #region Special Attribute + + public DayOfWeek DayOfWeek { get; set; } + public TimeFrame TimeFrame { get; set; } + public Staff_Trip Staff_Trip { get; set; } + + #endregion Special Attribute +} \ No newline at end of file diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs index e8ec326..004a1ac 100644 --- a/src/Domain/Entities/Transaction.cs +++ b/src/Domain/Entities/Transaction.cs @@ -1,6 +1,4 @@ -using SWD_Laundry_Backend.Domain.Entities.Validation; - -namespace SWD_Laundry_Backend.Domain.Entities; +namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable public class Transaction : BaseAuditableEntity @@ -13,7 +11,7 @@ public class Transaction : BaseAuditableEntity public int WalletID { get; set; } - public List Wallet { get; set; } + public Wallet Wallet { get; set; } #endregion Relationship @@ -34,7 +32,7 @@ public class Transaction : BaseAuditableEntity public AllowedTransactionType TransactionType { get; set; } - public Status Status { get; set;} + public Status Status { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Wallet.cs b/src/Domain/Entities/Wallet.cs index c93653c..ee9361f 100644 --- a/src/Domain/Entities/Wallet.cs +++ b/src/Domain/Entities/Wallet.cs @@ -5,4 +5,12 @@ public class Wallet : BaseAuditableEntity { public double Balance { get; set; } + #region Relationship + + public List Transactions { get; set; } + public Customer Customer { get; set; } + public LaundryStore LaundryStore { get; set; } + public Staff Staff { get; set; } + + #endregion Relationship } \ No newline at end of file diff --git a/src/Domain/Enums/TimeFrame.cs b/src/Domain/Enums/TimeFrame.cs new file mode 100644 index 0000000..18a252e --- /dev/null +++ b/src/Domain/Enums/TimeFrame.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Domain.Enums; +public enum TimeFrame +{ + Morning = 0, // 7h - 12h + Afternoon= 1, // 13h - 18h + Night = 2, // 19h - 24h +} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index e6dfee7..df1a672 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/src/Infrastructure/Migrations/20230918144740_InitMigration.Designer.cs b/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs similarity index 83% rename from src/Infrastructure/Migrations/20230918144740_InitMigration.Designer.cs rename to src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs index c98c812..ca49bad 100644 --- a/src/Infrastructure/Migrations/20230918144740_InitMigration.Designer.cs +++ b/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs @@ -12,8 +12,8 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230918144740_InitMigration")] - partial class InitMigration + [Migration("20230919183842_UpdateDatabase3")] + partial class UpdateDatabase3 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -372,7 +372,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("BuildingID"); - b.HasIndex("WalletID"); + b.HasIndex("WalletID") + .IsUnique(); b.ToTable("Customers"); }); @@ -422,7 +423,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.HasIndex("WalletID"); + b.HasIndex("WalletID") + .IsUnique(); b.ToTable("LaundryStores"); }); @@ -441,27 +443,27 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Amount") .HasColumnType("smallint"); - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); + b.Property("CustomerID") + .HasColumnType("int"); + b.Property("ExpectedFinishDate") .HasColumnType("datetime2"); - b.Property("IsWhiteClothes") - .HasColumnType("bit"); - b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("LaundryStoreId") + .HasColumnType("int"); + b.Property("OrderDate") .HasColumnType("datetime2"); @@ -471,18 +473,30 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); + b.Property("ServiceId") + .HasColumnType("int"); + b.Property("ShipDate") .HasColumnType("datetime2"); + b.Property("StaffId") + .HasColumnType("int"); + b.Property("TotalPrice") .HasColumnType("float"); b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreId"); b.HasIndex("PaymentMethodID"); + b.HasIndex("ServiceId"); + + b.HasIndex("StaffId"); + b.ToTable("Orders"); }); @@ -550,7 +564,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("PaymentMethods"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -558,9 +572,40 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Service"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); @@ -570,9 +615,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Dob") - .HasColumnType("datetime2"); - b.Property("LastModified") .HasColumnType("datetime2"); @@ -592,7 +634,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.HasIndex("WalletID"); + b.HasIndex("WalletID") + .IsUnique(); b.ToTable("Staffs"); }); @@ -605,8 +648,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") - .HasColumnType("nvarchar(max)"); + b.Property("BuildingID") + .HasColumnType("int"); b.Property("Created") .HasColumnType("datetime2"); @@ -614,9 +657,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("EndTime") - .HasColumnType("datetime2"); - b.Property("LastModified") .HasColumnType("datetime2"); @@ -626,8 +666,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("StaffID") .HasColumnType("int"); - b.Property("StartTime") - .HasColumnType("datetime2"); + b.Property("TimeScheduleID") + .HasColumnType("int"); b.Property("TripCollect") .HasColumnType("int"); @@ -637,11 +677,53 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Id"); + b.HasIndex("BuildingID"); + b.HasIndex("StaffID"); + b.HasIndex("TimeScheduleID") + .IsUnique(); + b.ToTable("Staff_Trips"); }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedule"); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => { b.Property("Id") @@ -759,6 +841,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Id"); + b.HasIndex("WalletID"); + b.ToTable("Transactions"); }); @@ -785,13 +869,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("TransactionId") - .HasColumnType("int"); - b.HasKey("Id"); - b.HasIndex("TransactionId"); - b.ToTable("Wallets"); }); @@ -921,14 +1000,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() + .WithMany("Customers") .HasForeignKey("BuildingID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") + .WithOne("Customer") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Customer", "WalletID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -946,8 +1025,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") + .WithOne("LaundryStore") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "WalletID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -958,25 +1037,45 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") .WithMany() - .HasForeignKey("ApplicationUserID"); + .HasForeignKey("CustomerID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") + .WithMany("Orders") + .HasForeignKey("LaundryStoreId"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") - .WithMany() + .WithMany("Orders") .HasForeignKey("PaymentMethodID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("ApplicationUser"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", "Service") + .WithMany("Order") + .HasForeignKey("ServiceId"); + + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") + .WithMany("Order") + .HasForeignKey("StaffId"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); b.Navigation("PaymentMethod"); + + b.Navigation("Service"); + + b.Navigation("Staff"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => { b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany() + .WithMany("OrderHistories") .HasForeignKey("OrderID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -991,8 +1090,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") + .WithOne("Staff") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff", "WalletID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -1003,13 +1102,29 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") + .WithMany("Staff_Trips") + .HasForeignKey("BuildingID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany() + .WithMany("Staff_Trips") .HasForeignKey("StaffID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") + .WithOne("Staff_Trip") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", "TimeScheduleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Building"); + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => @@ -1046,11 +1161,55 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired(); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") + .WithMany("Transactions") + .HasForeignKey("WalletID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => + { + b.Navigation("Customers"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Transaction", null) - .WithMany("Wallet") - .HasForeignKey("TransactionId"); + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => + { + b.Navigation("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => + { + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + { + b.Navigation("Order"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => + { + b.Navigation("Staff_Trip") + .IsRequired(); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => @@ -1058,9 +1217,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Items"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => { - b.Navigation("Wallet"); + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + + b.Navigation("Transactions"); }); #pragma warning restore 612, 618 } diff --git a/src/Infrastructure/Migrations/20230918144740_InitMigration.cs b/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs similarity index 85% rename from src/Infrastructure/Migrations/20230918144740_InitMigration.cs rename to src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs index 75fab74..0371465 100644 --- a/src/Infrastructure/Migrations/20230918144740_InitMigration.cs +++ b/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs @@ -6,7 +6,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { /// - public partial class InitMigration : Migration + public partial class UpdateDatabase3 : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -145,6 +145,45 @@ protected override void Up(MigrationBuilder migrationBuilder) table.PrimaryKey("PK_PersistedGrants", x => x.Key); }); + migrationBuilder.CreateTable( + name: "Service", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: true), + Description = table.Column(type: "nvarchar(max)", nullable: true), + Price = table.Column(type: "float", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Service", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TimeSchedule", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false), + DayOfWeek = table.Column(type: "int", nullable: false), + TimeFrame = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TimeSchedule", x => x.Id); + }); + migrationBuilder.CreateTable( name: "TodoLists", columns: table => new @@ -164,17 +203,12 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "Transactions", + name: "Wallets", columns: table => new { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - TransactionType = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), + Balance = table.Column(type: "float", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -182,7 +216,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Transactions", x => x.Id); + table.PrimaryKey("PK_Wallets", x => x.Id); }); migrationBuilder.CreateTable( @@ -291,43 +325,6 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "Orders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ShipDate = table.Column(type: "datetime2", nullable: false), - OrderDate = table.Column(type: "datetime2", nullable: false), - ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "smallint", nullable: false), - IsWhiteClothes = table.Column(type: "bit", nullable: false), - TotalPrice = table.Column(type: "float", nullable: false), - PaymentMethodID = table.Column(type: "int", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - OrderType = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Orders", x => x.Id); - table.ForeignKey( - name: "FK_Orders_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Orders_PaymentMethods_PaymentMethodID", - column: x => x.PaymentMethodID, - principalTable: "PaymentMethods", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateTable( name: "TodoItems", columns: table => new @@ -356,53 +353,6 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "Wallets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Balance = table.Column(type: "float", nullable: false), - TransactionId = table.Column(type: "int", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Wallets", x => x.Id); - table.ForeignKey( - name: "FK_Wallets_Transactions_TransactionId", - column: x => x.TransactionId, - principalTable: "Transactions", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "OrderHistory", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderID = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OrderHistory", x => x.Id); - table.ForeignKey( - name: "FK_OrderHistory_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateTable( name: "Customers", columns: table => new @@ -479,8 +429,6 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - Dob = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), Salary = table.Column(type: "float", nullable: false), WalletID = table.Column(type: "int", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), @@ -507,16 +455,98 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "Staff_Trips", + name: "Transactions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), + Amount = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + WalletID = table.Column(type: "int", nullable: false), + TransactionType = table.Column(type: "int", nullable: false), + Status = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Transactions", x => x.Id); + table.ForeignKey( + name: "FK_Transactions_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Orders", columns: table => new { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), + OrderDate = table.Column(type: "datetime2", nullable: false), + ShipDate = table.Column(type: "datetime2", nullable: false), + ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), Address = table.Column(type: "nvarchar(max)", nullable: true), - StartTime = table.Column(type: "datetime2", nullable: false), - EndTime = table.Column(type: "datetime2", nullable: false), + Amount = table.Column(type: "smallint", nullable: false), + TotalPrice = table.Column(type: "float", nullable: false), + PaymentMethodID = table.Column(type: "int", nullable: false), + CustomerID = table.Column(type: "int", nullable: false), + ServiceId = table.Column(type: "int", nullable: true), + LaundryStoreId = table.Column(type: "int", nullable: true), + StaffId = table.Column(type: "int", nullable: true), + OrderType = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Customers_CustomerID", + column: x => x.CustomerID, + principalTable: "Customers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Orders_LaundryStores_LaundryStoreId", + column: x => x.LaundryStoreId, + principalTable: "LaundryStores", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Orders_PaymentMethods_PaymentMethodID", + column: x => x.PaymentMethodID, + principalTable: "PaymentMethods", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Orders_Service_ServiceId", + column: x => x.ServiceId, + principalTable: "Service", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Orders_Staffs_StaffId", + column: x => x.StaffId, + principalTable: "Staffs", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Staff_Trips", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), TripCollect = table.Column(type: "int", nullable: false), StaffID = table.Column(type: "int", nullable: false), + TimeScheduleID = table.Column(type: "int", nullable: false), + BuildingID = table.Column(type: "int", nullable: false), TripStatus = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), @@ -526,12 +556,48 @@ protected override void Up(MigrationBuilder migrationBuilder) constraints: table => { table.PrimaryKey("PK_Staff_Trips", x => x.Id); + table.ForeignKey( + name: "FK_Staff_Trips_Buildings_BuildingID", + column: x => x.BuildingID, + principalTable: "Buildings", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); table.ForeignKey( name: "FK_Staff_Trips_Staffs_StaffID", column: x => x.StaffID, principalTable: "Staffs", principalColumn: "Id", onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Staff_Trips_TimeSchedule_TimeScheduleID", + column: x => x.TimeScheduleID, + principalTable: "TimeSchedule", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OrderHistory", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + OrderID = table.Column(type: "int", nullable: false), + Status = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OrderHistory", x => x.Id); + table.ForeignKey( + name: "FK_OrderHistory_Orders_OrderID", + column: x => x.OrderID, + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateIndex( @@ -586,7 +652,8 @@ protected override void Up(MigrationBuilder migrationBuilder) migrationBuilder.CreateIndex( name: "IX_Customers_WalletID", table: "Customers", - column: "WalletID"); + column: "WalletID", + unique: true); migrationBuilder.CreateIndex( name: "IX_DeviceCodes_DeviceCode", @@ -612,7 +679,8 @@ protected override void Up(MigrationBuilder migrationBuilder) migrationBuilder.CreateIndex( name: "IX_LaundryStores_WalletID", table: "LaundryStores", - column: "WalletID"); + column: "WalletID", + unique: true); migrationBuilder.CreateIndex( name: "IX_OrderHistory_OrderID", @@ -620,15 +688,30 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "OrderID"); migrationBuilder.CreateIndex( - name: "IX_Orders_ApplicationUserID", + name: "IX_Orders_CustomerID", table: "Orders", - column: "ApplicationUserID"); + column: "CustomerID"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_LaundryStoreId", + table: "Orders", + column: "LaundryStoreId"); migrationBuilder.CreateIndex( name: "IX_Orders_PaymentMethodID", table: "Orders", column: "PaymentMethodID"); + migrationBuilder.CreateIndex( + name: "IX_Orders_ServiceId", + table: "Orders", + column: "ServiceId"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_StaffId", + table: "Orders", + column: "StaffId"); + migrationBuilder.CreateIndex( name: "IX_PersistedGrants_ConsumedTime", table: "PersistedGrants", @@ -649,11 +732,22 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "PersistedGrants", columns: new[] { "SubjectId", "SessionId", "Type" }); + migrationBuilder.CreateIndex( + name: "IX_Staff_Trips_BuildingID", + table: "Staff_Trips", + column: "BuildingID"); + migrationBuilder.CreateIndex( name: "IX_Staff_Trips_StaffID", table: "Staff_Trips", column: "StaffID"); + migrationBuilder.CreateIndex( + name: "IX_Staff_Trips_TimeScheduleID", + table: "Staff_Trips", + column: "TimeScheduleID", + unique: true); + migrationBuilder.CreateIndex( name: "IX_Staffs_ApplicationUserID", table: "Staffs", @@ -662,7 +756,8 @@ protected override void Up(MigrationBuilder migrationBuilder) migrationBuilder.CreateIndex( name: "IX_Staffs_WalletID", table: "Staffs", - column: "WalletID"); + column: "WalletID", + unique: true); migrationBuilder.CreateIndex( name: "IX_TodoItems_ListId", @@ -670,9 +765,9 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "ListId"); migrationBuilder.CreateIndex( - name: "IX_Wallets_TransactionId", - table: "Wallets", - column: "TransactionId"); + name: "IX_Transactions_WalletID", + table: "Transactions", + column: "WalletID"); } /// @@ -693,18 +788,12 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "AspNetUserTokens"); - migrationBuilder.DropTable( - name: "Customers"); - migrationBuilder.DropTable( name: "DeviceCodes"); migrationBuilder.DropTable( name: "Keys"); - migrationBuilder.DropTable( - name: "LaundryStores"); - migrationBuilder.DropTable( name: "OrderHistory"); @@ -718,31 +807,43 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "TodoItems"); migrationBuilder.DropTable( - name: "AspNetRoles"); + name: "Transactions"); migrationBuilder.DropTable( - name: "Buildings"); + name: "AspNetRoles"); migrationBuilder.DropTable( name: "Orders"); migrationBuilder.DropTable( - name: "Staffs"); + name: "TimeSchedule"); migrationBuilder.DropTable( name: "TodoLists"); + migrationBuilder.DropTable( + name: "Customers"); + + migrationBuilder.DropTable( + name: "LaundryStores"); + migrationBuilder.DropTable( name: "PaymentMethods"); migrationBuilder.DropTable( - name: "AspNetUsers"); + name: "Service"); migrationBuilder.DropTable( - name: "Wallets"); + name: "Staffs"); migrationBuilder.DropTable( - name: "Transactions"); + name: "Buildings"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + + migrationBuilder.DropTable( + name: "Wallets"); } } } diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index f6022f9..c64d9cf 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -369,7 +369,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("BuildingID"); - b.HasIndex("WalletID"); + b.HasIndex("WalletID") + .IsUnique(); b.ToTable("Customers"); }); @@ -419,7 +420,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.HasIndex("WalletID"); + b.HasIndex("WalletID") + .IsUnique(); b.ToTable("LaundryStores"); }); @@ -438,27 +440,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Amount") .HasColumnType("smallint"); - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); + b.Property("CustomerID") + .HasColumnType("int"); + b.Property("ExpectedFinishDate") .HasColumnType("datetime2"); - b.Property("IsWhiteClothes") - .HasColumnType("bit"); - b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("LaundryStoreId") + .HasColumnType("int"); + b.Property("OrderDate") .HasColumnType("datetime2"); @@ -468,18 +470,30 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); + b.Property("ServiceId") + .HasColumnType("int"); + b.Property("ShipDate") .HasColumnType("datetime2"); + b.Property("StaffId") + .HasColumnType("int"); + b.Property("TotalPrice") .HasColumnType("float"); b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreId"); b.HasIndex("PaymentMethodID"); + b.HasIndex("ServiceId"); + + b.HasIndex("StaffId"); + b.ToTable("Orders"); }); @@ -547,7 +561,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("PaymentMethods"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -555,9 +569,40 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Service"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); @@ -567,9 +612,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Dob") - .HasColumnType("datetime2"); - b.Property("LastModified") .HasColumnType("datetime2"); @@ -589,7 +631,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.HasIndex("WalletID"); + b.HasIndex("WalletID") + .IsUnique(); b.ToTable("Staffs"); }); @@ -602,8 +645,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("Address") - .HasColumnType("nvarchar(max)"); + b.Property("BuildingID") + .HasColumnType("int"); b.Property("Created") .HasColumnType("datetime2"); @@ -611,9 +654,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("EndTime") - .HasColumnType("datetime2"); - b.Property("LastModified") .HasColumnType("datetime2"); @@ -623,8 +663,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("StaffID") .HasColumnType("int"); - b.Property("StartTime") - .HasColumnType("datetime2"); + b.Property("TimeScheduleID") + .HasColumnType("int"); b.Property("TripCollect") .HasColumnType("int"); @@ -634,11 +674,53 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); + b.HasIndex("BuildingID"); + b.HasIndex("StaffID"); + b.HasIndex("TimeScheduleID") + .IsUnique(); + b.ToTable("Staff_Trips"); }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedule"); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => { b.Property("Id") @@ -756,6 +838,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); + b.HasIndex("WalletID"); + b.ToTable("Transactions"); }); @@ -782,13 +866,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("TransactionId") - .HasColumnType("int"); - b.HasKey("Id"); - b.HasIndex("TransactionId"); - b.ToTable("Wallets"); }); @@ -918,14 +997,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany() + .WithMany("Customers") .HasForeignKey("BuildingID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") + .WithOne("Customer") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Customer", "WalletID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -943,8 +1022,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") + .WithOne("LaundryStore") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "WalletID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -955,25 +1034,45 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") .WithMany() - .HasForeignKey("ApplicationUserID"); + .HasForeignKey("CustomerID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") + .WithMany("Orders") + .HasForeignKey("LaundryStoreId"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") - .WithMany() + .WithMany("Orders") .HasForeignKey("PaymentMethodID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("ApplicationUser"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", "Service") + .WithMany("Order") + .HasForeignKey("ServiceId"); + + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") + .WithMany("Order") + .HasForeignKey("StaffId"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); b.Navigation("PaymentMethod"); + + b.Navigation("Service"); + + b.Navigation("Staff"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => { b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany() + .WithMany("OrderHistories") .HasForeignKey("OrderID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -988,8 +1087,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ApplicationUserID"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletID") + .WithOne("Staff") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff", "WalletID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -1000,13 +1099,29 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") + .WithMany("Staff_Trips") + .HasForeignKey("BuildingID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany() + .WithMany("Staff_Trips") .HasForeignKey("StaffID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") + .WithOne("Staff_Trip") + .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", "TimeScheduleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Building"); + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => @@ -1043,11 +1158,55 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") + .WithMany("Transactions") + .HasForeignKey("WalletID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => + { + b.Navigation("Customers"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Transaction", null) - .WithMany("Wallet") - .HasForeignKey("TransactionId"); + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => + { + b.Navigation("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => + { + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + { + b.Navigation("Order"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => + { + b.Navigation("Staff_Trip") + .IsRequired(); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => @@ -1055,9 +1214,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Items"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => { - b.Navigation("Wallet"); + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + + b.Navigation("Transactions"); }); #pragma warning restore 612, 618 } diff --git a/src/WebUI/WebUI.csproj b/src/WebUI/WebUI.csproj index 8d10436..451a231 100644 --- a/src/WebUI/WebUI.csproj +++ b/src/WebUI/WebUI.csproj @@ -44,7 +44,7 @@ OnBuildSuccess - + diff --git a/src/WebUI/appsettings.json b/src/WebUI/appsettings.json index 63f5e42..790319c 100644 --- a/src/WebUI/appsettings.json +++ b/src/WebUI/appsettings.json @@ -1,7 +1,7 @@ { "UseInMemoryDatabase": false, "ConnectionStrings": { - "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=Laundry;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=12345" + "DefaultConnection": "Server=LEWIS;Database=Laundry;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=123456;TrustServerCertificate=true" }, "Logging": { From 3abd665ad08621cc6492c63568651b1427070db5 Mon Sep 17 00:00:00 2001 From: Nero Date: Wed, 20 Sep 2023 02:54:03 +0700 Subject: [PATCH 11/53] Delete src/WebUI/appsettings.json --- src/WebUI/appsettings.json | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/WebUI/appsettings.json diff --git a/src/WebUI/appsettings.json b/src/WebUI/appsettings.json deleted file mode 100644 index 790319c..0000000 --- a/src/WebUI/appsettings.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "UseInMemoryDatabase": false, - "ConnectionStrings": { - "DefaultConnection": "Server=LEWIS;Database=Laundry;Trusted_Connection=True;MultipleActiveResultSets=true;User ID=sa;Password=123456;TrustServerCertificate=true" - - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "IdentityServer": { - "Clients": { - "SWD_Laundry_Backend.WebUI": { - "Profile": "IdentityServerSPA" - } - } - }, - "AllowedHosts": "*" -} From cb5ad40437be8afafaddc58c3d3e8ec4ce7b1c15 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Wed, 20 Sep 2023 02:54:21 +0700 Subject: [PATCH 12/53] update --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 52dc8e2..6f06060 100644 --- a/.gitignore +++ b/.gitignore @@ -236,3 +236,4 @@ _Pvt_Extensions /SWD_Laundry_Backend.ndproj /.mfractor src/WebUI/ClientApp/package-lock.json +/src/WebUI/appsettings.json From 0be1ca057572a37812b27f0ba994ff8dd4bddd1a Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Wed, 20 Sep 2023 02:54:40 +0700 Subject: [PATCH 13/53] Dev --- .../CreateBuilding/CreateBuildingCommand.cs | 2 +- .../Interfaces/IApplicationDbContext.cs | 23 +++++++++---------- .../GetTodoItemsWithPaginationQuery.cs | 3 ++- src/Domain/Entities/PaymentMethod.cs | 2 ++ .../Persistence/ApplicationDbContext.cs | 22 +++++++++--------- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs index 54ac321..f4f2deb 100644 --- a/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs +++ b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs @@ -21,7 +21,7 @@ public CreateBuildingCommandHandler(IApplicationDbContext context) public async Task Handle(CreateBuildingCommand request, CancellationToken cancellationToken) { - var entity = new Domain.Entities.Building + var entity = new Building { Name = request.Name, Address = request.Address, diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index be24d29..94c41a9 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -1,7 +1,6 @@ using SWD_Laundry_Backend.Domain.Entities; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Domain.Common; -using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Application.Common.Interfaces; @@ -10,17 +9,17 @@ public interface IApplicationDbContext DbSet TodoLists { get; } DbSet TodoItems { get; } - DbSet Customers { get; } - DbSet Buildings { get; } - DbSet ApplicationUsers { get; } - DbSet LaundryStores { get; } - DbSet Orders { get; } - DbSet OrdersHistory { get; } - DbSet PaymentMethods { get; } - DbSet Staff_Trips { get; } - DbSet Staffs { get; } - DbSet Transactions { get; } - DbSet Wallets { get; } + //DbSet Customers { get; } + //DbSet Buildings { get; } + //DbSet ApplicationUsers { get; } + //DbSet LaundryStores { get; } + //DbSet Orders { get; } + //DbSet OrdersHistory { get; } + //DbSet PaymentMethods { get; } + //DbSet Staff_Trips { get; } + //DbSet Staffs { get; } + //DbSet Transactions { get; } + //DbSet Wallets { get; } DbSet Get() where T : BaseAuditableEntity; diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs index e22c477..3672823 100644 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs @@ -4,6 +4,7 @@ using SWD_Laundry_Backend.Application.Common.Mappings; using SWD_Laundry_Backend.Application.Common.Models; using MediatR; +using SWD_Laundry_Backend.Domain.Entities; namespace SWD_Laundry_Backend.Application.TodoItems.Queries.GetTodoItemsWithPagination; @@ -27,7 +28,7 @@ public GetTodoItemsWithPaginationQueryHandler(IApplicationDbContext context, IMa public void Test() { - var test1 = _context.Orders.Where(c => c.LaundryStore.Id == 1).ToList(); + var test1 = _context.Get().Where(c => c.LaundryStore.Id == 1).ToList(); } public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 6b2ee74..30feee1 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -25,4 +25,6 @@ public class PaymentMethod : BaseAuditableEntity // } //} public string Name { get; set; } + + #endregion Special Attributes } \ No newline at end of file diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index c6169ce..1d8bfbd 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -33,19 +33,19 @@ public ApplicationDbContext( public DbSet TodoItems => Set(); - public DbSet ApplicationUsers => Set(); + //public DbSet ApplicationUsers => Set(); - public DbSet Buildings => Set(); - public DbSet Customers => Set(); - public DbSet LaundryStores => Set(); - public DbSet Orders => Set(); - public DbSet OrderHistory => Set(); - public DbSet PaymentMethods => Set(); - public DbSet Staff_Trips => Set(); - public DbSet Staffs => Set(); + //public DbSet Buildings => Set(); + //public DbSet Customers => Set(); + //public DbSet LaundryStores => Set(); + //public DbSet Orders => Set(); + //public DbSet OrderHistory => Set(); + //public DbSet PaymentMethods => Set(); + //public DbSet Staff_Trips => Set(); + //public DbSet Staffs => Set(); - public DbSet Transactions => Set(); - public DbSet Wallets => Set(); + //public DbSet Transactions => Set(); + //public DbSet Wallets => Set(); protected override void OnModelCreating(ModelBuilder builder) { From 526a09f0debdd3253a0c5c4dfe1bbf95de0656af Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Fri, 22 Sep 2023 19:15:13 +0700 Subject: [PATCH 14/53] UpdateEntity5 --- .../Buildings/Queries/BuildingViewModel.cs | 6 +- .../Interfaces/IApplicationDbContext.cs | 3 +- .../CreatePaymentMethodCommand.cs | 4 +- .../Queries/PaymentMethodDto.cs | 2 +- .../GetTodoItemsWithPaginationQuery.cs | 5 +- src/Domain/Entities/Customer.cs | 10 +- src/Domain/Entities/LaundryStore.cs | 7 - src/Domain/Entities/LaundryStoreOrder.cs | 22 + src/Domain/Entities/Order.cs | 22 +- src/Domain/Entities/OrderHistory.cs | 14 +- src/Domain/Entities/PaymentMethod.cs | 12 +- src/Domain/Entities/Service.cs | 21 - src/Domain/Entities/Staff.cs | 16 +- src/Domain/Entities/StaffOrder.cs | 28 ++ src/Domain/Entities/Staff_Trip.cs | 2 +- src/Domain/Entities/TimeSchedule.cs | 5 +- src/Domain/Entities/Transaction.cs | 2 +- src/Domain/Entities/Wallet.cs | 9 +- .../Enums/{Status.cs => OrderStatus.cs} | 4 +- src/Domain/Enums/StaffOrderType.cs | 13 + src/Domain/Enums/StaffRole.cs | 6 - src/Domain/IdentityModel/ApplicationUser.cs | 16 +- ...0230922043540_UpdateDatabase5.Designer.cs} | 237 +++++----- ...3.cs => 20230922043540_UpdateDatabase5.cs} | 408 +++++++++--------- .../ApplicationDbContextModelSnapshot.cs | 233 +++++----- .../Persistence/ApplicationDbContext.cs | 6 +- 26 files changed, 576 insertions(+), 537 deletions(-) create mode 100644 src/Domain/Entities/LaundryStoreOrder.cs delete mode 100644 src/Domain/Entities/Service.cs create mode 100644 src/Domain/Entities/StaffOrder.cs rename src/Domain/Enums/{Status.cs => OrderStatus.cs} (72%) create mode 100644 src/Domain/Enums/StaffOrderType.cs delete mode 100644 src/Domain/Enums/StaffRole.cs rename src/Infrastructure/Migrations/{20230919183842_UpdateDatabase3.Designer.cs => 20230922043540_UpdateDatabase5.Designer.cs} (92%) rename src/Infrastructure/Migrations/{20230919183842_UpdateDatabase3.cs => 20230922043540_UpdateDatabase5.cs} (90%) diff --git a/src/Application/Buildings/Queries/BuildingViewModel.cs b/src/Application/Buildings/Queries/BuildingViewModel.cs index 590af13..03657a7 100644 --- a/src/Application/Buildings/Queries/BuildingViewModel.cs +++ b/src/Application/Buildings/Queries/BuildingViewModel.cs @@ -4,7 +4,7 @@ namespace SWD_Laundry_Backend.Application.Buildings.Queries; public class BuildingViewModel : IMapFrom { - public string Name { get; set; } - public string Address { get; set; } - public string Description { get; set; } + public string? Name { get; set; } + public string? Address { get; set; } + public string? Description { get; set; } } diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index be24d29..2b229f9 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -15,12 +15,13 @@ public interface IApplicationDbContext DbSet ApplicationUsers { get; } DbSet LaundryStores { get; } DbSet Orders { get; } - DbSet OrdersHistory { get; } + DbSet OrdersHistory{ get; } DbSet PaymentMethods { get; } DbSet Staff_Trips { get; } DbSet Staffs { get; } DbSet Transactions { get; } DbSet Wallets { get; } + DbSet Get() where T : BaseAuditableEntity; diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs index b67439e..e608eaf 100644 --- a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs +++ b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs @@ -6,8 +6,8 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; public class CreatePaymentMethodCommand : IRequest { - public string Name { get; set; } - public string Description { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } } public class CreatePaymentMethodCommandHandler : IRequestHandler diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs index b282b1d..b255489 100644 --- a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs +++ b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs @@ -5,6 +5,6 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; public class PaymentMethodDto : IMapFrom { - public string Name { get; init; } + public string? Name { get; init; } public string? Description { get; set; } } diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs index e22c477..5c602bf 100644 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs +++ b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs @@ -25,10 +25,7 @@ public GetTodoItemsWithPaginationQueryHandler(IApplicationDbContext context, IMa _mapper = mapper; } - public void Test() - { - var test1 = _context.Orders.Where(c => c.LaundryStore.Id == 1).ToList(); - } + public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) { diff --git a/src/Domain/Entities/Customer.cs b/src/Domain/Entities/Customer.cs index 220ba40..2d38dcb 100644 --- a/src/Domain/Entities/Customer.cs +++ b/src/Domain/Entities/Customer.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.Entities.Validation; using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Domain.Entities; @@ -8,7 +7,7 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Customer : BaseAuditableEntity { - //public string Name { get; set; } + //public string Name { get; set; } //public string Address { get; set; } #region Relationship @@ -16,16 +15,13 @@ public class Customer : BaseAuditableEntity [ForeignKey("Building")] public int BuildingID { get; set; } - [ForeignKey("Wallet")] - public int WalletID { get; set; } - [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } public Building Building { get; set; } - public Wallet Wallet { get; set; } + public ApplicationUser ApplicationUser { get; set; } - //public virtual List Order { get; set; } + public virtual List Order { get; set; } #endregion Relationship diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs index fe8f488..35ac678 100644 --- a/src/Domain/Entities/LaundryStore.cs +++ b/src/Domain/Entities/LaundryStore.cs @@ -19,14 +19,7 @@ public class LaundryStore : BaseAuditableEntity [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } - [ForeignKey("Wallet")] - public int WalletID { get; set; } - public ApplicationUser ApplicationUser { get; set; } - public Wallet Wallet { get; set; } - - - public virtual List Orders { get; set; } #endregion Relationship } \ No newline at end of file diff --git a/src/Domain/Entities/LaundryStoreOrder.cs b/src/Domain/Entities/LaundryStoreOrder.cs new file mode 100644 index 0000000..89b83ac --- /dev/null +++ b/src/Domain/Entities/LaundryStoreOrder.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace SWD_Laundry_Backend.Domain.Entities; + +public class LaundryStoreOrder : BaseAuditableEntity +#nullable disable +{ + public bool IsDone { get; set; } + + #region Relationship + + [ForeignKey("Order")] + public int OrderID { get; set; } + + [ForeignKey("LaundryStore")] + public int LaundryStoreID { get; set; } + + public LaundryStore LaundryStore { get; set; } + public Order Order { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs index b228f8a..b132d82 100644 --- a/src/Domain/Entities/Order.cs +++ b/src/Domain/Entities/Order.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable @@ -7,9 +6,7 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Order : BaseAuditableEntity { public DateTime OrderDate { get; set; } = DateTime.Now; - - public DateTime ShipDate { get; set; } - + public TimeFrame TimeFrame { get; set; } public DateTime ExpectedFinishDate { get; set; } public string Address { get; set; } // Address = Customer's building location public short Amount { get; set; } @@ -24,24 +21,13 @@ public class Order : BaseAuditableEntity [ForeignKey("Customer")] public int CustomerID { get; set; } - //[ForeignKey("LaundryStore")] - //public int LaundryStoreID { get; set; } - - ////[ForeignKey("Staff")] - ////public int StaffID { get; set; } - - //[ForeignKey("Service")] - //public int ServiceID { get; set; } - ////=========================== - public Service Service { get; set; } - - public virtual LaundryStore LaundryStore { get; set; } - public virtual Customer Customer { get; set; } - public virtual Staff Staff { get; set; } + public Customer Customer { get; set; } public PaymentMethod PaymentMethod { get; set; } public List OrderHistories { get; set; } + public List StaffOrders { get; set; } + //public LaundryStoreOrder LaundryStoreOrder { get; set; } #endregion Relationship diff --git a/src/Domain/Entities/OrderHistory.cs b/src/Domain/Entities/OrderHistory.cs index f660ac5..9e7c13d 100644 --- a/src/Domain/Entities/OrderHistory.cs +++ b/src/Domain/Entities/OrderHistory.cs @@ -17,19 +17,7 @@ public class OrderHistory : BaseAuditableEntity #region Special attributes - //private string _orderstatus; - - //public string Status - //{ - // get { return _orderstatus; } - // set - // { - // _orderstatus = new Validate().IsValidTripStatus(value) - // ? value - // : throw new ArgumentException("Invalid order status {FINISHED, PROCESSING, CANCELLED}."); - // } - //} - public Status Status { get; set;} + public OrderStatus Status { get; set;} #endregion Special attributes } \ No newline at end of file diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 6b2ee74..4b6b79e 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -13,16 +13,6 @@ public class PaymentMethod : BaseAuditableEntity #region Special Attributes - - //public string PaymentType - //{ - // get { return _type; } - // set - // { - // _type = new Validate().IsValidPayment(value) - // ? value - // : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); - // } - //} public string Name { get; set; } + #endregion } \ No newline at end of file diff --git a/src/Domain/Entities/Service.cs b/src/Domain/Entities/Service.cs deleted file mode 100644 index 21146d4..0000000 --- a/src/Domain/Entities/Service.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Service : BaseAuditableEntity -{ - public string Name { get; set; } - public string Description { get; set; } - public double Price { get; set; } - - #region Relationship - - public List Order { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/Staff.cs b/src/Domain/Entities/Staff.cs index 2bb90f2..ae26c6f 100644 --- a/src/Domain/Entities/Staff.cs +++ b/src/Domain/Entities/Staff.cs @@ -6,29 +6,19 @@ namespace SWD_Laundry_Backend.Domain.Entities; public class Staff : BaseAuditableEntity { - //public DateTime Dob { get; set; } - //public string Address { get; set; } + public DateTime Dob { get; set; } + public string Address { get; set; } public double Salary { get; set; } #region Relationship - [ForeignKey("Wallet")] - public int WalletID { get; set; } - [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } public ApplicationUser ApplicationUser { get; set; } - public Wallet Wallet { get; set; } - public List Order { get; set; } public List Staff_Trips { get; set; } + public List StaffOrders { get; set; } #endregion Relationship - - #region Special Attribute - - public StaffRole StaffRole { get; set; } - - #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/StaffOrder.cs b/src/Domain/Entities/StaffOrder.cs new file mode 100644 index 0000000..c3ae50c --- /dev/null +++ b/src/Domain/Entities/StaffOrder.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Domain.Entities; +#nullable disable + +public class StaffOrder : BaseAuditableEntity +{ + public bool IsDone { get; set; } + public StaffOrderType Type { get; set; } + + #region Relationship + + [ForeignKey("Staff")] + public int StaffID { get; set; } + + [ForeignKey("Order")] + public int OrderID { get; set; } + + public Staff Staff { get; set; } + public Order Order { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/Domain/Entities/Staff_Trip.cs b/src/Domain/Entities/Staff_Trip.cs index 5fc617d..260c96b 100644 --- a/src/Domain/Entities/Staff_Trip.cs +++ b/src/Domain/Entities/Staff_Trip.cs @@ -29,7 +29,7 @@ public class Staff_Trip : BaseAuditableEntity #region Special Attribute - public Status TripStatus { get; set; } + public OrderStatus TripStatus { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/TimeSchedule.cs b/src/Domain/Entities/TimeSchedule.cs index b2e777c..966531e 100644 --- a/src/Domain/Entities/TimeSchedule.cs +++ b/src/Domain/Entities/TimeSchedule.cs @@ -1,7 +1,8 @@ namespace SWD_Laundry_Backend.Domain.Entities; +#nullable disable public class TimeSchedule : BaseAuditableEntity -{ +{ public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } @@ -9,7 +10,7 @@ public class TimeSchedule : BaseAuditableEntity public DayOfWeek DayOfWeek { get; set; } public TimeFrame TimeFrame { get; set; } - public Staff_Trip Staff_Trip { get; set; } + public List Staff_Trip { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs index 004a1ac..190996f 100644 --- a/src/Domain/Entities/Transaction.cs +++ b/src/Domain/Entities/Transaction.cs @@ -32,7 +32,7 @@ public class Transaction : BaseAuditableEntity public AllowedTransactionType TransactionType { get; set; } - public Status Status { get; set; } + public OrderStatus Status { get; set; } #endregion Special Attribute } \ No newline at end of file diff --git a/src/Domain/Entities/Wallet.cs b/src/Domain/Entities/Wallet.cs index ee9361f..7f3078a 100644 --- a/src/Domain/Entities/Wallet.cs +++ b/src/Domain/Entities/Wallet.cs @@ -1,4 +1,6 @@ -namespace SWD_Laundry_Backend.Domain.Entities; +using SWD_Laundry_Backend.Domain.IdentityModel; + +namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable public class Wallet : BaseAuditableEntity @@ -8,9 +10,8 @@ public class Wallet : BaseAuditableEntity #region Relationship public List Transactions { get; set; } - public Customer Customer { get; set; } - public LaundryStore LaundryStore { get; set; } - public Staff Staff { get; set; } + + public ApplicationUser ApplicationUser { get; set; } #endregion Relationship } \ No newline at end of file diff --git a/src/Domain/Enums/Status.cs b/src/Domain/Enums/OrderStatus.cs similarity index 72% rename from src/Domain/Enums/Status.cs rename to src/Domain/Enums/OrderStatus.cs index 9f5770b..492970f 100644 --- a/src/Domain/Enums/Status.cs +++ b/src/Domain/Enums/OrderStatus.cs @@ -1,7 +1,7 @@ namespace SWD_Laundry_Backend.Domain.Enums; -public enum Status +public enum OrderStatus { - Pending = 1, + Pending = 1, Processing = 2, Completed = 3, Cancelled = 4 diff --git a/src/Domain/Enums/StaffOrderType.cs b/src/Domain/Enums/StaffOrderType.cs new file mode 100644 index 0000000..32c6d6e --- /dev/null +++ b/src/Domain/Enums/StaffOrderType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Domain.Enums; + +public enum StaffOrderType +{ + CollectFromCustomer = 0, + DeliveryToCustomer = 1 +} \ No newline at end of file diff --git a/src/Domain/Enums/StaffRole.cs b/src/Domain/Enums/StaffRole.cs deleted file mode 100644 index 708fd15..0000000 --- a/src/Domain/Enums/StaffRole.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Enums; -public enum StaffRole -{ - COLLECTOR = 1, - RECIEVER = 2, -} diff --git a/src/Domain/IdentityModel/ApplicationUser.cs b/src/Domain/IdentityModel/ApplicationUser.cs index a5af9f3..f6152ab 100644 --- a/src/Domain/IdentityModel/ApplicationUser.cs +++ b/src/Domain/IdentityModel/ApplicationUser.cs @@ -1,7 +1,19 @@ -using Microsoft.AspNetCore.Identity; +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.AspNetCore.Identity; + namespace SWD_Laundry_Backend.Domain.IdentityModel; public class ApplicationUser : IdentityUser { - public string? Name { get; set; } +#nullable disable + public string Name { get; set; } + + #region Relationship + + [ForeignKey("Wallet")] + public int WalletID { get; set; } + + public Wallet Wallet { get; set; } + + #endregion Relationship } \ No newline at end of file diff --git a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs b/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs similarity index 92% rename from src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs rename to src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs index ca49bad..1c0d07d 100644 --- a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs +++ b/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs @@ -12,8 +12,8 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230919183842_UpdateDatabase3")] - partial class UpdateDatabase3 + [Migration("20230922043540_UpdateDatabase5")] + partial class UpdateDatabase5 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -363,18 +363,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("WalletID") - .HasColumnType("int"); - b.HasKey("Id"); b.HasIndex("ApplicationUserID"); b.HasIndex("BuildingID"); - b.HasIndex("WalletID") - .IsUnique(); - b.ToTable("Customers"); }); @@ -416,17 +410,49 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Status") .HasColumnType("bit"); - b.Property("WalletID") + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDone") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LaundryStoreID") + .HasColumnType("int"); + + b.Property("OrderID") .HasColumnType("int"); b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); + b.HasIndex("LaundryStoreID"); - b.HasIndex("WalletID") - .IsUnique(); + b.HasIndex("OrderID"); - b.ToTable("LaundryStores"); + b.ToTable("LaundryStoreOrders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => @@ -461,9 +487,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("LaundryStoreId") - .HasColumnType("int"); - b.Property("OrderDate") .HasColumnType("datetime2"); @@ -473,13 +496,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); - b.Property("ServiceId") - .HasColumnType("int"); - - b.Property("ShipDate") - .HasColumnType("datetime2"); - - b.Property("StaffId") + b.Property("TimeFrame") .HasColumnType("int"); b.Property("TotalPrice") @@ -489,14 +506,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("CustomerID"); - b.HasIndex("LaundryStoreId"); - b.HasIndex("PaymentMethodID"); - b.HasIndex("ServiceId"); - - b.HasIndex("StaffId"); - b.ToTable("Orders"); }); @@ -530,7 +541,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("OrderID"); - b.ToTable("OrderHistory"); + b.ToTable("OrdersHistory"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => @@ -556,15 +567,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("PaymentType") - .HasColumnType("int"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); b.ToTable("PaymentMethods"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -572,14 +583,20 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Description") - .HasColumnType("nvarchar(max)"); + b.Property("Dob") + .HasColumnType("datetime2"); b.Property("LastModified") .HasColumnType("datetime2"); @@ -587,18 +604,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("Price") + b.Property("Salary") .HasColumnType("float"); b.HasKey("Id"); - b.ToTable("Service"); + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -606,38 +622,37 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); + b.Property("IsDone") + .HasColumnType("bit"); + b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Salary") - .HasColumnType("float"); + b.Property("OrderID") + .HasColumnType("int"); - b.Property("StaffRole") + b.Property("StaffID") .HasColumnType("int"); - b.Property("WalletID") + b.Property("Type") .HasColumnType("int"); b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); + b.HasIndex("OrderID"); - b.HasIndex("WalletID") - .IsUnique(); + b.HasIndex("StaffID"); - b.ToTable("Staffs"); + b.ToTable("StaffOrders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => @@ -681,8 +696,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("StaffID"); - b.HasIndex("TimeScheduleID") - .IsUnique(); + b.HasIndex("TimeScheduleID"); b.ToTable("Staff_Trips"); }); @@ -721,7 +735,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("TimeSchedule"); + b.ToTable("TimeSchedules"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => @@ -929,6 +943,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasMaxLength(256) .HasColumnType("nvarchar(256)"); + b.Property("WalletID") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("NormalizedEmail") @@ -939,6 +956,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); + b.HasIndex("WalletID") + .IsUnique(); + b.ToTable("AspNetUsers", (string)null); }); @@ -1005,17 +1025,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("Customer") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Customer", "WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.Navigation("ApplicationUser"); b.Navigation("Building"); - - b.Navigation("Wallet"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => @@ -1024,52 +1036,45 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("LaundryStore") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "WalletID") + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") + .WithMany() + .HasForeignKey("LaundryStoreID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("ApplicationUser"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") + .WithMany() + .HasForeignKey("OrderID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Wallet"); + b.Navigation("LaundryStore"); + + b.Navigation("Order"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") - .WithMany() + .WithMany("Order") .HasForeignKey("CustomerID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany("Orders") - .HasForeignKey("LaundryStoreId"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") .WithMany("Orders") .HasForeignKey("PaymentMethodID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", "Service") - .WithMany("Order") - .HasForeignKey("ServiceId"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Order") - .HasForeignKey("StaffId"); - b.Navigation("Customer"); - b.Navigation("LaundryStore"); - b.Navigation("PaymentMethod"); - - b.Navigation("Service"); - - b.Navigation("Staff"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => @@ -1089,15 +1094,26 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("Staff") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff", "WalletID") + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") + .WithMany("StaffOrders") + .HasForeignKey("OrderID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("ApplicationUser"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") + .WithMany("StaffOrders") + .HasForeignKey("StaffID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Wallet"); + b.Navigation("Order"); + + b.Navigation("Staff"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => @@ -1115,8 +1131,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired(); b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") - .WithOne("Staff_Trip") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", "TimeScheduleID") + .WithMany("Staff_Trip") + .HasForeignKey("TimeScheduleID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -1172,6 +1188,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Wallet"); }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "WalletID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Wallet"); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => { b.Navigation("Customers"); @@ -1179,14 +1206,16 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Staff_Trips"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => { - b.Navigation("Orders"); + b.Navigation("Order"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.Navigation("OrderHistories"); + + b.Navigation("StaffOrders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => @@ -1194,22 +1223,16 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Orders"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Navigation("Order"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { - b.Navigation("Order"); + b.Navigation("StaffOrders"); b.Navigation("Staff_Trips"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => { - b.Navigation("Staff_Trip") - .IsRequired(); + b.Navigation("Staff_Trip"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => @@ -1219,11 +1242,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => { - b.Navigation("Customer"); - - b.Navigation("LaundryStore"); - - b.Navigation("Staff"); + b.Navigation("ApplicationUser"); b.Navigation("Transactions"); }); diff --git a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs b/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs similarity index 90% rename from src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs rename to src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs index 0371465..c328226 100644 --- a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs +++ b/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs @@ -6,7 +6,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { /// - public partial class UpdateDatabase3 : Migration + public partial class UpdateDatabase5 : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -25,32 +25,6 @@ protected override void Up(MigrationBuilder migrationBuilder) table.PrimaryKey("PK_AspNetRoles", x => x.Id); }); - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: true), - UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - migrationBuilder.CreateTable( name: "Buildings", columns: table => new @@ -114,7 +88,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Description = table.Column(type: "nvarchar(max)", nullable: true), - PaymentType = table.Column(type: "int", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -146,26 +120,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "Service", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Price = table.Column(type: "float", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Service", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "TimeSchedule", + name: "TimeSchedules", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -181,7 +136,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_TimeSchedule", x => x.Id); + table.PrimaryKey("PK_TimeSchedules", x => x.Id); }); migrationBuilder.CreateTable( @@ -240,6 +195,95 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "TodoItems", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ListId = table.Column(type: "int", nullable: false), + Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Note = table.Column(type: "nvarchar(max)", nullable: true), + Priority = table.Column(type: "int", nullable: false), + Reminder = table.Column(type: "datetime2", nullable: true), + Done = table.Column(type: "bit", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TodoItems", x => x.Id); + table.ForeignKey( + name: "FK_TodoItems_TodoLists_ListId", + column: x => x.ListId, + principalTable: "TodoLists", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), + WalletID = table.Column(type: "int", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUsers_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Transactions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), + Amount = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + WalletID = table.Column(type: "int", nullable: false), + TransactionType = table.Column(type: "int", nullable: false), + Status = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Transactions", x => x.Id); + table.ForeignKey( + name: "FK_Transactions_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AspNetUserClaims", columns: table => new @@ -325,34 +369,6 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ListId = table.Column(type: "int", nullable: false), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Note = table.Column(type: "nvarchar(max)", nullable: true), - Priority = table.Column(type: "int", nullable: false), - Reminder = table.Column(type: "datetime2", nullable: true), - Done = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - table.ForeignKey( - name: "FK_TodoItems_TodoLists_ListId", - column: x => x.ListId, - principalTable: "TodoLists", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateTable( name: "Customers", columns: table => new @@ -360,7 +376,6 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), BuildingID = table.Column(type: "int", nullable: false), - WalletID = table.Column(type: "int", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), @@ -381,12 +396,6 @@ protected override void Up(MigrationBuilder migrationBuilder) principalTable: "Buildings", principalColumn: "Id", onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Customers_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -401,7 +410,6 @@ protected override void Up(MigrationBuilder migrationBuilder) EndTime = table.Column(type: "datetime2", nullable: false), Status = table.Column(type: "bit", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -415,12 +423,6 @@ protected override void Up(MigrationBuilder migrationBuilder) column: x => x.ApplicationUserID, principalTable: "AspNetUsers", principalColumn: "Id"); - table.ForeignKey( - name: "FK_LaundryStores_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -429,10 +431,10 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), + Dob = table.Column(type: "datetime2", nullable: false), + Address = table.Column(type: "nvarchar(max)", nullable: true), Salary = table.Column(type: "float", nullable: false), - WalletID = table.Column(type: "int", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - StaffRole = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -446,40 +448,6 @@ protected override void Up(MigrationBuilder migrationBuilder) column: x => x.ApplicationUserID, principalTable: "AspNetUsers", principalColumn: "Id"); - table.ForeignKey( - name: "FK_Staffs_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Transactions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - TransactionType = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Transactions", x => x.Id); - table.ForeignKey( - name: "FK_Transactions_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -489,16 +457,13 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), OrderDate = table.Column(type: "datetime2", nullable: false), - ShipDate = table.Column(type: "datetime2", nullable: false), + TimeFrame = table.Column(type: "int", nullable: false), ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), Address = table.Column(type: "nvarchar(max)", nullable: true), Amount = table.Column(type: "smallint", nullable: false), TotalPrice = table.Column(type: "float", nullable: false), PaymentMethodID = table.Column(type: "int", nullable: false), CustomerID = table.Column(type: "int", nullable: false), - ServiceId = table.Column(type: "int", nullable: true), - LaundryStoreId = table.Column(type: "int", nullable: true), - StaffId = table.Column(type: "int", nullable: true), OrderType = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), @@ -514,27 +479,12 @@ protected override void Up(MigrationBuilder migrationBuilder) principalTable: "Customers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_LaundryStores_LaundryStoreId", - column: x => x.LaundryStoreId, - principalTable: "LaundryStores", - principalColumn: "Id"); table.ForeignKey( name: "FK_Orders_PaymentMethods_PaymentMethodID", column: x => x.PaymentMethodID, principalTable: "PaymentMethods", principalColumn: "Id", onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_Service_ServiceId", - column: x => x.ServiceId, - principalTable: "Service", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Orders_Staffs_StaffId", - column: x => x.StaffId, - principalTable: "Staffs", - principalColumn: "Id"); }); migrationBuilder.CreateTable( @@ -569,15 +519,46 @@ protected override void Up(MigrationBuilder migrationBuilder) principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_Staff_Trips_TimeSchedule_TimeScheduleID", + name: "FK_Staff_Trips_TimeSchedules_TimeScheduleID", column: x => x.TimeScheduleID, - principalTable: "TimeSchedule", + principalTable: "TimeSchedules", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( - name: "OrderHistory", + name: "LaundryStoreOrders", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IsDone = table.Column(type: "bit", nullable: false), + OrderID = table.Column(type: "int", nullable: false), + LaundryStoreID = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_LaundryStoreOrders", x => x.Id); + table.ForeignKey( + name: "FK_LaundryStoreOrders_LaundryStores_LaundryStoreID", + column: x => x.LaundryStoreID, + principalTable: "LaundryStores", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_LaundryStoreOrders_Orders_OrderID", + column: x => x.OrderID, + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OrdersHistory", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -591,15 +572,47 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_OrderHistory", x => x.Id); + table.PrimaryKey("PK_OrdersHistory", x => x.Id); table.ForeignKey( - name: "FK_OrderHistory_Orders_OrderID", + name: "FK_OrdersHistory_Orders_OrderID", column: x => x.OrderID, principalTable: "Orders", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "StaffOrders", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IsDone = table.Column(type: "bit", nullable: false), + Type = table.Column(type: "int", nullable: false), + StaffID = table.Column(type: "int", nullable: false), + OrderID = table.Column(type: "int", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastModified = table.Column(type: "datetime2", nullable: true), + LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_StaffOrders", x => x.Id); + table.ForeignKey( + name: "FK_StaffOrders_Orders_OrderID", + column: x => x.OrderID, + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_StaffOrders_Staffs_StaffID", + column: x => x.StaffID, + principalTable: "Staffs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", @@ -632,6 +645,12 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "AspNetUsers", column: "NormalizedEmail"); + migrationBuilder.CreateIndex( + name: "IX_AspNetUsers_WalletID", + table: "AspNetUsers", + column: "WalletID", + unique: true); + migrationBuilder.CreateIndex( name: "UserNameIndex", table: "AspNetUsers", @@ -649,12 +668,6 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "Customers", column: "BuildingID"); - migrationBuilder.CreateIndex( - name: "IX_Customers_WalletID", - table: "Customers", - column: "WalletID", - unique: true); - migrationBuilder.CreateIndex( name: "IX_DeviceCodes_DeviceCode", table: "DeviceCodes", @@ -672,45 +685,34 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "Use"); migrationBuilder.CreateIndex( - name: "IX_LaundryStores_ApplicationUserID", - table: "LaundryStores", - column: "ApplicationUserID"); + name: "IX_LaundryStoreOrders_LaundryStoreID", + table: "LaundryStoreOrders", + column: "LaundryStoreID"); migrationBuilder.CreateIndex( - name: "IX_LaundryStores_WalletID", - table: "LaundryStores", - column: "WalletID", - unique: true); + name: "IX_LaundryStoreOrders_OrderID", + table: "LaundryStoreOrders", + column: "OrderID"); migrationBuilder.CreateIndex( - name: "IX_OrderHistory_OrderID", - table: "OrderHistory", - column: "OrderID"); + name: "IX_LaundryStores_ApplicationUserID", + table: "LaundryStores", + column: "ApplicationUserID"); migrationBuilder.CreateIndex( name: "IX_Orders_CustomerID", table: "Orders", column: "CustomerID"); - migrationBuilder.CreateIndex( - name: "IX_Orders_LaundryStoreId", - table: "Orders", - column: "LaundryStoreId"); - migrationBuilder.CreateIndex( name: "IX_Orders_PaymentMethodID", table: "Orders", column: "PaymentMethodID"); migrationBuilder.CreateIndex( - name: "IX_Orders_ServiceId", - table: "Orders", - column: "ServiceId"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_StaffId", - table: "Orders", - column: "StaffId"); + name: "IX_OrdersHistory_OrderID", + table: "OrdersHistory", + column: "OrderID"); migrationBuilder.CreateIndex( name: "IX_PersistedGrants_ConsumedTime", @@ -745,19 +747,22 @@ protected override void Up(MigrationBuilder migrationBuilder) migrationBuilder.CreateIndex( name: "IX_Staff_Trips_TimeScheduleID", table: "Staff_Trips", - column: "TimeScheduleID", - unique: true); + column: "TimeScheduleID"); migrationBuilder.CreateIndex( - name: "IX_Staffs_ApplicationUserID", - table: "Staffs", - column: "ApplicationUserID"); + name: "IX_StaffOrders_OrderID", + table: "StaffOrders", + column: "OrderID"); + + migrationBuilder.CreateIndex( + name: "IX_StaffOrders_StaffID", + table: "StaffOrders", + column: "StaffID"); migrationBuilder.CreateIndex( - name: "IX_Staffs_WalletID", + name: "IX_Staffs_ApplicationUserID", table: "Staffs", - column: "WalletID", - unique: true); + column: "ApplicationUserID"); migrationBuilder.CreateIndex( name: "IX_TodoItems_ListId", @@ -795,7 +800,10 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "Keys"); migrationBuilder.DropTable( - name: "OrderHistory"); + name: "LaundryStoreOrders"); + + migrationBuilder.DropTable( + name: "OrdersHistory"); migrationBuilder.DropTable( name: "PersistedGrants"); @@ -803,6 +811,9 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "Staff_Trips"); + migrationBuilder.DropTable( + name: "StaffOrders"); + migrationBuilder.DropTable( name: "TodoItems"); @@ -813,35 +824,32 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "AspNetRoles"); migrationBuilder.DropTable( - name: "Orders"); + name: "LaundryStores"); migrationBuilder.DropTable( - name: "TimeSchedule"); + name: "TimeSchedules"); migrationBuilder.DropTable( - name: "TodoLists"); + name: "Orders"); migrationBuilder.DropTable( - name: "Customers"); + name: "Staffs"); migrationBuilder.DropTable( - name: "LaundryStores"); + name: "TodoLists"); migrationBuilder.DropTable( - name: "PaymentMethods"); + name: "Customers"); migrationBuilder.DropTable( - name: "Service"); + name: "PaymentMethods"); migrationBuilder.DropTable( - name: "Staffs"); + name: "AspNetUsers"); migrationBuilder.DropTable( name: "Buildings"); - migrationBuilder.DropTable( - name: "AspNetUsers"); - migrationBuilder.DropTable( name: "Wallets"); } diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index c64d9cf..b43a049 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -360,18 +360,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("WalletID") - .HasColumnType("int"); - b.HasKey("Id"); b.HasIndex("ApplicationUserID"); b.HasIndex("BuildingID"); - b.HasIndex("WalletID") - .IsUnique(); - b.ToTable("Customers"); }); @@ -413,17 +407,49 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Status") .HasColumnType("bit"); - b.Property("WalletID") + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDone") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LaundryStoreID") + .HasColumnType("int"); + + b.Property("OrderID") .HasColumnType("int"); b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); + b.HasIndex("LaundryStoreID"); - b.HasIndex("WalletID") - .IsUnique(); + b.HasIndex("OrderID"); - b.ToTable("LaundryStores"); + b.ToTable("LaundryStoreOrders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => @@ -458,9 +484,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("LaundryStoreId") - .HasColumnType("int"); - b.Property("OrderDate") .HasColumnType("datetime2"); @@ -470,13 +493,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); - b.Property("ServiceId") - .HasColumnType("int"); - - b.Property("ShipDate") - .HasColumnType("datetime2"); - - b.Property("StaffId") + b.Property("TimeFrame") .HasColumnType("int"); b.Property("TotalPrice") @@ -486,14 +503,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("CustomerID"); - b.HasIndex("LaundryStoreId"); - b.HasIndex("PaymentMethodID"); - b.HasIndex("ServiceId"); - - b.HasIndex("StaffId"); - b.ToTable("Orders"); }); @@ -527,7 +538,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("OrderID"); - b.ToTable("OrderHistory"); + b.ToTable("OrdersHistory"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => @@ -553,15 +564,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("PaymentType") - .HasColumnType("int"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); b.ToTable("PaymentMethods"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -569,14 +580,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); - b.Property("Description") - .HasColumnType("nvarchar(max)"); + b.Property("Dob") + .HasColumnType("datetime2"); b.Property("LastModified") .HasColumnType("datetime2"); @@ -584,18 +601,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("Price") + b.Property("Salary") .HasColumnType("float"); b.HasKey("Id"); - b.ToTable("Service"); + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -603,38 +619,37 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - b.Property("Created") .HasColumnType("datetime2"); b.Property("CreatedBy") .HasColumnType("nvarchar(max)"); + b.Property("IsDone") + .HasColumnType("bit"); + b.Property("LastModified") .HasColumnType("datetime2"); b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("Salary") - .HasColumnType("float"); + b.Property("OrderID") + .HasColumnType("int"); - b.Property("StaffRole") + b.Property("StaffID") .HasColumnType("int"); - b.Property("WalletID") + b.Property("Type") .HasColumnType("int"); b.HasKey("Id"); - b.HasIndex("ApplicationUserID"); + b.HasIndex("OrderID"); - b.HasIndex("WalletID") - .IsUnique(); + b.HasIndex("StaffID"); - b.ToTable("Staffs"); + b.ToTable("StaffOrders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => @@ -678,8 +693,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("StaffID"); - b.HasIndex("TimeScheduleID") - .IsUnique(); + b.HasIndex("TimeScheduleID"); b.ToTable("Staff_Trips"); }); @@ -718,7 +732,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("TimeSchedule"); + b.ToTable("TimeSchedules"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => @@ -926,6 +940,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(256) .HasColumnType("nvarchar(256)"); + b.Property("WalletID") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("NormalizedEmail") @@ -936,6 +953,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); + b.HasIndex("WalletID") + .IsUnique(); + b.ToTable("AspNetUsers", (string)null); }); @@ -1002,17 +1022,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("Customer") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Customer", "WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.Navigation("ApplicationUser"); b.Navigation("Building"); - - b.Navigation("Wallet"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => @@ -1021,52 +1033,45 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("LaundryStore") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "WalletID") + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") + .WithMany() + .HasForeignKey("LaundryStoreID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("ApplicationUser"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") + .WithMany() + .HasForeignKey("OrderID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Wallet"); + b.Navigation("LaundryStore"); + + b.Navigation("Order"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") - .WithMany() + .WithMany("Order") .HasForeignKey("CustomerID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany("Orders") - .HasForeignKey("LaundryStoreId"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") .WithMany("Orders") .HasForeignKey("PaymentMethodID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", "Service") - .WithMany("Order") - .HasForeignKey("ServiceId"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Order") - .HasForeignKey("StaffId"); - b.Navigation("Customer"); - b.Navigation("LaundryStore"); - b.Navigation("PaymentMethod"); - - b.Navigation("Service"); - - b.Navigation("Staff"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => @@ -1086,15 +1091,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("Staff") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff", "WalletID") + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") + .WithMany("StaffOrders") + .HasForeignKey("OrderID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("ApplicationUser"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") + .WithMany("StaffOrders") + .HasForeignKey("StaffID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("Wallet"); + b.Navigation("Order"); + + b.Navigation("Staff"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => @@ -1112,8 +1128,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") - .WithOne("Staff_Trip") - .HasForeignKey("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", "TimeScheduleID") + .WithMany("Staff_Trip") + .HasForeignKey("TimeScheduleID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -1169,6 +1185,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Wallet"); }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "WalletID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Wallet"); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => { b.Navigation("Customers"); @@ -1176,14 +1203,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Staff_Trips"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => + modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => { - b.Navigation("Orders"); + b.Navigation("Order"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.Navigation("OrderHistories"); + + b.Navigation("StaffOrders"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => @@ -1191,22 +1220,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Orders"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Navigation("Order"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { - b.Navigation("Order"); + b.Navigation("StaffOrders"); b.Navigation("Staff_Trips"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => { - b.Navigation("Staff_Trip") - .IsRequired(); + b.Navigation("Staff_Trip"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => @@ -1216,11 +1239,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => { - b.Navigation("Customer"); - - b.Navigation("LaundryStore"); - - b.Navigation("Staff"); + b.Navigation("ApplicationUser"); b.Navigation("Transactions"); }); diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index c6169ce..7d6d6a8 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -33,13 +33,15 @@ public ApplicationDbContext( public DbSet TodoItems => Set(); + public DbSet TimeSchedules => Set(); public DbSet ApplicationUsers => Set(); - + public DbSet LaundryStoreOrders => Set(); + public DbSet StaffOrders => Set(); public DbSet Buildings => Set(); public DbSet Customers => Set(); public DbSet LaundryStores => Set(); public DbSet Orders => Set(); - public DbSet OrderHistory => Set(); + public DbSet OrdersHistory => Set(); public DbSet PaymentMethods => Set(); public DbSet Staff_Trips => Set(); public DbSet Staffs => Set(); From f938a654f11a4abf9967b35265ae7542b1fb08b3 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Fri, 22 Sep 2023 19:28:01 +0700 Subject: [PATCH 15/53] Complete remove Domain.Validate --- src/Domain/Entities/LaundryStore.cs | 1 - src/Domain/Entities/OrderHistory.cs | 1 - src/Domain/Entities/Staff_Trip.cs | 3 - src/Domain/Entities/Validation/Validate.cs | 150 ++++++++++----------- 4 files changed, 75 insertions(+), 80 deletions(-) diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs index 35ac678..a29ad13 100644 --- a/src/Domain/Entities/LaundryStore.cs +++ b/src/Domain/Entities/LaundryStore.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.Entities.Validation; using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Domain.Entities; diff --git a/src/Domain/Entities/OrderHistory.cs b/src/Domain/Entities/OrderHistory.cs index 9e7c13d..0f8115b 100644 --- a/src/Domain/Entities/OrderHistory.cs +++ b/src/Domain/Entities/OrderHistory.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.Entities.Validation; namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable diff --git a/src/Domain/Entities/Staff_Trip.cs b/src/Domain/Entities/Staff_Trip.cs index 260c96b..edc23f0 100644 --- a/src/Domain/Entities/Staff_Trip.cs +++ b/src/Domain/Entities/Staff_Trip.cs @@ -1,7 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; -using SWD_Laundry_Backend.Domain.Entities.Validation; - namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable diff --git a/src/Domain/Entities/Validation/Validate.cs b/src/Domain/Entities/Validation/Validate.cs index 32b1227..1687108 100644 --- a/src/Domain/Entities/Validation/Validate.cs +++ b/src/Domain/Entities/Validation/Validate.cs @@ -1,78 +1,78 @@ -using System.Text.RegularExpressions; +//using System.Text.RegularExpressions; -namespace SWD_Laundry_Backend.Domain.Entities.Validation; +//namespace SWD_Laundry_Backend.Domain.Entities.Validation; -public class Validate -{ +//public class Validate +//{ - public bool IsValidStaffRole(string roleName) - { - return StaffRole.Contains(roleName); - } - - public bool IsValidTransactionType(string type) - { - return AllowedTransactionType.Contains(type); - } - - public bool IsValidTransactionStatus(string status) - { - return Status.Contains(status); - } - - public bool IsValidPhone(string phone) - { - string pattern = @"^(09|01)\d{8,9}$"; - return Regex.IsMatch(phone, pattern); - } - - public bool IsValidEmail(string email) - { - string pattern = @"^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$"; - return Regex.IsMatch(email, pattern); - } - - public bool IsValidTripStatus(string status) - { - return Status.Contains(status); - } - - public bool IsValidPayment(string payment) - { - return Payment.Contains(payment); - } - - public bool IsValidOrderType(string value) - { - return OrderType.Contains(value); - } - - //======================================================= - private readonly string[] OrderType = new string[] - { - "ONEWAY","TWOWAY" - }; - - private readonly string[] Payment = new string[] - { - "CASH","PAYPAL" - }; - private readonly string[] Status = new string[] - { - "FINISHED","PROCESSING","CANCELLED" - }; - - - private readonly string[] StaffRole = new string[] - { - "COLLECTOR","RECEIVER" - }; - - - private readonly string[] AllowedTransactionType = new string[] - { - "DEPOSIT","WITHDRAWAL", "DEBT", "PAID" - }; - - -} \ No newline at end of file +// public bool IsValidStaffRole(string roleName) +// { +// return StaffRole.Contains(roleName); +// } + +// public bool IsValidTransactionType(string type) +// { +// return AllowedTransactionType.Contains(type); +// } + +// public bool IsValidTransactionStatus(string status) +// { +// return Status.Contains(status); +// } + +// public bool IsValidPhone(string phone) +// { +// string pattern = @"^(09|01)\d{8,9}$"; +// return Regex.IsMatch(phone, pattern); +// } + +// public bool IsValidEmail(string email) +// { +// string pattern = @"^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$"; +// return Regex.IsMatch(email, pattern); +// } + +// public bool IsValidTripStatus(string status) +// { +// return Status.Contains(status); +// } + +// public bool IsValidPayment(string payment) +// { +// return Payment.Contains(payment); +// } + +// public bool IsValidOrderType(string value) +// { +// return OrderType.Contains(value); +// } + +// //======================================================= +// private readonly string[] OrderType = new string[] +// { +// "ONEWAY","TWOWAY" +// }; + +// private readonly string[] Payment = new string[] +// { +// "CASH","PAYPAL" +// }; +// private readonly string[] Status = new string[] +// { +// "FINISHED","PROCESSING","CANCELLED" +// }; + + +// private readonly string[] StaffRole = new string[] +// { +// "COLLECTOR","RECEIVER" +// }; + + +// private readonly string[] AllowedTransactionType = new string[] +// { +// "DEPOSIT","WITHDRAWAL", "DEBT", "PAID" +// }; + + +//} \ No newline at end of file From d9fa63a74de3b4b8543d343c1f4dfb38442166f4 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sat, 23 Sep 2023 03:03:22 +0700 Subject: [PATCH 16/53] minor update --- src/Application/Application.csproj | 3 +- .../Customers/Queries/CustomerVm.cs | 17 +++++++++ .../Customers/Queries/GetAllCustomerQuery.cs | 10 +++++ .../Customers/Queries/GetCustomerQuery.cs | 37 +++++++++++++++++++ .../CreatePaymentMethodCommandValdiator.cs | 14 +++++++ .../DeletePaymentMethodCommand.cs | 26 +++++++++++++ .../UpdatePaymentMethodCommand.cs | 31 ++++++++++++++++ .../UpdatePaymentMethodCommandValidator.cs | 13 +++++++ .../PaymentMethods/Queries/PaymentMethodVm.cs | 6 --- .../PaymentMethods/Queries/PaymentTypeDto.cs | 6 --- src/Domain/Entities/StaffOrder.cs | 7 +--- src/Domain/IdentityModel/ApplicationRole.cs | 7 +--- 12 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 src/Application/Customers/Queries/CustomerVm.cs create mode 100644 src/Application/Customers/Queries/GetAllCustomerQuery.cs create mode 100644 src/Application/Customers/Queries/GetCustomerQuery.cs create mode 100644 src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs create mode 100644 src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs create mode 100644 src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs create mode 100644 src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs delete mode 100644 src/Application/PaymentMethods/Queries/PaymentMethodVm.cs delete mode 100644 src/Application/PaymentMethods/Queries/PaymentTypeDto.cs diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index fb6ef03..b43adc4 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -19,8 +19,7 @@ - - + diff --git a/src/Application/Customers/Queries/CustomerVm.cs b/src/Application/Customers/Queries/CustomerVm.cs new file mode 100644 index 0000000..322436c --- /dev/null +++ b/src/Application/Customers/Queries/CustomerVm.cs @@ -0,0 +1,17 @@ +using SWD_Laundry_Backend.Application.Common.Mappings; +using SWD_Laundry_Backend.Domain.Entities; +using SWD_Laundry_Backend.Domain.IdentityModel; + +namespace SWD_Laundry_Backend.Application.Customers.Queries; +public class CustomerVm : IMapFrom +{ + public int BuildingID { get; set; } + + public string ApplicationUserID { get; set; } + + public Building Building { get; set; } + + public ApplicationUser ApplicationUser { get; set; } + public virtual List Order { get; set; } + +} diff --git a/src/Application/Customers/Queries/GetAllCustomerQuery.cs b/src/Application/Customers/Queries/GetAllCustomerQuery.cs new file mode 100644 index 0000000..fe39af7 --- /dev/null +++ b/src/Application/Customers/Queries/GetAllCustomerQuery.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Application.Customers.Queries; +internal class GetAllCustomerQuery +{ +} diff --git a/src/Application/Customers/Queries/GetCustomerQuery.cs b/src/Application/Customers/Queries/GetCustomerQuery.cs new file mode 100644 index 0000000..4c59019 --- /dev/null +++ b/src/Application/Customers/Queries/GetCustomerQuery.cs @@ -0,0 +1,37 @@ +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; + +namespace SWD_Laundry_Backend.Application.Customers.Queries; +public class GetCustomerQuery : IRequest +{ + public int Id { get; set; } = 0; + public string? UserName { get; set; } + public string? UserId { get; set; } + +} + +public class GetCustomerQueryHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public GetCustomerQueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(GetCustomerQuery request, CancellationToken cancellationToken) + { + var customers = await _context.Get() + .Include(x => x.ApplicationUser) + .AsNoTracking() + .Where(x => x.Id == request.Id || x.ApplicationUser.UserName == request.UserName || x.ApplicationUser.Id == request.UserId) + .FirstOrDefaultAsync(cancellationToken); + + return _mapper.Map(customers); + } + +} \ No newline at end of file diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs new file mode 100644 index 0000000..41cfc02 --- /dev/null +++ b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs @@ -0,0 +1,14 @@ +using FluentValidation; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; +public class CreatePaymentMethodCommandValdiator : AbstractValidator +{ + + public CreatePaymentMethodCommandValdiator() + { + RuleFor(v => v.Name) + .MaximumLength(200) + .NotEmpty(); + RuleFor(v => v.Description); + } +} diff --git a/src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs new file mode 100644 index 0000000..0ce288f --- /dev/null +++ b/src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs @@ -0,0 +1,26 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.DeletePaymentMethod; +public class DeletePaymentMethodCommand : IRequest +{ + public int Id { get; set; } +} + +public class DeletePaymentMethodCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public DeletePaymentMethodCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(DeletePaymentMethodCommand request, CancellationToken cancellationToken) + { + int affectedRows = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken: cancellationToken); + return affectedRows; + } +} diff --git a/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs new file mode 100644 index 0000000..274eae4 --- /dev/null +++ b/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs @@ -0,0 +1,31 @@ +using MediatR; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Application.Common.Interfaces; +using SWD_Laundry_Backend.Domain.Entities; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.UpdatePaymentMethod; +public class UpdatePaymentMethodCommand : IRequest +{ + public int Id { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } +} + +public class UpdatePaymentMethodCommandHandler : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public UpdatePaymentMethodCommandHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task Handle(UpdatePaymentMethodCommand request, CancellationToken cancellationToken) + { + int affectedRows = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => + x.SetProperty(p => p.Name, p => request.Name ?? p.Name) + .SetProperty(p => p.Description, p => request.Description ?? p.Name)); + return affectedRows; + } +} + diff --git a/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs b/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs new file mode 100644 index 0000000..27fb3f6 --- /dev/null +++ b/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs @@ -0,0 +1,13 @@ +using FluentValidation; + +namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.UpdatePaymentMethod; +public class UpdatePaymentMethodCommandValidator : AbstractValidator +{ + public UpdatePaymentMethodCommandValidator() + { + RuleFor(v => v.Name) + .MaximumLength(200) + .NotEmpty(); + RuleFor(v => v.Description); + } +} diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs b/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs deleted file mode 100644 index b2c903d..0000000 --- a/src/Application/PaymentMethods/Queries/PaymentMethodVm.cs +++ /dev/null @@ -1,6 +0,0 @@ -//namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -//public class PaymentMethodVm -//{ -// public required IReadOnlyCollection PaymentTypes { get; init; } = Array.Empty(); -// public required dynamic PaymentMethods { get; init; } -//} diff --git a/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs b/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs deleted file mode 100644 index c7f23d3..0000000 --- a/src/Application/PaymentMethods/Queries/PaymentTypeDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -//namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -//public class PaymentTypeDto -//{ -// public int Value { get; init; } -// public string? Name { get; init; } -//} diff --git a/src/Domain/Entities/StaffOrder.cs b/src/Domain/Entities/StaffOrder.cs index c3ae50c..1ab6693 100644 --- a/src/Domain/Entities/StaffOrder.cs +++ b/src/Domain/Entities/StaffOrder.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations.Schema; namespace SWD_Laundry_Backend.Domain.Entities; #nullable disable diff --git a/src/Domain/IdentityModel/ApplicationRole.cs b/src/Domain/IdentityModel/ApplicationRole.cs index ef26b50..86cdb24 100644 --- a/src/Domain/IdentityModel/ApplicationRole.cs +++ b/src/Domain/IdentityModel/ApplicationRole.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity; namespace SWD_Laundry_Backend.Domain.IdentityModel; From 154d75f94bd12efd455d2fd12bfbf2c5c5ca8290 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Wed, 27 Sep 2023 02:00:03 +0700 Subject: [PATCH 17/53] Update database5 --- .../Buildings/Queries/BuildingViewModel.cs | 6 +- .../Interfaces/IApplicationDbContext.cs | 3 +- .../CreatePaymentMethodCommand.cs | 4 +- .../Queries/PaymentMethodDto.cs | 2 +- src/Domain/Entities/LaundryService.cs | 25 +++++++ src/Domain/Entities/LaundryStore.cs | 2 +- src/Domain/Entities/Order.cs | 2 +- src/Domain/Entities/PaymentMethod.cs | 12 +--- src/Domain/Entities/Service.cs | 4 +- ...0230920073700_UpdateDatabase4.Designer.cs} | 66 ++++++++++-------- ...3.cs => 20230920073700_UpdateDatabase4.cs} | 68 ++++++++++++------- .../ApplicationDbContextModelSnapshot.cs | 62 +++++++++-------- .../Persistence/ApplicationDbContext.cs | 2 +- 13 files changed, 153 insertions(+), 105 deletions(-) create mode 100644 src/Domain/Entities/LaundryService.cs rename src/Infrastructure/Migrations/{20230919183842_UpdateDatabase3.Designer.cs => 20230920073700_UpdateDatabase4.Designer.cs} (97%) rename src/Infrastructure/Migrations/{20230919183842_UpdateDatabase3.cs => 20230920073700_UpdateDatabase4.cs} (95%) diff --git a/src/Application/Buildings/Queries/BuildingViewModel.cs b/src/Application/Buildings/Queries/BuildingViewModel.cs index 590af13..03657a7 100644 --- a/src/Application/Buildings/Queries/BuildingViewModel.cs +++ b/src/Application/Buildings/Queries/BuildingViewModel.cs @@ -4,7 +4,7 @@ namespace SWD_Laundry_Backend.Application.Buildings.Queries; public class BuildingViewModel : IMapFrom { - public string Name { get; set; } - public string Address { get; set; } - public string Description { get; set; } + public string? Name { get; set; } + public string? Address { get; set; } + public string? Description { get; set; } } diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index be24d29..2b229f9 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -15,12 +15,13 @@ public interface IApplicationDbContext DbSet ApplicationUsers { get; } DbSet LaundryStores { get; } DbSet Orders { get; } - DbSet OrdersHistory { get; } + DbSet OrdersHistory{ get; } DbSet PaymentMethods { get; } DbSet Staff_Trips { get; } DbSet Staffs { get; } DbSet Transactions { get; } DbSet Wallets { get; } + DbSet Get() where T : BaseAuditableEntity; diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs index b67439e..e608eaf 100644 --- a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs +++ b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs @@ -6,8 +6,8 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; public class CreatePaymentMethodCommand : IRequest { - public string Name { get; set; } - public string Description { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } } public class CreatePaymentMethodCommandHandler : IRequestHandler diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs index b282b1d..b255489 100644 --- a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs +++ b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs @@ -5,6 +5,6 @@ namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; public class PaymentMethodDto : IMapFrom { - public string Name { get; init; } + public string? Name { get; init; } public string? Description { get; set; } } diff --git a/src/Domain/Entities/LaundryService.cs b/src/Domain/Entities/LaundryService.cs new file mode 100644 index 0000000..fc4fb54 --- /dev/null +++ b/src/Domain/Entities/LaundryService.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Domain.Entities; + +public class LaundryService : BaseAuditableEntity +{ + public double Price { get; set; } + #region Relationship + + [ForeignKey(nameof(LaundryStore))] + public int LaundryId { get; set; } + + [ForeignKey(nameof(LaundryStore))] + public int ServiceId { get; set; } + + public LaundryStore? LaundryStore { get; set; } + public Service? Service { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs index fe8f488..5bf41a2 100644 --- a/src/Domain/Entities/LaundryStore.cs +++ b/src/Domain/Entities/LaundryStore.cs @@ -26,7 +26,7 @@ public class LaundryStore : BaseAuditableEntity public Wallet Wallet { get; set; } - public virtual List Orders { get; set; } + public virtual List Services { get; set; } #endregion Relationship } \ No newline at end of file diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs index b228f8a..32ff840 100644 --- a/src/Domain/Entities/Order.cs +++ b/src/Domain/Entities/Order.cs @@ -34,7 +34,7 @@ public class Order : BaseAuditableEntity //public int ServiceID { get; set; } ////=========================== - public Service Service { get; set; } + //public Service Service { get; set; } public virtual LaundryStore LaundryStore { get; set; } public virtual Customer Customer { get; set; } diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs index 6b2ee74..4b6b79e 100644 --- a/src/Domain/Entities/PaymentMethod.cs +++ b/src/Domain/Entities/PaymentMethod.cs @@ -13,16 +13,6 @@ public class PaymentMethod : BaseAuditableEntity #region Special Attributes - - //public string PaymentType - //{ - // get { return _type; } - // set - // { - // _type = new Validate().IsValidPayment(value) - // ? value - // : throw new ArgumentException("Invalid payment type{CASH , PAYPAL}."); - // } - //} public string Name { get; set; } + #endregion } \ No newline at end of file diff --git a/src/Domain/Entities/Service.cs b/src/Domain/Entities/Service.cs index 21146d4..939c895 100644 --- a/src/Domain/Entities/Service.cs +++ b/src/Domain/Entities/Service.cs @@ -11,11 +11,11 @@ public class Service : BaseAuditableEntity { public string Name { get; set; } public string Description { get; set; } - public double Price { get; set; } + //public double Price { get; set; } #region Relationship - public List Order { get; set; } + public List LaundryStores{ get; set; } #endregion Relationship } \ No newline at end of file diff --git a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs b/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs similarity index 97% rename from src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs rename to src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs index ca49bad..39d9443 100644 --- a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.Designer.cs +++ b/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs @@ -12,8 +12,8 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20230919183842_UpdateDatabase3")] - partial class UpdateDatabase3 + [Migration("20230920073700_UpdateDatabase4")] + partial class UpdateDatabase4 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -166,6 +166,21 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("PersistedGrants", (string)null); }); + modelBuilder.Entity("LaundryStoreService", b => + { + b.Property("LaundryStoresId") + .HasColumnType("int"); + + b.Property("ServicesId") + .HasColumnType("int"); + + b.HasKey("LaundryStoresId", "ServicesId"); + + b.HasIndex("ServicesId"); + + b.ToTable("LaundryStoreService"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") @@ -473,9 +488,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); - b.Property("ServiceId") - .HasColumnType("int"); - b.Property("ShipDate") .HasColumnType("datetime2"); @@ -493,8 +505,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("PaymentMethodID"); - b.HasIndex("ServiceId"); - b.HasIndex("StaffId"); b.ToTable("Orders"); @@ -530,7 +540,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("OrderID"); - b.ToTable("OrderHistory"); + b.ToTable("OrdersHistory"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => @@ -556,8 +566,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("PaymentType") - .HasColumnType("int"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -590,9 +600,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Name") .HasColumnType("nvarchar(max)"); - b.Property("Price") - .HasColumnType("float"); - b.HasKey("Id"); b.ToTable("Service"); @@ -942,6 +949,21 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers", (string)null); }); + modelBuilder.Entity("LaundryStoreService", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", null) + .WithMany() + .HasForeignKey("LaundryStoresId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", null) + .WithMany() + .HasForeignKey("ServicesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -1044,7 +1066,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired(); b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany("Orders") + .WithMany() .HasForeignKey("LaundryStoreId"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") @@ -1053,10 +1075,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", "Service") - .WithMany("Order") - .HasForeignKey("ServiceId"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") .WithMany("Order") .HasForeignKey("StaffId"); @@ -1067,8 +1085,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("PaymentMethod"); - b.Navigation("Service"); - b.Navigation("Staff"); }); @@ -1179,11 +1195,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Staff_Trips"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.Navigation("Orders"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.Navigation("OrderHistories"); @@ -1194,11 +1205,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Orders"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Navigation("Order"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { b.Navigation("Order"); diff --git a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs b/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs similarity index 95% rename from src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs rename to src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs index 0371465..58f323b 100644 --- a/src/Infrastructure/Migrations/20230919183842_UpdateDatabase3.cs +++ b/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs @@ -6,7 +6,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { /// - public partial class UpdateDatabase3 : Migration + public partial class UpdateDatabase4 : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -114,7 +114,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Description = table.Column(type: "nvarchar(max)", nullable: true), - PaymentType = table.Column(type: "int", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -153,7 +153,6 @@ protected override void Up(MigrationBuilder migrationBuilder) .Annotation("SqlServer:Identity", "1, 1"), Name = table.Column(type: "nvarchar(max)", nullable: true), Description = table.Column(type: "nvarchar(max)", nullable: true), - Price = table.Column(type: "float", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -482,6 +481,30 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "LaundryStoreService", + columns: table => new + { + LaundryStoresId = table.Column(type: "int", nullable: false), + ServicesId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LaundryStoreService", x => new { x.LaundryStoresId, x.ServicesId }); + table.ForeignKey( + name: "FK_LaundryStoreService_LaundryStores_LaundryStoresId", + column: x => x.LaundryStoresId, + principalTable: "LaundryStores", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_LaundryStoreService_Service_ServicesId", + column: x => x.ServicesId, + principalTable: "Service", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "Orders", columns: table => new @@ -496,7 +519,6 @@ protected override void Up(MigrationBuilder migrationBuilder) TotalPrice = table.Column(type: "float", nullable: false), PaymentMethodID = table.Column(type: "int", nullable: false), CustomerID = table.Column(type: "int", nullable: false), - ServiceId = table.Column(type: "int", nullable: true), LaundryStoreId = table.Column(type: "int", nullable: true), StaffId = table.Column(type: "int", nullable: true), OrderType = table.Column(type: "int", nullable: false), @@ -525,11 +547,6 @@ protected override void Up(MigrationBuilder migrationBuilder) principalTable: "PaymentMethods", principalColumn: "Id", onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_Service_ServiceId", - column: x => x.ServiceId, - principalTable: "Service", - principalColumn: "Id"); table.ForeignKey( name: "FK_Orders_Staffs_StaffId", column: x => x.StaffId, @@ -577,7 +594,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "OrderHistory", + name: "OrdersHistory", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -591,9 +608,9 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_OrderHistory", x => x.Id); + table.PrimaryKey("PK_OrdersHistory", x => x.Id); table.ForeignKey( - name: "FK_OrderHistory_Orders_OrderID", + name: "FK_OrdersHistory_Orders_OrderID", column: x => x.OrderID, principalTable: "Orders", principalColumn: "Id", @@ -683,9 +700,9 @@ protected override void Up(MigrationBuilder migrationBuilder) unique: true); migrationBuilder.CreateIndex( - name: "IX_OrderHistory_OrderID", - table: "OrderHistory", - column: "OrderID"); + name: "IX_LaundryStoreService_ServicesId", + table: "LaundryStoreService", + column: "ServicesId"); migrationBuilder.CreateIndex( name: "IX_Orders_CustomerID", @@ -702,16 +719,16 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "Orders", column: "PaymentMethodID"); - migrationBuilder.CreateIndex( - name: "IX_Orders_ServiceId", - table: "Orders", - column: "ServiceId"); - migrationBuilder.CreateIndex( name: "IX_Orders_StaffId", table: "Orders", column: "StaffId"); + migrationBuilder.CreateIndex( + name: "IX_OrdersHistory_OrderID", + table: "OrdersHistory", + column: "OrderID"); + migrationBuilder.CreateIndex( name: "IX_PersistedGrants_ConsumedTime", table: "PersistedGrants", @@ -795,7 +812,10 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "Keys"); migrationBuilder.DropTable( - name: "OrderHistory"); + name: "LaundryStoreService"); + + migrationBuilder.DropTable( + name: "OrdersHistory"); migrationBuilder.DropTable( name: "PersistedGrants"); @@ -812,6 +832,9 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "AspNetRoles"); + migrationBuilder.DropTable( + name: "Service"); + migrationBuilder.DropTable( name: "Orders"); @@ -830,9 +853,6 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "PaymentMethods"); - migrationBuilder.DropTable( - name: "Service"); - migrationBuilder.DropTable( name: "Staffs"); diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index c64d9cf..3d19083 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -163,6 +163,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("PersistedGrants", (string)null); }); + modelBuilder.Entity("LaundryStoreService", b => + { + b.Property("LaundryStoresId") + .HasColumnType("int"); + + b.Property("ServicesId") + .HasColumnType("int"); + + b.HasKey("LaundryStoresId", "ServicesId"); + + b.HasIndex("ServicesId"); + + b.ToTable("LaundryStoreService"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") @@ -470,9 +485,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); - b.Property("ServiceId") - .HasColumnType("int"); - b.Property("ShipDate") .HasColumnType("datetime2"); @@ -490,8 +502,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PaymentMethodID"); - b.HasIndex("ServiceId"); - b.HasIndex("StaffId"); b.ToTable("Orders"); @@ -527,7 +537,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("OrderID"); - b.ToTable("OrderHistory"); + b.ToTable("OrdersHistory"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => @@ -553,8 +563,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); - b.Property("PaymentType") - .HasColumnType("int"); + b.Property("Name") + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -587,9 +597,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .HasColumnType("nvarchar(max)"); - b.Property("Price") - .HasColumnType("float"); - b.HasKey("Id"); b.ToTable("Service"); @@ -939,6 +946,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers", (string)null); }); + modelBuilder.Entity("LaundryStoreService", b => + { + b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", null) + .WithMany() + .HasForeignKey("LaundryStoresId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", null) + .WithMany() + .HasForeignKey("ServicesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -1041,7 +1063,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany("Orders") + .WithMany() .HasForeignKey("LaundryStoreId"); b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") @@ -1050,10 +1072,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", "Service") - .WithMany("Order") - .HasForeignKey("ServiceId"); - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") .WithMany("Order") .HasForeignKey("StaffId"); @@ -1064,8 +1082,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("PaymentMethod"); - b.Navigation("Service"); - b.Navigation("Staff"); }); @@ -1176,11 +1192,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Staff_Trips"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.Navigation("Orders"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.Navigation("OrderHistories"); @@ -1191,11 +1202,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Orders"); }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Navigation("Order"); - }); - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { b.Navigation("Order"); diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs index c6169ce..83e1929 100644 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ b/src/Infrastructure/Persistence/ApplicationDbContext.cs @@ -39,7 +39,7 @@ public ApplicationDbContext( public DbSet Customers => Set(); public DbSet LaundryStores => Set(); public DbSet Orders => Set(); - public DbSet OrderHistory => Set(); + public DbSet OrdersHistory => Set(); public DbSet PaymentMethods => Set(); public DbSet Staff_Trips => Set(); public DbSet Staffs => Set(); From c31908836b9ec7cad774be37828c5d316d44cc6c Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Wed, 27 Sep 2023 04:54:02 +0700 Subject: [PATCH 18/53] Fix Migration --- .../Interfaces/IApplicationDbContext.cs | 1 + ...20230922043540_UpdateDatabase5.Designer.cs | 1355 ----------------- .../20230922043540_UpdateDatabase5.cs | 960 ------------ ... 20230926215325_InitMigration.Designer.cs} | 55 +- ...se4.cs => 20230926215325_InitMigration.cs} | 73 +- .../ApplicationDbContextModelSnapshot.cs | 43 +- 6 files changed, 73 insertions(+), 2414 deletions(-) delete mode 100644 src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs rename src/Infrastructure/Migrations/{20230920073700_UpdateDatabase4.Designer.cs => 20230926215325_InitMigration.Designer.cs} (95%) rename src/Infrastructure/Migrations/{20230920073700_UpdateDatabase4.cs => 20230926215325_InitMigration.cs} (94%) diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs index 16b89db..06667cc 100644 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ b/src/Application/Common/Interfaces/IApplicationDbContext.cs @@ -1,6 +1,7 @@ using SWD_Laundry_Backend.Domain.Entities; using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Domain.Common; +using SWD_Laundry_Backend.Domain.IdentityModel; namespace SWD_Laundry_Backend.Application.Common.Interfaces; diff --git a/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs b/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs deleted file mode 100644 index 8ae5451..0000000 --- a/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs +++ /dev/null @@ -1,1355 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SWD_Laundry_Backend.Infrastructure.Persistence; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - [Migration("20230920073700_UpdateDatabase4")] - partial class UpdateDatabase4 -======== - [Migration("20230922043540_UpdateDatabase5")] - partial class UpdateDatabase5 ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("LaundryStoreService", b => - { - b.Property("LaundryStoresId") - .HasColumnType("int"); - - b.Property("ServicesId") - .HasColumnType("int"); - - b.HasKey("LaundryStoresId", "ServicesId"); - - b.HasIndex("ServicesId"); - - b.ToTable("LaundryStoreService"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Buildings"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("BuildingID"); - - b.ToTable("Customers"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("Status") - .HasColumnType("bit"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.ToTable("LaundryStores"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDone") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LaundryStoreID") - .HasColumnType("int"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("LaundryStoreID"); - - b.HasIndex("OrderID"); - - b.ToTable("LaundryStoreOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Amount") - .HasColumnType("smallint"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("CustomerID") - .HasColumnType("int"); - - b.Property("ExpectedFinishDate") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderDate") - .HasColumnType("datetime2"); - - b.Property("OrderType") - .HasColumnType("int"); - - b.Property("PaymentMethodID") - .HasColumnType("int"); - -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - b.Property("ShipDate") - .HasColumnType("datetime2"); - - b.Property("StaffId") -======== - b.Property("TimeFrame") ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - .HasColumnType("int"); - - b.Property("TotalPrice") - .HasColumnType("float"); - - b.HasKey("Id"); - - b.HasIndex("CustomerID"); - - b.HasIndex("PaymentMethodID"); - -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - b.HasIndex("StaffId"); - -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - b.ToTable("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("Status") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.ToTable("OrdersHistory"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("PaymentMethods"); - }); - -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Service"); - }); - -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Dob") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Salary") - .HasColumnType("float"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.ToTable("Staffs"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDone") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.HasIndex("StaffID"); - - b.ToTable("StaffOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("TimeScheduleID") - .HasColumnType("int"); - - b.Property("TripCollect") - .HasColumnType("int"); - - b.Property("TripStatus") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("BuildingID"); - - b.HasIndex("StaffID"); - - b.HasIndex("TimeScheduleID"); - - b.ToTable("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("DayOfWeek") - .HasColumnType("int"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TimeSchedules"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("PaymentMethod") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TransactionType") - .HasColumnType("int"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WalletID"); - - b.ToTable("Transactions"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Balance") - .HasColumnType("float"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Wallets"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.HasIndex("WalletID") - .IsUnique(); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("LaundryStoreService", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", null) - .WithMany() - .HasForeignKey("LaundryStoresId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", null) - .WithMany() - .HasForeignKey("ServicesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany("Customers") - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Building"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.Navigation("ApplicationUser"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany() - .HasForeignKey("LaundryStoreID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany() - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("LaundryStore"); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") - .WithMany("Order") - .HasForeignKey("CustomerID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany() - .HasForeignKey("LaundryStoreId"); - -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") - .WithMany("Orders") - .HasForeignKey("PaymentMethodID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Order") - .HasForeignKey("StaffId"); - -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - b.Navigation("Customer"); - - b.Navigation("PaymentMethod"); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - - b.Navigation("Staff"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany("OrderHistories") - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.Navigation("ApplicationUser"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany("StaffOrders") - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("StaffOrders") - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - - b.Navigation("Staff"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany("Staff_Trips") - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Staff_Trips") - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") - .WithMany("Staff_Trip") - .HasForeignKey("TimeScheduleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Building"); - - b.Navigation("Staff"); - - b.Navigation("TimeSchedule"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.OwnsOne("SWD_Laundry_Backend.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany("Transactions") - .HasForeignKey("WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("ApplicationUser") - .HasForeignKey("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Navigation("Customers"); - - b.Navigation("Staff_Trips"); - }); - -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs -======== - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Navigation("Order"); - }); - ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Navigation("OrderHistories"); - - b.Navigation("StaffOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Navigation("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Navigation("StaffOrders"); - - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => - { - b.Navigation("Staff_Trip"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Navigation("ApplicationUser"); - - b.Navigation("Transactions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs b/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs deleted file mode 100644 index ef4d074..0000000 --- a/src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs +++ /dev/null @@ -1,960 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Migrations -{ - /// -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - public partial class UpdateDatabase4 : Migration -======== - public partial class UpdateDatabase5 : Migration ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Buildings", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Buildings", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: false), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Version = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Use = table.Column(type: "nvarchar(450)", nullable: true), - Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - IsX509Certificate = table.Column(type: "bit", nullable: false), - DataProtected = table.Column(type: "bit", nullable: false), - Data = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PaymentMethods", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_PaymentMethods", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - ConsumedTime = table.Column(type: "datetime2", nullable: true), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - - migrationBuilder.CreateTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "Service", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Service", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "TimeSchedule", -======== - name: "TimeSchedules", ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - StartTime = table.Column(type: "datetime2", nullable: false), - EndTime = table.Column(type: "datetime2", nullable: false), - DayOfWeek = table.Column(type: "int", nullable: false), - TimeFrame = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TimeSchedules", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "TodoLists", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Colour_Code = table.Column(type: "nvarchar(max)", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoLists", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Wallets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Balance = table.Column(type: "float", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Wallets", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ListId = table.Column(type: "int", nullable: false), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Note = table.Column(type: "nvarchar(max)", nullable: true), - Priority = table.Column(type: "int", nullable: false), - Reminder = table.Column(type: "datetime2", nullable: true), - Done = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - table.ForeignKey( - name: "FK_TodoItems_TodoLists_ListId", - column: x => x.ListId, - principalTable: "TodoLists", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUsers_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Transactions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - TransactionType = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Transactions", x => x.Id); - table.ForeignKey( - name: "FK_Transactions_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), - UserId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - RoleId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Customers", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - BuildingID = table.Column(type: "int", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Customers", x => x.Id); - table.ForeignKey( - name: "FK_Customers_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Customers_Buildings_BuildingID", - column: x => x.BuildingID, - principalTable: "Buildings", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "LaundryStores", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Address = table.Column(type: "nvarchar(max)", nullable: true), - StartTime = table.Column(type: "datetime2", nullable: false), - EndTime = table.Column(type: "datetime2", nullable: false), - Status = table.Column(type: "bit", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStores", x => x.Id); - table.ForeignKey( - name: "FK_LaundryStores_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "Staffs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Dob = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Salary = table.Column(type: "float", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Staffs", x => x.Id); - table.ForeignKey( - name: "FK_Staffs_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "LaundryStoreService", - columns: table => new - { - LaundryStoresId = table.Column(type: "int", nullable: false), - ServicesId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStoreService", x => new { x.LaundryStoresId, x.ServicesId }); - table.ForeignKey( - name: "FK_LaundryStoreService_LaundryStores_LaundryStoresId", - column: x => x.LaundryStoresId, - principalTable: "LaundryStores", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_LaundryStoreService_Service_ServicesId", - column: x => x.ServicesId, - principalTable: "Service", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Orders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderDate = table.Column(type: "datetime2", nullable: false), - TimeFrame = table.Column(type: "int", nullable: false), - ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "smallint", nullable: false), - TotalPrice = table.Column(type: "float", nullable: false), - PaymentMethodID = table.Column(type: "int", nullable: false), - CustomerID = table.Column(type: "int", nullable: false), -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - LaundryStoreId = table.Column(type: "int", nullable: true), - StaffId = table.Column(type: "int", nullable: true), -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - OrderType = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Orders", x => x.Id); - table.ForeignKey( - name: "FK_Orders_Customers_CustomerID", - column: x => x.CustomerID, - principalTable: "Customers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_PaymentMethods_PaymentMethodID", - column: x => x.PaymentMethodID, - principalTable: "PaymentMethods", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - table.ForeignKey( - name: "FK_Orders_Staffs_StaffId", - column: x => x.StaffId, - principalTable: "Staffs", - principalColumn: "Id"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - }); - - migrationBuilder.CreateTable( - name: "Staff_Trips", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - TripCollect = table.Column(type: "int", nullable: false), - StaffID = table.Column(type: "int", nullable: false), - TimeScheduleID = table.Column(type: "int", nullable: false), - BuildingID = table.Column(type: "int", nullable: false), - TripStatus = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Staff_Trips", x => x.Id); - table.ForeignKey( - name: "FK_Staff_Trips_Buildings_BuildingID", - column: x => x.BuildingID, - principalTable: "Buildings", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Staff_Trips_Staffs_StaffID", - column: x => x.StaffID, - principalTable: "Staffs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Staff_Trips_TimeSchedules_TimeScheduleID", - column: x => x.TimeScheduleID, - principalTable: "TimeSchedules", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs -======== - name: "LaundryStoreOrders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IsDone = table.Column(type: "bit", nullable: false), - OrderID = table.Column(type: "int", nullable: false), - LaundryStoreID = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStoreOrders", x => x.Id); - table.ForeignKey( - name: "FK_LaundryStoreOrders_LaundryStores_LaundryStoreID", - column: x => x.LaundryStoreID, - principalTable: "LaundryStores", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_LaundryStoreOrders_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - name: "OrdersHistory", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderID = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OrdersHistory", x => x.Id); - table.ForeignKey( - name: "FK_OrdersHistory_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "StaffOrders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IsDone = table.Column(type: "bit", nullable: false), - Type = table.Column(type: "int", nullable: false), - StaffID = table.Column(type: "int", nullable: false), - OrderID = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_StaffOrders", x => x.Id); - table.ForeignKey( - name: "FK_StaffOrders_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_StaffOrders_Staffs_StaffID", - column: x => x.StaffID, - principalTable: "Staffs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUsers_WalletID", - table: "AspNetUsers", - column: "WalletID", - unique: true); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_Customers_ApplicationUserID", - table: "Customers", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_Customers_BuildingID", - table: "Customers", - column: "BuildingID"); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStoreOrders_LaundryStoreID", - table: "LaundryStoreOrders", - column: "LaundryStoreID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStoreOrders_OrderID", - table: "LaundryStoreOrders", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStores_ApplicationUserID", - table: "LaundryStores", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "IX_LaundryStores_WalletID", - table: "LaundryStores", - column: "WalletID", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStoreService_ServicesId", - table: "LaundryStoreService", - column: "ServicesId"); - - migrationBuilder.CreateIndex( -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - name: "IX_Orders_CustomerID", - table: "Orders", - column: "CustomerID"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_PaymentMethodID", - table: "Orders", - column: "PaymentMethodID"); - - migrationBuilder.CreateIndex( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "IX_Orders_StaffId", - table: "Orders", - column: "StaffId"); -======== - name: "IX_OrdersHistory_OrderID", - table: "OrdersHistory", - column: "OrderID"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - - migrationBuilder.CreateIndex( - name: "IX_OrdersHistory_OrderID", - table: "OrdersHistory", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_Staff_Trips_BuildingID", - table: "Staff_Trips", - column: "BuildingID"); - - migrationBuilder.CreateIndex( - name: "IX_Staff_Trips_StaffID", - table: "Staff_Trips", - column: "StaffID"); - - migrationBuilder.CreateIndex( - name: "IX_Staff_Trips_TimeScheduleID", - table: "Staff_Trips", - column: "TimeScheduleID"); - - migrationBuilder.CreateIndex( - name: "IX_StaffOrders_OrderID", - table: "StaffOrders", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_StaffOrders_StaffID", - table: "StaffOrders", - column: "StaffID"); - - migrationBuilder.CreateIndex( - name: "IX_Staffs_ApplicationUserID", - table: "Staffs", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_TodoItems_ListId", - table: "TodoItems", - column: "ListId"); - - migrationBuilder.CreateIndex( - name: "IX_Transactions_WalletID", - table: "Transactions", - column: "WalletID"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - - migrationBuilder.DropTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "LaundryStoreService"); -======== - name: "LaundryStoreOrders"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - - migrationBuilder.DropTable( - name: "OrdersHistory"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - - migrationBuilder.DropTable( - name: "Staff_Trips"); - - migrationBuilder.DropTable( - name: "StaffOrders"); - - migrationBuilder.DropTable( - name: "TodoItems"); - - migrationBuilder.DropTable( - name: "Transactions"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "Service"); -======== - name: "LaundryStores"); - - migrationBuilder.DropTable( - name: "TimeSchedules"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - - migrationBuilder.DropTable( - name: "Orders"); - - migrationBuilder.DropTable( - name: "Staffs"); - - migrationBuilder.DropTable( - name: "TodoLists"); - - migrationBuilder.DropTable( - name: "Customers"); - - migrationBuilder.DropTable( - name: "PaymentMethods"); - - migrationBuilder.DropTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "Staffs"); -======== - name: "AspNetUsers"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs - - migrationBuilder.DropTable( - name: "Buildings"); - - migrationBuilder.DropTable( - name: "Wallets"); - } - } -} diff --git a/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs b/src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs similarity index 95% rename from src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs rename to src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs index 8ae5451..388ad39 100644 --- a/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs +++ b/src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs @@ -12,13 +12,8 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - [Migration("20230920073700_UpdateDatabase4")] - partial class UpdateDatabase4 -======== - [Migration("20230922043540_UpdateDatabase5")] - partial class UpdateDatabase5 ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs + [Migration("20230926215325_InitMigration")] + partial class InitMigration { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -430,10 +425,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("Status") .HasColumnType("bit"); + b.Property("WalletId") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("ApplicationUserID"); + b.HasIndex("WalletId"); + b.ToTable("LaundryStores"); }); @@ -507,6 +507,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("LaundryStoreId") + .HasColumnType("int"); + b.Property("OrderDate") .HasColumnType("datetime2"); @@ -516,14 +519,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs - b.Property("ShipDate") - .HasColumnType("datetime2"); - b.Property("StaffId") -======== + .HasColumnType("int"); + b.Property("TimeFrame") ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs .HasColumnType("int"); b.Property("TotalPrice") @@ -533,13 +532,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("CustomerID"); + b.HasIndex("LaundryStoreId"); + b.HasIndex("PaymentMethodID"); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs b.HasIndex("StaffId"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs b.ToTable("Orders"); }); @@ -607,7 +605,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("PaymentMethods"); }); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => { b.Property("Id") @@ -639,8 +636,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Service"); }); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { b.Property("Id") @@ -1117,7 +1112,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") + .WithMany() + .HasForeignKey("WalletId"); + b.Navigation("ApplicationUser"); + + b.Navigation("Wallet"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => @@ -1147,34 +1148,27 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") .WithMany() .HasForeignKey("LaundryStoreId"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") .WithMany("Orders") .HasForeignKey("PaymentMethodID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Order") + .WithMany() .HasForeignKey("StaffId"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs b.Navigation("Customer"); + b.Navigation("LaundryStore"); + b.Navigation("PaymentMethod"); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs b.Navigation("Staff"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => @@ -1306,14 +1300,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Staff_Trips"); }); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.Designer.cs -======== modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => { b.Navigation("Order"); }); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.Designer.cs modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.Navigation("OrderHistories"); diff --git a/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs b/src/Infrastructure/Migrations/20230926215325_InitMigration.cs similarity index 94% rename from src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs rename to src/Infrastructure/Migrations/20230926215325_InitMigration.cs index ef4d074..90cf6da 100644 --- a/src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs +++ b/src/Infrastructure/Migrations/20230926215325_InitMigration.cs @@ -6,11 +6,7 @@ namespace SWD_Laundry_Backend.Infrastructure.Migrations { /// -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - public partial class UpdateDatabase4 : Migration -======== - public partial class UpdateDatabase5 : Migration ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs + public partial class InitMigration : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -124,7 +120,6 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs name: "Service", columns: table => new { @@ -143,10 +138,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "TimeSchedule", -======== name: "TimeSchedules", ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -436,6 +428,7 @@ protected override void Up(MigrationBuilder migrationBuilder) EndTime = table.Column(type: "datetime2", nullable: false), Status = table.Column(type: "bit", nullable: false), ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + WalletId = table.Column(type: "int", nullable: true), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), @@ -449,6 +442,11 @@ protected override void Up(MigrationBuilder migrationBuilder) column: x => x.ApplicationUserID, principalTable: "AspNetUsers", principalColumn: "Id"); + table.ForeignKey( + name: "FK_LaundryStores_Wallets_WalletId", + column: x => x.WalletId, + principalTable: "Wallets", + principalColumn: "Id"); }); migrationBuilder.CreateTable( @@ -514,11 +512,8 @@ protected override void Up(MigrationBuilder migrationBuilder) TotalPrice = table.Column(type: "float", nullable: false), PaymentMethodID = table.Column(type: "int", nullable: false), CustomerID = table.Column(type: "int", nullable: false), -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs LaundryStoreId = table.Column(type: "int", nullable: true), StaffId = table.Column(type: "int", nullable: true), -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs OrderType = table.Column(type: "int", nullable: false), Created = table.Column(type: "datetime2", nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), @@ -534,20 +529,22 @@ protected override void Up(MigrationBuilder migrationBuilder) principalTable: "Customers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Orders_LaundryStores_LaundryStoreId", + column: x => x.LaundryStoreId, + principalTable: "LaundryStores", + principalColumn: "Id"); table.ForeignKey( name: "FK_Orders_PaymentMethods_PaymentMethodID", column: x => x.PaymentMethodID, principalTable: "PaymentMethods", principalColumn: "Id", onDelete: ReferentialAction.Cascade); -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs table.ForeignKey( name: "FK_Orders_Staffs_StaffId", column: x => x.StaffId, principalTable: "Staffs", principalColumn: "Id"); -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs }); migrationBuilder.CreateTable( @@ -590,8 +587,6 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs -======== name: "LaundryStoreOrders", columns: table => new { @@ -623,7 +618,6 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs name: "OrdersHistory", columns: table => new { @@ -766,11 +760,9 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "ApplicationUserID"); migrationBuilder.CreateIndex( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "IX_LaundryStores_WalletID", + name: "IX_LaundryStores_WalletId", table: "LaundryStores", - column: "WalletID", - unique: true); + column: "WalletId"); migrationBuilder.CreateIndex( name: "IX_LaundryStoreService_ServicesId", @@ -778,27 +770,24 @@ protected override void Up(MigrationBuilder migrationBuilder) column: "ServicesId"); migrationBuilder.CreateIndex( -======== ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs name: "IX_Orders_CustomerID", table: "Orders", column: "CustomerID"); + migrationBuilder.CreateIndex( + name: "IX_Orders_LaundryStoreId", + table: "Orders", + column: "LaundryStoreId"); + migrationBuilder.CreateIndex( name: "IX_Orders_PaymentMethodID", table: "Orders", column: "PaymentMethodID"); migrationBuilder.CreateIndex( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs name: "IX_Orders_StaffId", table: "Orders", column: "StaffId"); -======== - name: "IX_OrdersHistory_OrderID", - table: "OrdersHistory", - column: "OrderID"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs migrationBuilder.CreateIndex( name: "IX_OrdersHistory_OrderID", @@ -891,11 +880,10 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "Keys"); migrationBuilder.DropTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs - name: "LaundryStoreService"); -======== name: "LaundryStoreOrders"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs + + migrationBuilder.DropTable( + name: "LaundryStoreService"); migrationBuilder.DropTable( name: "OrdersHistory"); @@ -919,40 +907,35 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "AspNetRoles"); migrationBuilder.DropTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs name: "Service"); -======== - name: "LaundryStores"); migrationBuilder.DropTable( name: "TimeSchedules"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs migrationBuilder.DropTable( name: "Orders"); - migrationBuilder.DropTable( - name: "Staffs"); - migrationBuilder.DropTable( name: "TodoLists"); migrationBuilder.DropTable( name: "Customers"); + migrationBuilder.DropTable( + name: "LaundryStores"); + migrationBuilder.DropTable( name: "PaymentMethods"); migrationBuilder.DropTable( -<<<<<<<< HEAD:src/Infrastructure/Migrations/20230920073700_UpdateDatabase4.cs name: "Staffs"); -======== - name: "AspNetUsers"); ->>>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1:src/Infrastructure/Migrations/20230922043540_UpdateDatabase5.cs migrationBuilder.DropTable( name: "Buildings"); + migrationBuilder.DropTable( + name: "AspNetUsers"); + migrationBuilder.DropTable( name: "Wallets"); } diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 746fcd6..306b86a 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -422,10 +422,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Status") .HasColumnType("bit"); + b.Property("WalletId") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("ApplicationUserID"); + b.HasIndex("WalletId"); + b.ToTable("LaundryStores"); }); @@ -499,6 +504,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedBy") .HasColumnType("nvarchar(max)"); + b.Property("LaundryStoreId") + .HasColumnType("int"); + b.Property("OrderDate") .HasColumnType("datetime2"); @@ -508,14 +516,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PaymentMethodID") .HasColumnType("int"); -<<<<<<< HEAD - b.Property("ShipDate") - .HasColumnType("datetime2"); - b.Property("StaffId") -======= + .HasColumnType("int"); + b.Property("TimeFrame") ->>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1 .HasColumnType("int"); b.Property("TotalPrice") @@ -525,13 +529,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("CustomerID"); + b.HasIndex("LaundryStoreId"); + b.HasIndex("PaymentMethodID"); -<<<<<<< HEAD b.HasIndex("StaffId"); -======= ->>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1 b.ToTable("Orders"); }); @@ -599,7 +602,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("PaymentMethods"); }); -<<<<<<< HEAD modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => { b.Property("Id") @@ -631,8 +633,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Service"); }); -======= ->>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1 modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => { b.Property("Id") @@ -1109,7 +1109,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ApplicationUserID"); + b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") + .WithMany() + .HasForeignKey("WalletId"); + b.Navigation("ApplicationUser"); + + b.Navigation("Wallet"); }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => @@ -1139,31 +1145,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); -<<<<<<< HEAD b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") .WithMany() .HasForeignKey("LaundryStoreId"); -======= ->>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1 b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") .WithMany("Orders") .HasForeignKey("PaymentMethodID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); -<<<<<<< HEAD b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Order") + .WithMany() .HasForeignKey("StaffId"); b.Navigation("Customer"); - b.Navigation("PaymentMethod"); + b.Navigation("LaundryStore"); + b.Navigation("PaymentMethod"); b.Navigation("Staff"); - }); modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => @@ -1295,14 +1297,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Staff_Trips"); }); -<<<<<<< HEAD -======= modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => { b.Navigation("Order"); }); ->>>>>>> 9f42d83778e45289a900b887f80bd5e36a7b42f1 modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => { b.Navigation("OrderHistories"); From 63b11329943ebe5f2c2bee6a561bf4e8b9102675 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sun, 1 Oct 2023 04:10:50 +0700 Subject: [PATCH 19/53] Rebase project --- SWD-Laundry-Backend.sln | 86 +- src/Application/Application.csproj | 25 - .../CreateBuilding/CreateBuildingCommand.cs | 37 - .../CreateBuildingCommandValidator.cs | 17 - .../DeleteBuilding/DeleteBuildingCommand.cs | 25 - .../UpdateBuilding/UpdateBuildingCommand.cs | 33 - .../UpdateBuildingCommandValidator.cs | 17 - .../Buildings/Queries/BuildingViewModel.cs | 10 - .../Buildings/Queries/GetAllBuildingQuery.cs | 30 - .../Buildings/Queries/GetBuildingQuery.cs | 28 - .../Behaviours/AuthorizationBehaviour.cs | 80 - .../Common/Behaviours/LoggingBehaviour.cs | 34 - .../Common/Behaviours/PerformanceBehaviour.cs | 54 - .../Behaviours/UnhandledExceptionBehaviour.cs | 30 - .../Common/Behaviours/ValidationBehaviour.cs | 37 - .../Exceptions/ForbiddenAccessException.cs | 6 - .../Common/Exceptions/NotFoundException.cs | 24 - .../Common/Exceptions/ValidationException.cs | 22 - .../Interfaces/IApplicationDbContext.cs | 31 - .../Common/Interfaces/ICsvFileBuilder.cs | 8 - .../Common/Interfaces/ICurrentUserService.cs | 6 - .../Common/Interfaces/IDateTime.cs | 6 - .../Common/Interfaces/IIdentityService.cs | 16 - src/Application/Common/Mappings/IMapFrom.cs | 8 - .../Common/Mappings/MappingExtensions.cs | 15 - .../Common/Mappings/MappingProfile.cs | 51 - src/Application/Common/Models/LookupDto.cs | 12 - .../Common/Models/PaginatedList.cs | 31 - src/Application/Common/Models/Result.cs | 24 - .../Common/Security/AuthorizeAttribute.cs | 23 - src/Application/ConfigureServices.cs | 26 - .../Customers/Queries/CustomerVm.cs | 17 - .../Customers/Queries/GetAllCustomerQuery.cs | 10 - .../Customers/Queries/GetCustomerQuery.cs | 37 - .../CreatePaymentMethodCommand.cs | 36 - .../CreatePaymentMethodCommandValdiator.cs | 14 - .../DeletePaymentMethodCommand.cs | 26 - .../UpdatePaymentMethodCommand.cs | 31 - .../UpdatePaymentMethodCommandValidator.cs | 13 - .../Queries/GetAllPaymentMethods.cs | 34 - .../Queries/GetPaymentMethod.cs | 34 - .../Queries/PaymentMethodDto.cs | 10 - .../CreateTodoItem/CreateTodoItemCommand.cs | 41 - .../CreateTodoItemCommandValidator.cs | 13 - .../DeleteTodoItem/DeleteTodoItemCommand.cs | 37 - .../UpdateTodoItem/UpdateTodoItemCommand.cs | 41 - .../UpdateTodoItemCommandValidator.cs | 13 - .../UpdateTodoItemDetailCommand.cs | 45 - .../TodoItemCompletedEventHandler.cs | 22 - .../TodoItemCreatedEventHandler.cs | 22 - .../GetTodoItemsWithPaginationQuery.cs | 41 - ...etTodoItemsWithPaginationQueryValidator.cs | 18 - .../TodoItemBriefDto.cs | 15 - .../CreateTodoList/CreateTodoListCommand.cs | 33 - .../CreateTodoListCommandValidator.cs | 26 - .../DeleteTodoList/DeleteTodoListCommand.cs | 35 - .../PurgeTodoLists/PurgeTodoListsCommand.cs | 26 - .../UpdateTodoList/UpdateTodoListCommand.cs | 39 - .../UpdateTodoListCommandValidator.cs | 27 - .../Queries/ExportTodos/ExportTodosQuery.cs | 41 - .../Queries/ExportTodos/ExportTodosVm.cs | 17 - .../Queries/ExportTodos/TodoItemFileRecord.cs | 11 - .../Queries/GetTodos/GetTodosQuery.cs | 40 - .../Queries/GetTodos/PriorityLevelDto.cs | 8 - .../TodoLists/Queries/GetTodos/TodoItemDto.cs | 26 - .../TodoLists/Queries/GetTodos/TodoListDto.cs | 20 - .../TodoLists/Queries/GetTodos/TodosVm.cs | 8 - .../CreateWallet/CreateWalletCommand.cs | 32 - .../CreateWalletCommandValidator.cs | 15 - .../DeleteWallet/DeleteWalletCommand.cs | 25 - .../UpdateWallet/UpdateWalletCommand.cs | 27 - .../UpdateWalletCommandValidator.cs | 10 - .../Wallets/Queries/GetAllWalletQuery.cs | 30 - .../Wallets/Queries/GetWalletQuery.cs | 29 - .../Wallets/Queries/WalletViewModel.cs | 8 - src/Domain/Common/BaseAuditableEntity.cs | 12 - src/Domain/Common/BaseEntity.cs | 28 - src/Domain/Common/BaseEvent.cs | 7 - src/Domain/Common/ValueObject.cs | 40 - src/Domain/Domain.csproj | 16 - src/Domain/Entities/Building.cs | 14 - src/Domain/Entities/Customer.cs | 57 - src/Domain/Entities/LaundryService.cs | 25 - src/Domain/Entities/LaundryStore.cs | 29 - src/Domain/Entities/LaundryStoreOrder.cs | 22 - src/Domain/Entities/Order.cs | 44 - src/Domain/Entities/OrderHistory.cs | 22 - src/Domain/Entities/PaymentMethod.cs | 20 - src/Domain/Entities/Service.cs | 21 - src/Domain/Entities/Staff.cs | 24 - src/Domain/Entities/StaffOrder.cs | 23 - src/Domain/Entities/Staff_Trip.cs | 32 - src/Domain/Entities/TimeSchedule.cs | 16 - src/Domain/Entities/TodoItem.cs | 31 - src/Domain/Entities/TodoList.cs | 10 - src/Domain/Entities/Transaction.cs | 38 - src/Domain/Entities/Validation/Validate.cs | 78 - src/Domain/Entities/Wallet.cs | 17 - src/Domain/Enums/AllowedTransactionType.cs | 8 - src/Domain/Enums/OrderStatus.cs | 8 - src/Domain/Enums/OrderType.cs | 6 - src/Domain/Enums/PaymentType.cs | 8 - src/Domain/Enums/PriorityLevel.cs | 9 - src/Domain/Enums/StaffOrderType.cs | 13 - src/Domain/Enums/TimeFrame.cs | 13 - src/Domain/Events/TodoItemCompletedEvent.cs | 11 - src/Domain/Events/TodoItemCreatedEvent.cs | 11 - src/Domain/Events/TodoItemDeletedEvent.cs | 11 - .../Exceptions/UnsupportedColourException.cs | 9 - src/Domain/GlobalUsings.cs | 6 - src/Domain/IdentityModel/ApplicationRole.cs | 9 - src/Domain/IdentityModel/ApplicationUser.cs | 19 - src/Domain/ValueObjects/Colour.cs | 82 - .../Common/MediatorExtensions.cs | 24 - src/Infrastructure/ConfigureServices.cs | 83 - src/Infrastructure/Files/CsvFileBuilder.cs | 24 - .../Files/Maps/TodoItemRecordMap.cs | 15 - .../Identity/IdentityResultExtensions.cs | 14 - .../Identity/IdentityService.cs | 82 - src/Infrastructure/Infrastructure.csproj | 29 - .../20230926215325_InitMigration.Designer.cs | 1346 ----------------- .../20230926215325_InitMigration.cs | 943 ------------ .../ApplicationDbContextModelSnapshot.cs | 1343 ---------------- .../Persistence/ApplicationDbContext.cs | 74 - .../ApplicationDbContextInitialiser.cs | 115 -- .../Configurations/TodoItemConfiguration.cs | 15 - .../Configurations/TodoListConfiguration.cs | 18 - .../AuditableEntitySaveChangesInterceptor.cs | 64 - .../Services/DateTimeService.cs | 8 - .../Class1.cs | 6 + ...Laundry-Backend.Contract.Repository.csproj | 10 + .../Class1.cs | 6 + ...WD-Laundry-Backend.Contract.Service.csproj | 10 + src/SWD-Laundry-Backend.Core/Class1.cs | 6 + .../SWD-Laundry-Backend.Core.csproj | 14 + src/SWD-Laundry-Backend.Mapper/Class1.cs | 6 + .../SWD-Laundry-Backend.Mapper.csproj | 10 + src/SWD-Laundry-Backend.Repository/Class1.cs | 6 + .../SWD-Laundry-Backend.Repository.csproj | 10 + src/SWD-Laundry-Backend.Service/Class1.cs | 6 + .../SWD-Laundry-Backend.Service.csproj | 10 + .../Controllers/WeatherForecastController.cs | 31 + src/SWD-Laundry-Backend/Program.cs | 39 + .../Properties/launchSettings.json | 41 + .../SWD-Laundry-Backend.csproj | 19 + src/SWD-Laundry-Backend/WeatherForecast.cs | 12 + .../appsettings.Development.json | 8 + src/SWD-Laundry-Backend/appsettings.json | 9 + src/WebUI/.config/dotnet-tools.json | 12 - src/WebUI/ConfigureServices.cs | 61 - src/WebUI/Controllers/ApiControllerBase.cs | 15 - src/WebUI/Controllers/BuildingController.cs | 55 - .../OidcConfigurationController.cs | 27 - src/WebUI/Controllers/TodoItemsController.cs | 66 - src/WebUI/Controllers/TodoListsController.cs | 58 - src/WebUI/Controllers/WalletController.cs | 53 - .../Filters/ApiExceptionFilterAttribute.cs | 122 -- src/WebUI/Pages/Error.cshtml | 26 - src/WebUI/Pages/Error.cshtml.cs | 25 - src/WebUI/Pages/_ViewImports.cshtml | 3 - src/WebUI/Program.cs | 58 - src/WebUI/Properties/launchSettings.json | 29 - src/WebUI/Services/CurrentUserService.cs | 17 - src/WebUI/WebUI.csproj | 57 - src/WebUI/appsettings.Development.json | 15 - src/WebUI/appsettings.Production.json | 18 - src/WebUI/nswag.json | 66 - src/WebUI/wwwroot/api/specification.json | 1168 -------------- src/WebUI/wwwroot/favicon.ico | Bin 5430 -> 0 bytes 169 files changed, 312 insertions(+), 8899 deletions(-) delete mode 100644 src/Application/Application.csproj delete mode 100644 src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs delete mode 100644 src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs delete mode 100644 src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs delete mode 100644 src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs delete mode 100644 src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs delete mode 100644 src/Application/Buildings/Queries/BuildingViewModel.cs delete mode 100644 src/Application/Buildings/Queries/GetAllBuildingQuery.cs delete mode 100644 src/Application/Buildings/Queries/GetBuildingQuery.cs delete mode 100644 src/Application/Common/Behaviours/AuthorizationBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/LoggingBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/PerformanceBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs delete mode 100644 src/Application/Common/Behaviours/ValidationBehaviour.cs delete mode 100644 src/Application/Common/Exceptions/ForbiddenAccessException.cs delete mode 100644 src/Application/Common/Exceptions/NotFoundException.cs delete mode 100644 src/Application/Common/Exceptions/ValidationException.cs delete mode 100644 src/Application/Common/Interfaces/IApplicationDbContext.cs delete mode 100644 src/Application/Common/Interfaces/ICsvFileBuilder.cs delete mode 100644 src/Application/Common/Interfaces/ICurrentUserService.cs delete mode 100644 src/Application/Common/Interfaces/IDateTime.cs delete mode 100644 src/Application/Common/Interfaces/IIdentityService.cs delete mode 100644 src/Application/Common/Mappings/IMapFrom.cs delete mode 100644 src/Application/Common/Mappings/MappingExtensions.cs delete mode 100644 src/Application/Common/Mappings/MappingProfile.cs delete mode 100644 src/Application/Common/Models/LookupDto.cs delete mode 100644 src/Application/Common/Models/PaginatedList.cs delete mode 100644 src/Application/Common/Models/Result.cs delete mode 100644 src/Application/Common/Security/AuthorizeAttribute.cs delete mode 100644 src/Application/ConfigureServices.cs delete mode 100644 src/Application/Customers/Queries/CustomerVm.cs delete mode 100644 src/Application/Customers/Queries/GetAllCustomerQuery.cs delete mode 100644 src/Application/Customers/Queries/GetCustomerQuery.cs delete mode 100644 src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs delete mode 100644 src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs delete mode 100644 src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs delete mode 100644 src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs delete mode 100644 src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs delete mode 100644 src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs delete mode 100644 src/Application/PaymentMethods/Queries/GetPaymentMethod.cs delete mode 100644 src/Application/PaymentMethods/Queries/PaymentMethodDto.cs delete mode 100644 src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommand.cs delete mode 100644 src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs delete mode 100644 src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItemCommand.cs delete mode 100644 src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommand.cs delete mode 100644 src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs delete mode 100644 src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetailCommand.cs delete mode 100644 src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs delete mode 100644 src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs delete mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs delete mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs delete mode 100644 src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs delete mode 100644 src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommand.cs delete mode 100644 src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs delete mode 100644 src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoListCommand.cs delete mode 100644 src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoListsCommand.cs delete mode 100644 src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommand.cs delete mode 100644 src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs delete mode 100644 src/Application/TodoLists/Queries/ExportTodos/ExportTodosQuery.cs delete mode 100644 src/Application/TodoLists/Queries/ExportTodos/ExportTodosVm.cs delete mode 100644 src/Application/TodoLists/Queries/ExportTodos/TodoItemFileRecord.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/GetTodosQuery.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/PriorityLevelDto.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs delete mode 100644 src/Application/TodoLists/Queries/GetTodos/TodosVm.cs delete mode 100644 src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs delete mode 100644 src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs delete mode 100644 src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs delete mode 100644 src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs delete mode 100644 src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs delete mode 100644 src/Application/Wallets/Queries/GetAllWalletQuery.cs delete mode 100644 src/Application/Wallets/Queries/GetWalletQuery.cs delete mode 100644 src/Application/Wallets/Queries/WalletViewModel.cs delete mode 100644 src/Domain/Common/BaseAuditableEntity.cs delete mode 100644 src/Domain/Common/BaseEntity.cs delete mode 100644 src/Domain/Common/BaseEvent.cs delete mode 100644 src/Domain/Common/ValueObject.cs delete mode 100644 src/Domain/Domain.csproj delete mode 100644 src/Domain/Entities/Building.cs delete mode 100644 src/Domain/Entities/Customer.cs delete mode 100644 src/Domain/Entities/LaundryService.cs delete mode 100644 src/Domain/Entities/LaundryStore.cs delete mode 100644 src/Domain/Entities/LaundryStoreOrder.cs delete mode 100644 src/Domain/Entities/Order.cs delete mode 100644 src/Domain/Entities/OrderHistory.cs delete mode 100644 src/Domain/Entities/PaymentMethod.cs delete mode 100644 src/Domain/Entities/Service.cs delete mode 100644 src/Domain/Entities/Staff.cs delete mode 100644 src/Domain/Entities/StaffOrder.cs delete mode 100644 src/Domain/Entities/Staff_Trip.cs delete mode 100644 src/Domain/Entities/TimeSchedule.cs delete mode 100644 src/Domain/Entities/TodoItem.cs delete mode 100644 src/Domain/Entities/TodoList.cs delete mode 100644 src/Domain/Entities/Transaction.cs delete mode 100644 src/Domain/Entities/Validation/Validate.cs delete mode 100644 src/Domain/Entities/Wallet.cs delete mode 100644 src/Domain/Enums/AllowedTransactionType.cs delete mode 100644 src/Domain/Enums/OrderStatus.cs delete mode 100644 src/Domain/Enums/OrderType.cs delete mode 100644 src/Domain/Enums/PaymentType.cs delete mode 100644 src/Domain/Enums/PriorityLevel.cs delete mode 100644 src/Domain/Enums/StaffOrderType.cs delete mode 100644 src/Domain/Enums/TimeFrame.cs delete mode 100644 src/Domain/Events/TodoItemCompletedEvent.cs delete mode 100644 src/Domain/Events/TodoItemCreatedEvent.cs delete mode 100644 src/Domain/Events/TodoItemDeletedEvent.cs delete mode 100644 src/Domain/Exceptions/UnsupportedColourException.cs delete mode 100644 src/Domain/GlobalUsings.cs delete mode 100644 src/Domain/IdentityModel/ApplicationRole.cs delete mode 100644 src/Domain/IdentityModel/ApplicationUser.cs delete mode 100644 src/Domain/ValueObjects/Colour.cs delete mode 100644 src/Infrastructure/Common/MediatorExtensions.cs delete mode 100644 src/Infrastructure/ConfigureServices.cs delete mode 100644 src/Infrastructure/Files/CsvFileBuilder.cs delete mode 100644 src/Infrastructure/Files/Maps/TodoItemRecordMap.cs delete mode 100644 src/Infrastructure/Identity/IdentityResultExtensions.cs delete mode 100644 src/Infrastructure/Identity/IdentityService.cs delete mode 100644 src/Infrastructure/Infrastructure.csproj delete mode 100644 src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs delete mode 100644 src/Infrastructure/Migrations/20230926215325_InitMigration.cs delete mode 100644 src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs delete mode 100644 src/Infrastructure/Persistence/ApplicationDbContext.cs delete mode 100644 src/Infrastructure/Persistence/ApplicationDbContextInitialiser.cs delete mode 100644 src/Infrastructure/Persistence/Configurations/TodoItemConfiguration.cs delete mode 100644 src/Infrastructure/Persistence/Configurations/TodoListConfiguration.cs delete mode 100644 src/Infrastructure/Persistence/Interceptors/AuditableEntitySaveChangesInterceptor.cs delete mode 100644 src/Infrastructure/Services/DateTimeService.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj create mode 100644 src/SWD-Laundry-Backend.Core/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj create mode 100644 src/SWD-Laundry-Backend.Mapper/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj create mode 100644 src/SWD-Laundry-Backend.Repository/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj create mode 100644 src/SWD-Laundry-Backend.Service/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj create mode 100644 src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs create mode 100644 src/SWD-Laundry-Backend/Program.cs create mode 100644 src/SWD-Laundry-Backend/Properties/launchSettings.json create mode 100644 src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj create mode 100644 src/SWD-Laundry-Backend/WeatherForecast.cs create mode 100644 src/SWD-Laundry-Backend/appsettings.Development.json create mode 100644 src/SWD-Laundry-Backend/appsettings.json delete mode 100644 src/WebUI/.config/dotnet-tools.json delete mode 100644 src/WebUI/ConfigureServices.cs delete mode 100644 src/WebUI/Controllers/ApiControllerBase.cs delete mode 100644 src/WebUI/Controllers/BuildingController.cs delete mode 100644 src/WebUI/Controllers/OidcConfigurationController.cs delete mode 100644 src/WebUI/Controllers/TodoItemsController.cs delete mode 100644 src/WebUI/Controllers/TodoListsController.cs delete mode 100644 src/WebUI/Controllers/WalletController.cs delete mode 100644 src/WebUI/Filters/ApiExceptionFilterAttribute.cs delete mode 100644 src/WebUI/Pages/Error.cshtml delete mode 100644 src/WebUI/Pages/Error.cshtml.cs delete mode 100644 src/WebUI/Pages/_ViewImports.cshtml delete mode 100644 src/WebUI/Program.cs delete mode 100644 src/WebUI/Properties/launchSettings.json delete mode 100644 src/WebUI/Services/CurrentUserService.cs delete mode 100644 src/WebUI/WebUI.csproj delete mode 100644 src/WebUI/appsettings.Development.json delete mode 100644 src/WebUI/appsettings.Production.json delete mode 100644 src/WebUI/nswag.json delete mode 100644 src/WebUI/wwwroot/api/specification.json delete mode 100644 src/WebUI/wwwroot/favicon.ico diff --git a/SWD-Laundry-Backend.sln b/SWD-Laundry-Backend.sln index b27657d..63667f5 100644 --- a/SWD-Laundry-Backend.sln +++ b/SWD-Laundry-Backend.sln @@ -1,24 +1,29 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 +VisualStudioVersion = 17.7.34031.279 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "src\Domain\Domain.csproj", "{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend", "src\SWD-Laundry-Backend\SWD-Laundry-Backend.csproj", "{AA5AD472-4023-4E4F-A5B6-E0EFFA6183F4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "src\Application\Application.csproj", "{34C0FACD-F3D9-400C-8945-554DD6B0819A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web API", "Web API", "{36453920-D9F0-4EFF-898D-2CEB9A2217CD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{117DA02F-5274-4565-ACC6-DA9B6E568B09}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repository", "Repository", "{709AF39E-C923-4181-A776-01DBA3C45731}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B47-4613-AD01-C85CF28491BD}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Service", "Service", "{DAF8ABB4-A12C-4E6A-A15D-4F39A67EB1DF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebUI", "src\WebUI\WebUI.csproj", "{22454EE9-16B3-4B7A-8352-37E59B858155}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{A33BBFB5-1BF2-492E-AD5D-8265E276F60A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .gitignore = .gitignore - global.json = global.json - EndProjectSection +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend.Core", "src\SWD-Laundry-Backend.Core\SWD-Laundry-Backend.Core.csproj", "{A844548E-538A-461F-837F-D0A4243CE03A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend.Mapper", "src\SWD-Laundry-Backend.Mapper\SWD-Laundry-Backend.Mapper.csproj", "{EC75302B-AB1D-4D22-9957-7CEBF3B7501B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend.Contract.Repository", "src\SWD-Laundry-Backend.Contract.Repository\SWD-Laundry-Backend.Contract.Repository.csproj", "{A0B198E3-377D-4C83-8235-190B59B7A1AF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend.Repository", "src\SWD-Laundry-Backend.Repository\SWD-Laundry-Backend.Repository.csproj", "{7C9DBA26-6A75-436D-AE3A-919CC7C11061}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend.Service", "src\SWD-Laundry-Backend.Service\SWD-Laundry-Backend.Service.csproj", "{2DFE5E2D-F533-46B6-BD4C-056A701DEFB8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SWD-Laundry-Backend.Contract.Service", "src\SWD-Laundry-Backend.Contract.Service\SWD-Laundry-Backend.Contract.Service.csproj", "{A7F4EAFC-1E0C-4DF5-90C1-9D4C70B2D2FE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -26,33 +31,48 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.Build.0 = Release|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.Build.0 = Release|Any CPU - {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU - {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU - {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU - {22454EE9-16B3-4B7A-8352-37E59B858155}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {22454EE9-16B3-4B7A-8352-37E59B858155}.Debug|Any CPU.Build.0 = Debug|Any CPU - {22454EE9-16B3-4B7A-8352-37E59B858155}.Release|Any CPU.ActiveCfg = Release|Any CPU - {22454EE9-16B3-4B7A-8352-37E59B858155}.Release|Any CPU.Build.0 = Release|Any CPU + {AA5AD472-4023-4E4F-A5B6-E0EFFA6183F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA5AD472-4023-4E4F-A5B6-E0EFFA6183F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA5AD472-4023-4E4F-A5B6-E0EFFA6183F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA5AD472-4023-4E4F-A5B6-E0EFFA6183F4}.Release|Any CPU.Build.0 = Release|Any CPU + {A844548E-538A-461F-837F-D0A4243CE03A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A844548E-538A-461F-837F-D0A4243CE03A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A844548E-538A-461F-837F-D0A4243CE03A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A844548E-538A-461F-837F-D0A4243CE03A}.Release|Any CPU.Build.0 = Release|Any CPU + {EC75302B-AB1D-4D22-9957-7CEBF3B7501B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC75302B-AB1D-4D22-9957-7CEBF3B7501B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC75302B-AB1D-4D22-9957-7CEBF3B7501B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC75302B-AB1D-4D22-9957-7CEBF3B7501B}.Release|Any CPU.Build.0 = Release|Any CPU + {A0B198E3-377D-4C83-8235-190B59B7A1AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0B198E3-377D-4C83-8235-190B59B7A1AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0B198E3-377D-4C83-8235-190B59B7A1AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0B198E3-377D-4C83-8235-190B59B7A1AF}.Release|Any CPU.Build.0 = Release|Any CPU + {7C9DBA26-6A75-436D-AE3A-919CC7C11061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C9DBA26-6A75-436D-AE3A-919CC7C11061}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C9DBA26-6A75-436D-AE3A-919CC7C11061}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C9DBA26-6A75-436D-AE3A-919CC7C11061}.Release|Any CPU.Build.0 = Release|Any CPU + {2DFE5E2D-F533-46B6-BD4C-056A701DEFB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DFE5E2D-F533-46B6-BD4C-056A701DEFB8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DFE5E2D-F533-46B6-BD4C-056A701DEFB8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DFE5E2D-F533-46B6-BD4C-056A701DEFB8}.Release|Any CPU.Build.0 = Release|Any CPU + {A7F4EAFC-1E0C-4DF5-90C1-9D4C70B2D2FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7F4EAFC-1E0C-4DF5-90C1-9D4C70B2D2FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7F4EAFC-1E0C-4DF5-90C1-9D4C70B2D2FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7F4EAFC-1E0C-4DF5-90C1-9D4C70B2D2FE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {22454EE9-16B3-4B7A-8352-37E59B858155} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} + {AA5AD472-4023-4E4F-A5B6-E0EFFA6183F4} = {36453920-D9F0-4EFF-898D-2CEB9A2217CD} + {A844548E-538A-461F-837F-D0A4243CE03A} = {A33BBFB5-1BF2-492E-AD5D-8265E276F60A} + {EC75302B-AB1D-4D22-9957-7CEBF3B7501B} = {A33BBFB5-1BF2-492E-AD5D-8265E276F60A} + {A0B198E3-377D-4C83-8235-190B59B7A1AF} = {709AF39E-C923-4181-A776-01DBA3C45731} + {7C9DBA26-6A75-436D-AE3A-919CC7C11061} = {709AF39E-C923-4181-A776-01DBA3C45731} + {2DFE5E2D-F533-46B6-BD4C-056A701DEFB8} = {DAF8ABB4-A12C-4E6A-A15D-4F39A67EB1DF} + {A7F4EAFC-1E0C-4DF5-90C1-9D4C70B2D2FE} = {DAF8ABB4-A12C-4E6A-A15D-4F39A67EB1DF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430} + SolutionGuid = {D90E09BD-DB96-4CB2-97F2-86C759A1C802} EndGlobalSection EndGlobal diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj deleted file mode 100644 index b43adc4..0000000 --- a/src/Application/Application.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net7.0 - SWD_Laundry_Backend.Application - SWD_Laundry_Backend.Application - enable - enable - - - - - - - - - - - - - - - - - diff --git a/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs deleted file mode 100644 index f4f2deb..0000000 --- a/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommand.cs +++ /dev/null @@ -1,37 +0,0 @@ -using MediatR; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Buildings.Commands.CreateBuilding; -public class CreateBuildingCommand : IRequest -{ - public string? Name { get; set; } - public string? Address { get; set; } - public string? Description { get; set; } -} - -public class CreateBuildingCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public CreateBuildingCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(CreateBuildingCommand request, CancellationToken cancellationToken) - { - var entity = new Building - { - Name = request.Name, - Address = request.Address, - Description = request.Description - }; - - _context.Get().Add(entity); - - await _context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} \ No newline at end of file diff --git a/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs b/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs deleted file mode 100644 index be0b759..0000000 --- a/src/Application/Buildings/Commands/CreateBuilding/CreateBuildingCommandValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using FluentValidation; -using SWD_Laundry_Backend.Application.Common.Interfaces; - -namespace SWD_Laundry_Backend.Application.Buildings.Commands.CreateBuilding; -public class CreateBuildingCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public CreateBuildingCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Name).NotEmpty(); - RuleFor(v => v.Description).NotEmpty(); - RuleFor(v => v.Address).NotEmpty(); - } -} diff --git a/src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs b/src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs deleted file mode 100644 index 7ced21d..0000000 --- a/src/Application/Buildings/Commands/DeleteBuilding/DeleteBuildingCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Buildings.Commands.DeleteBuilding; -public class DeleteBuildingCommand : IRequest -{ - public int Id { get; set; } -} - -public class DeleteBuildingCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - public DeleteBuildingCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(DeleteBuildingCommand request, CancellationToken cancellationToken) - { - var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken); - return affectedRow; - } -} diff --git a/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs b/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs deleted file mode 100644 index bdeff0b..0000000 --- a/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Buildings.Commands.UpdateBuilding; -public class UpdateBuildingCommand : IRequest -{ - public int Id { get; set; } - public string Name { get; set; } = null!; - public string Address { get; set; } = null!; - public string Description { get; set; } = null!; -} - -public class UpdateBuildingCommandHandler : IRequestHandler -{ - - private readonly IApplicationDbContext _context; - public UpdateBuildingCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(UpdateBuildingCommand request, CancellationToken cancellationToken) - { - var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => - x.SetProperty(y => y.Name, y => request.Name ?? y.Name) - .SetProperty(y => y.Address, y => request.Address ?? y.Address) - .SetProperty(y => y.Description, y => request.Description ?? y.Description), cancellationToken: cancellationToken); - return affectedRow; - } -} - diff --git a/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs b/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs deleted file mode 100644 index 22f9da0..0000000 --- a/src/Application/Buildings/Commands/UpdateBuilding/UpdateBuildingCommandValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using FluentValidation; -using SWD_Laundry_Backend.Application.Common.Interfaces; - -namespace SWD_Laundry_Backend.Application.Buildings.Commands.UpdateBuilding; -public class UpdateBuildingCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public UpdateBuildingCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Name); - RuleFor(v => v.Address); - RuleFor(v => v.Description); - } -} diff --git a/src/Application/Buildings/Queries/BuildingViewModel.cs b/src/Application/Buildings/Queries/BuildingViewModel.cs deleted file mode 100644 index 03657a7..0000000 --- a/src/Application/Buildings/Queries/BuildingViewModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Buildings.Queries; -public class BuildingViewModel : IMapFrom -{ - public string? Name { get; set; } - public string? Address { get; set; } - public string? Description { get; set; } -} diff --git a/src/Application/Buildings/Queries/GetAllBuildingQuery.cs b/src/Application/Buildings/Queries/GetAllBuildingQuery.cs deleted file mode 100644 index 72f6241..0000000 --- a/src/Application/Buildings/Queries/GetAllBuildingQuery.cs +++ /dev/null @@ -1,30 +0,0 @@ -using AutoMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Buildings.Queries; -public class GetAllBuildingQuery : IRequest> -{ - -} - -public class GetAllBuildingQueryHandler : IRequestHandler> -{ - - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - public GetAllBuildingQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task> Handle(GetAllBuildingQuery request, CancellationToken cancellationToken) - { - var buildingList = await _context.Get().AsNoTracking().ToListAsync(cancellationToken); - return _mapper.Map>(buildingList); - } - -} diff --git a/src/Application/Buildings/Queries/GetBuildingQuery.cs b/src/Application/Buildings/Queries/GetBuildingQuery.cs deleted file mode 100644 index d188b04..0000000 --- a/src/Application/Buildings/Queries/GetBuildingQuery.cs +++ /dev/null @@ -1,28 +0,0 @@ -using AutoMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Buildings.Queries; -public class GetBuildingQuery : IRequest -{ - public int Id { init; get; } -} - -public class GetBuildingQueryHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - public GetBuildingQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task Handle(GetBuildingQuery request, CancellationToken cancellationToken) - { - var building = await _context.Get().AsNoTracking().FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); - return _mapper.Map(building); - } -} \ No newline at end of file diff --git a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs b/src/Application/Common/Behaviours/AuthorizationBehaviour.cs deleted file mode 100644 index a98174d..0000000 --- a/src/Application/Common/Behaviours/AuthorizationBehaviour.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Reflection; -using SWD_Laundry_Backend.Application.Common.Exceptions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Application.Common.Security; -using MediatR; - -namespace SWD_Laundry_Backend.Application.Common.Behaviours; - -public class AuthorizationBehaviour : IPipelineBehavior where TRequest : notnull -{ - private readonly ICurrentUserService _currentUserService; - private readonly IIdentityService _identityService; - - public AuthorizationBehaviour( - ICurrentUserService currentUserService, - IIdentityService identityService) - { - _currentUserService = currentUserService; - _identityService = identityService; - } - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - var authorizeAttributes = request.GetType().GetCustomAttributes(); - - if (authorizeAttributes.Any()) - { - // Must be authenticated user - if (_currentUserService.UserId == null) - { - throw new UnauthorizedAccessException(); - } - - // Role-based authorization - var authorizeAttributesWithRoles = authorizeAttributes.Where(a => !string.IsNullOrWhiteSpace(a.Roles)); - - if (authorizeAttributesWithRoles.Any()) - { - var authorized = false; - - foreach (var roles in authorizeAttributesWithRoles.Select(a => a.Roles.Split(','))) - { - foreach (var role in roles) - { - var isInRole = await _identityService.IsInRoleAsync(_currentUserService.UserId, role.Trim()); - if (isInRole) - { - authorized = true; - break; - } - } - } - - // Must be a member of at least one role in roles - if (!authorized) - { - throw new ForbiddenAccessException(); - } - } - - // Policy-based authorization - var authorizeAttributesWithPolicies = authorizeAttributes.Where(a => !string.IsNullOrWhiteSpace(a.Policy)); - if (authorizeAttributesWithPolicies.Any()) - { - foreach (var policy in authorizeAttributesWithPolicies.Select(a => a.Policy)) - { - var authorized = await _identityService.AuthorizeAsync(_currentUserService.UserId, policy); - - if (!authorized) - { - throw new ForbiddenAccessException(); - } - } - } - } - - // User is authorized / authorization not required - return await next(); - } -} diff --git a/src/Application/Common/Behaviours/LoggingBehaviour.cs b/src/Application/Common/Behaviours/LoggingBehaviour.cs deleted file mode 100644 index b27a660..0000000 --- a/src/Application/Common/Behaviours/LoggingBehaviour.cs +++ /dev/null @@ -1,34 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using MediatR.Pipeline; -using Microsoft.Extensions.Logging; - -namespace SWD_Laundry_Backend.Application.Common.Behaviours; - -public class LoggingBehaviour : IRequestPreProcessor where TRequest : notnull -{ - private readonly ILogger _logger; - private readonly ICurrentUserService _currentUserService; - private readonly IIdentityService _identityService; - - public LoggingBehaviour(ILogger logger, ICurrentUserService currentUserService, IIdentityService identityService) - { - _logger = logger; - _currentUserService = currentUserService; - _identityService = identityService; - } - - public async Task Process(TRequest request, CancellationToken cancellationToken) - { - var requestName = typeof(TRequest).Name; - var userId = _currentUserService.UserId ?? string.Empty; - string? userName = string.Empty; - - if (!string.IsNullOrEmpty(userId)) - { - userName = await _identityService.GetUserNameAsync(userId); - } - - _logger.LogInformation("SWD_Laundry_Backend Request: {Name} {@UserId} {@UserName} {@Request}", - requestName, userId, userName, request); - } -} diff --git a/src/Application/Common/Behaviours/PerformanceBehaviour.cs b/src/Application/Common/Behaviours/PerformanceBehaviour.cs deleted file mode 100644 index 085fb46..0000000 --- a/src/Application/Common/Behaviours/PerformanceBehaviour.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Diagnostics; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using MediatR; -using Microsoft.Extensions.Logging; - -namespace SWD_Laundry_Backend.Application.Common.Behaviours; - -public class PerformanceBehaviour : IPipelineBehavior where TRequest : notnull -{ - private readonly Stopwatch _timer; - private readonly ILogger _logger; - private readonly ICurrentUserService _currentUserService; - private readonly IIdentityService _identityService; - - public PerformanceBehaviour( - ILogger logger, - ICurrentUserService currentUserService, - IIdentityService identityService) - { - _timer = new Stopwatch(); - - _logger = logger; - _currentUserService = currentUserService; - _identityService = identityService; - } - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - _timer.Start(); - - var response = await next(); - - _timer.Stop(); - - var elapsedMilliseconds = _timer.ElapsedMilliseconds; - - if (elapsedMilliseconds > 500) - { - var requestName = typeof(TRequest).Name; - var userId = _currentUserService.UserId ?? string.Empty; - var userName = string.Empty; - - if (!string.IsNullOrEmpty(userId)) - { - userName = await _identityService.GetUserNameAsync(userId); - } - - _logger.LogWarning("SWD_Laundry_Backend Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@UserName} {@Request}", - requestName, elapsedMilliseconds, userId, userName, request); - } - - return response; - } -} diff --git a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs b/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs deleted file mode 100644 index b51073e..0000000 --- a/src/Application/Common/Behaviours/UnhandledExceptionBehaviour.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediatR; -using Microsoft.Extensions.Logging; - -namespace SWD_Laundry_Backend.Application.Common.Behaviours; - -public class UnhandledExceptionBehaviour : IPipelineBehavior where TRequest : notnull -{ - private readonly ILogger _logger; - - public UnhandledExceptionBehaviour(ILogger logger) - { - _logger = logger; - } - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - try - { - return await next(); - } - catch (Exception ex) - { - var requestName = typeof(TRequest).Name; - - _logger.LogError(ex, "SWD_Laundry_Backend Request: Unhandled Exception for Request {Name} {@Request}", requestName, request); - - throw; - } - } -} diff --git a/src/Application/Common/Behaviours/ValidationBehaviour.cs b/src/Application/Common/Behaviours/ValidationBehaviour.cs deleted file mode 100644 index 237ede0..0000000 --- a/src/Application/Common/Behaviours/ValidationBehaviour.cs +++ /dev/null @@ -1,37 +0,0 @@ -using FluentValidation; -using MediatR; -using ValidationException = SWD_Laundry_Backend.Application.Common.Exceptions.ValidationException; - -namespace SWD_Laundry_Backend.Application.Common.Behaviours; - -public class ValidationBehaviour : IPipelineBehavior - where TRequest : notnull -{ - private readonly IEnumerable> _validators; - - public ValidationBehaviour(IEnumerable> validators) - { - _validators = validators; - } - - public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) - { - if (_validators.Any()) - { - var context = new ValidationContext(request); - - var validationResults = await Task.WhenAll( - _validators.Select(v => - v.ValidateAsync(context, cancellationToken))); - - var failures = validationResults - .Where(r => r.Errors.Any()) - .SelectMany(r => r.Errors) - .ToList(); - - if (failures.Any()) - throw new ValidationException(failures); - } - return await next(); - } -} diff --git a/src/Application/Common/Exceptions/ForbiddenAccessException.cs b/src/Application/Common/Exceptions/ForbiddenAccessException.cs deleted file mode 100644 index add6dfa..0000000 --- a/src/Application/Common/Exceptions/ForbiddenAccessException.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Application.Common.Exceptions; - -public class ForbiddenAccessException : Exception -{ - public ForbiddenAccessException() : base() { } -} diff --git a/src/Application/Common/Exceptions/NotFoundException.cs b/src/Application/Common/Exceptions/NotFoundException.cs deleted file mode 100644 index b4e5295..0000000 --- a/src/Application/Common/Exceptions/NotFoundException.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace SWD_Laundry_Backend.Application.Common.Exceptions; - -public class NotFoundException : Exception -{ - public NotFoundException() - : base() - { - } - - public NotFoundException(string message) - : base(message) - { - } - - public NotFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - - public NotFoundException(string name, object key) - : base($"Entity \"{name}\" ({key}) was not found.") - { - } -} diff --git a/src/Application/Common/Exceptions/ValidationException.cs b/src/Application/Common/Exceptions/ValidationException.cs deleted file mode 100644 index 6dffbae..0000000 --- a/src/Application/Common/Exceptions/ValidationException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FluentValidation.Results; - -namespace SWD_Laundry_Backend.Application.Common.Exceptions; - -public class ValidationException : Exception -{ - public ValidationException() - : base("One or more validation failures have occurred.") - { - Errors = new Dictionary(); - } - - public ValidationException(IEnumerable failures) - : this() - { - Errors = failures - .GroupBy(e => e.PropertyName, e => e.ErrorMessage) - .ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()); - } - - public IDictionary Errors { get; } -} diff --git a/src/Application/Common/Interfaces/IApplicationDbContext.cs b/src/Application/Common/Interfaces/IApplicationDbContext.cs deleted file mode 100644 index 06667cc..0000000 --- a/src/Application/Common/Interfaces/IApplicationDbContext.cs +++ /dev/null @@ -1,31 +0,0 @@ -using SWD_Laundry_Backend.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Domain.Common; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Application.Common.Interfaces; - -public interface IApplicationDbContext -{ - DbSet TodoLists { get; } - - DbSet TodoItems { get; } - - DbSet Customers { get; } - DbSet Buildings { get; } - DbSet ApplicationUsers { get; } - DbSet LaundryStores { get; } - DbSet Orders { get; } - DbSet OrdersHistory{ get; } - DbSet PaymentMethods { get; } - DbSet Staff_Trips { get; } - DbSet Staffs { get; } - DbSet Transactions { get; } - DbSet Wallets { get; } - - - - DbSet Get() where T : BaseAuditableEntity; - - Task SaveChangesAsync(CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/src/Application/Common/Interfaces/ICsvFileBuilder.cs b/src/Application/Common/Interfaces/ICsvFileBuilder.cs deleted file mode 100644 index d9c5155..0000000 --- a/src/Application/Common/Interfaces/ICsvFileBuilder.cs +++ /dev/null @@ -1,8 +0,0 @@ -using SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; - -namespace SWD_Laundry_Backend.Application.Common.Interfaces; - -public interface ICsvFileBuilder -{ - byte[] BuildTodoItemsFile(IEnumerable records); -} diff --git a/src/Application/Common/Interfaces/ICurrentUserService.cs b/src/Application/Common/Interfaces/ICurrentUserService.cs deleted file mode 100644 index 9e43825..0000000 --- a/src/Application/Common/Interfaces/ICurrentUserService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Application.Common.Interfaces; - -public interface ICurrentUserService -{ - string? UserId { get; } -} diff --git a/src/Application/Common/Interfaces/IDateTime.cs b/src/Application/Common/Interfaces/IDateTime.cs deleted file mode 100644 index fad4b30..0000000 --- a/src/Application/Common/Interfaces/IDateTime.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Application.Common.Interfaces; - -public interface IDateTime -{ - DateTime Now { get; } -} diff --git a/src/Application/Common/Interfaces/IIdentityService.cs b/src/Application/Common/Interfaces/IIdentityService.cs deleted file mode 100644 index f6dc3f0..0000000 --- a/src/Application/Common/Interfaces/IIdentityService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Models; - -namespace SWD_Laundry_Backend.Application.Common.Interfaces; - -public interface IIdentityService -{ - Task GetUserNameAsync(string userId); - - Task IsInRoleAsync(string userId, string role); - - Task AuthorizeAsync(string userId, string policyName); - - Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password); - - Task DeleteUserAsync(string userId); -} diff --git a/src/Application/Common/Mappings/IMapFrom.cs b/src/Application/Common/Mappings/IMapFrom.cs deleted file mode 100644 index 1dccd6d..0000000 --- a/src/Application/Common/Mappings/IMapFrom.cs +++ /dev/null @@ -1,8 +0,0 @@ -using AutoMapper; - -namespace SWD_Laundry_Backend.Application.Common.Mappings; - -public interface IMapFrom -{ - void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType()); -} diff --git a/src/Application/Common/Mappings/MappingExtensions.cs b/src/Application/Common/Mappings/MappingExtensions.cs deleted file mode 100644 index 226e31a..0000000 --- a/src/Application/Common/Mappings/MappingExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using AutoMapper; -using AutoMapper.QueryableExtensions; -using SWD_Laundry_Backend.Application.Common.Models; -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.Common.Mappings; - -public static class MappingExtensions -{ - public static Task> PaginatedListAsync(this IQueryable queryable, int pageNumber, int pageSize) where TDestination : class - => PaginatedList.CreateAsync(queryable.AsNoTracking(), pageNumber, pageSize); - - public static Task> ProjectToListAsync(this IQueryable queryable, IConfigurationProvider configuration) where TDestination : class - => queryable.ProjectTo(configuration).AsNoTracking().ToListAsync(); -} diff --git a/src/Application/Common/Mappings/MappingProfile.cs b/src/Application/Common/Mappings/MappingProfile.cs deleted file mode 100644 index 745f1ab..0000000 --- a/src/Application/Common/Mappings/MappingProfile.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Reflection; -using AutoMapper; - -namespace SWD_Laundry_Backend.Application.Common.Mappings; - -public class MappingProfile : Profile -{ - public MappingProfile() - { - ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly()); - } - - private void ApplyMappingsFromAssembly(Assembly assembly) - { - var mapFromType = typeof(IMapFrom<>); - - var mappingMethodName = nameof(IMapFrom.Mapping); - - bool HasInterface(Type t) => t.IsGenericType && t.GetGenericTypeDefinition() == mapFromType; - - var types = assembly.GetExportedTypes().Where(t => t.GetInterfaces().Any(HasInterface)).ToList(); - - var argumentTypes = new Type[] { typeof(Profile) }; - - foreach (var type in types) - { - var instance = Activator.CreateInstance(type); - - var methodInfo = type.GetMethod(mappingMethodName); - - if (methodInfo != null) - { - methodInfo.Invoke(instance, new object[] { this }); - } - else - { - var interfaces = type.GetInterfaces().Where(HasInterface).ToList(); - - if (interfaces.Count > 0) - { - foreach (var @interface in interfaces) - { - var interfaceMethodInfo = @interface.GetMethod(mappingMethodName, argumentTypes); - - interfaceMethodInfo?.Invoke(instance, new object[] { this }); - } - } - } - } - } -} diff --git a/src/Application/Common/Models/LookupDto.cs b/src/Application/Common/Models/LookupDto.cs deleted file mode 100644 index 3db1515..0000000 --- a/src/Application/Common/Models/LookupDto.cs +++ /dev/null @@ -1,12 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Common.Models; - -// Note: This is currently just used to demonstrate applying multiple IMapFrom attributes. -public class LookupDto : IMapFrom, IMapFrom -{ - public int Id { get; init; } - - public string? Title { get; init; } -} diff --git a/src/Application/Common/Models/PaginatedList.cs b/src/Application/Common/Models/PaginatedList.cs deleted file mode 100644 index b3c1fbd..0000000 --- a/src/Application/Common/Models/PaginatedList.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.Common.Models; - -public class PaginatedList -{ - public IReadOnlyCollection Items { get; } - public int PageNumber { get; } - public int TotalPages { get; } - public int TotalCount { get; } - - public PaginatedList(IReadOnlyCollection items, int count, int pageNumber, int pageSize) - { - PageNumber = pageNumber; - TotalPages = (int)Math.Ceiling(count / (double)pageSize); - TotalCount = count; - Items = items; - } - - public bool HasPreviousPage => PageNumber > 1; - - public bool HasNextPage => PageNumber < TotalPages; - - public static async Task> CreateAsync(IQueryable source, int pageNumber, int pageSize) - { - var count = await source.CountAsync(); - var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync(); - - return new PaginatedList(items, count, pageNumber, pageSize); - } -} diff --git a/src/Application/Common/Models/Result.cs b/src/Application/Common/Models/Result.cs deleted file mode 100644 index fd285c8..0000000 --- a/src/Application/Common/Models/Result.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace SWD_Laundry_Backend.Application.Common.Models; - -public class Result -{ - internal Result(bool succeeded, IEnumerable errors) - { - Succeeded = succeeded; - Errors = errors.ToArray(); - } - - public bool Succeeded { get; init; } - - public string[] Errors { get; init; } - - public static Result Success() - { - return new Result(true, Array.Empty()); - } - - public static Result Failure(IEnumerable errors) - { - return new Result(false, errors); - } -} diff --git a/src/Application/Common/Security/AuthorizeAttribute.cs b/src/Application/Common/Security/AuthorizeAttribute.cs deleted file mode 100644 index 2f54c4f..0000000 --- a/src/Application/Common/Security/AuthorizeAttribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace SWD_Laundry_Backend.Application.Common.Security; - -/// -/// Specifies the class this attribute is applied to requires authorization. -/// -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] -public class AuthorizeAttribute : Attribute -{ - /// - /// Initializes a new instance of the class. - /// - public AuthorizeAttribute() { } - - /// - /// Gets or sets a comma delimited list of roles that are allowed to access the resource. - /// - public string Roles { get; set; } = string.Empty; - - /// - /// Gets or sets the policy name that determines access to the resource. - /// - public string Policy { get; set; } = string.Empty; -} diff --git a/src/Application/ConfigureServices.cs b/src/Application/ConfigureServices.cs deleted file mode 100644 index ab09203..0000000 --- a/src/Application/ConfigureServices.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using SWD_Laundry_Backend.Application.Common.Behaviours; -using SWD_Laundry_Backend.Application.Common.Exceptions; -using FluentValidation; -using MediatR; - -namespace Microsoft.Extensions.DependencyInjection; - -public static class ConfigureServices -{ - public static IServiceCollection AddApplicationServices(this IServiceCollection services) - { - services.AddAutoMapper(Assembly.GetExecutingAssembly()); - services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); - services.AddMediatR(cfg => { - cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); - cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>)); - cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehaviour<,>)); - cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); - cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>)); - - }); - - return services; - } -} diff --git a/src/Application/Customers/Queries/CustomerVm.cs b/src/Application/Customers/Queries/CustomerVm.cs deleted file mode 100644 index 322436c..0000000 --- a/src/Application/Customers/Queries/CustomerVm.cs +++ /dev/null @@ -1,17 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Application.Customers.Queries; -public class CustomerVm : IMapFrom -{ - public int BuildingID { get; set; } - - public string ApplicationUserID { get; set; } - - public Building Building { get; set; } - - public ApplicationUser ApplicationUser { get; set; } - public virtual List Order { get; set; } - -} diff --git a/src/Application/Customers/Queries/GetAllCustomerQuery.cs b/src/Application/Customers/Queries/GetAllCustomerQuery.cs deleted file mode 100644 index fe39af7..0000000 --- a/src/Application/Customers/Queries/GetAllCustomerQuery.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Application.Customers.Queries; -internal class GetAllCustomerQuery -{ -} diff --git a/src/Application/Customers/Queries/GetCustomerQuery.cs b/src/Application/Customers/Queries/GetCustomerQuery.cs deleted file mode 100644 index 4c59019..0000000 --- a/src/Application/Customers/Queries/GetCustomerQuery.cs +++ /dev/null @@ -1,37 +0,0 @@ -using AutoMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; - -namespace SWD_Laundry_Backend.Application.Customers.Queries; -public class GetCustomerQuery : IRequest -{ - public int Id { get; set; } = 0; - public string? UserName { get; set; } - public string? UserId { get; set; } - -} - -public class GetCustomerQueryHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetCustomerQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task Handle(GetCustomerQuery request, CancellationToken cancellationToken) - { - var customers = await _context.Get() - .Include(x => x.ApplicationUser) - .AsNoTracking() - .Where(x => x.Id == request.Id || x.ApplicationUser.UserName == request.UserName || x.ApplicationUser.Id == request.UserId) - .FirstOrDefaultAsync(cancellationToken); - - return _mapper.Map(customers); - } - -} \ No newline at end of file diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs deleted file mode 100644 index e608eaf..0000000 --- a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommand.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediatR; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Enums; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; -public class CreatePaymentMethodCommand : IRequest -{ - public string? Name { get; set; } - public string? Description { get; set; } -} - -public class CreatePaymentMethodCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public CreatePaymentMethodCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(CreatePaymentMethodCommand request, CancellationToken cancellationToken) - { - var entity = new PaymentMethod - { - Name = request.Name, - Description = request.Description - }; - - _context.Get().Add(entity); - - await _context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} diff --git a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs b/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs deleted file mode 100644 index 41cfc02..0000000 --- a/src/Application/PaymentMethods/Commands/CreatePaymentMethod/CreatePaymentMethodCommandValdiator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FluentValidation; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.CreatePaymentMethod; -public class CreatePaymentMethodCommandValdiator : AbstractValidator -{ - - public CreatePaymentMethodCommandValdiator() - { - RuleFor(v => v.Name) - .MaximumLength(200) - .NotEmpty(); - RuleFor(v => v.Description); - } -} diff --git a/src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs deleted file mode 100644 index 0ce288f..0000000 --- a/src/Application/PaymentMethods/Commands/DeletePaymentMethod/DeletePaymentMethodCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.DeletePaymentMethod; -public class DeletePaymentMethodCommand : IRequest -{ - public int Id { get; set; } -} - -public class DeletePaymentMethodCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public DeletePaymentMethodCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(DeletePaymentMethodCommand request, CancellationToken cancellationToken) - { - int affectedRows = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken: cancellationToken); - return affectedRows; - } -} diff --git a/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs b/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs deleted file mode 100644 index 274eae4..0000000 --- a/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommand.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.UpdatePaymentMethod; -public class UpdatePaymentMethodCommand : IRequest -{ - public int Id { get; set; } - public string? Name { get; set; } - public string? Description { get; set; } -} - -public class UpdatePaymentMethodCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public UpdatePaymentMethodCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(UpdatePaymentMethodCommand request, CancellationToken cancellationToken) - { - int affectedRows = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => - x.SetProperty(p => p.Name, p => request.Name ?? p.Name) - .SetProperty(p => p.Description, p => request.Description ?? p.Name)); - return affectedRows; - } -} - diff --git a/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs b/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs deleted file mode 100644 index 27fb3f6..0000000 --- a/src/Application/PaymentMethods/Commands/UpdatePaymentMethod/UpdatePaymentMethodCommandValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Commands.UpdatePaymentMethod; -public class UpdatePaymentMethodCommandValidator : AbstractValidator -{ - public UpdatePaymentMethodCommandValidator() - { - RuleFor(v => v.Name) - .MaximumLength(200) - .NotEmpty(); - RuleFor(v => v.Description); - } -} diff --git a/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs b/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs deleted file mode 100644 index 5a28e9d..0000000 --- a/src/Application/PaymentMethods/Queries/GetAllPaymentMethods.cs +++ /dev/null @@ -1,34 +0,0 @@ -using AutoMapper; -using AutoMapper.QueryableExtensions; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Enums; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -public class GetAllPaymentMethods -{ - public class GetAllPaymentMethodsQuery : IRequest - { - } - - public class GetAllPaymentMethodsQueryHandler : IRequestHandler - { - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetAllPaymentMethodsQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task Handle(GetAllPaymentMethodsQuery request, CancellationToken cancellationToken) - { - var paymentMethods = await _context.Get().ProjectTo(_mapper.ConfigurationProvider).ToListAsync(cancellationToken); - var result = _mapper.Map(paymentMethods); - return result; - } - } -} diff --git a/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs b/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs deleted file mode 100644 index 5f7dd05..0000000 --- a/src/Application/PaymentMethods/Queries/GetPaymentMethod.cs +++ /dev/null @@ -1,34 +0,0 @@ -using AutoMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Enums; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -public class GetPaymentMethod : IRequest -{ - public int Id { get; init; } -} - -public class GetPaymentMethodHandler : IRequestHandler -{ - - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - public GetPaymentMethodHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task Handle(GetPaymentMethod request, CancellationToken cancellationToken) - { - var paymentMethod = await _context.Get().Where(x => x.Id == request.Id).AsNoTracking().FirstOrDefaultAsync(cancellationToken); - - var result = _mapper.Map(paymentMethod); - - return result; - } - -} \ No newline at end of file diff --git a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs b/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs deleted file mode 100644 index b255489..0000000 --- a/src/Application/PaymentMethods/Queries/PaymentMethodDto.cs +++ /dev/null @@ -1,10 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Enums; - -namespace SWD_Laundry_Backend.Application.PaymentMethods.Queries; -public class PaymentMethodDto : IMapFrom -{ - public string? Name { get; init; } - public string? Description { get; set; } -} diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommand.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommand.cs deleted file mode 100644 index 7a96d80..0000000 --- a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Events; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoItems.Commands.CreateTodoItem; - -public record CreateTodoItemCommand : IRequest -{ - public int ListId { get; init; } - - public string? Title { get; init; } -} - -public class CreateTodoItemCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public CreateTodoItemCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(CreateTodoItemCommand request, CancellationToken cancellationToken) - { - var entity = new TodoItem - { - ListId = request.ListId, - Title = request.Title, - Done = false - }; - - entity.AddDomainEvent(new TodoItemCreatedEvent(entity)); - - _context.TodoItems.Add(entity); - - await _context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} diff --git a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs b/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs deleted file mode 100644 index 3786dfc..0000000 --- a/src/Application/TodoItems/Commands/CreateTodoItem/CreateTodoItemCommandValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace SWD_Laundry_Backend.Application.TodoItems.Commands.CreateTodoItem; - -public class CreateTodoItemCommandValidator : AbstractValidator -{ - public CreateTodoItemCommandValidator() - { - RuleFor(v => v.Title) - .MaximumLength(200) - .NotEmpty(); - } -} diff --git a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItemCommand.cs b/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItemCommand.cs deleted file mode 100644 index 8349d62..0000000 --- a/src/Application/TodoItems/Commands/DeleteTodoItem/DeleteTodoItemCommand.cs +++ /dev/null @@ -1,37 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Exceptions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Events; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoItems.Commands.DeleteTodoItem; - -public record DeleteTodoItemCommand(int Id) : IRequest; - -public class DeleteTodoItemCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public DeleteTodoItemCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(DeleteTodoItemCommand request, CancellationToken cancellationToken) - { - var entity = await _context.TodoItems - .FindAsync(new object[] { request.Id }, cancellationToken); - - if (entity == null) - { - throw new NotFoundException(nameof(TodoItem), request.Id); - } - - _context.TodoItems.Remove(entity); - - entity.AddDomainEvent(new TodoItemDeletedEvent(entity)); - - await _context.SaveChangesAsync(cancellationToken); - } - -} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommand.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommand.cs deleted file mode 100644 index af206bf..0000000 --- a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Exceptions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItem; - -public record UpdateTodoItemCommand : IRequest -{ - public int Id { get; init; } - - public string? Title { get; init; } - - public bool Done { get; init; } -} - -public class UpdateTodoItemCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public UpdateTodoItemCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken) - { - var entity = await _context.TodoItems - .FindAsync(new object[] { request.Id }, cancellationToken); - - if (entity == null) - { - throw new NotFoundException(nameof(TodoItem), request.Id); - } - - entity.Title = request.Title; - entity.Done = request.Done; - - await _context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs b/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs deleted file mode 100644 index 71c7b0d..0000000 --- a/src/Application/TodoItems/Commands/UpdateTodoItem/UpdateTodoItemCommandValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItem; - -public class UpdateTodoItemCommandValidator : AbstractValidator -{ - public UpdateTodoItemCommandValidator() - { - RuleFor(v => v.Title) - .MaximumLength(200) - .NotEmpty(); - } -} diff --git a/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetailCommand.cs b/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetailCommand.cs deleted file mode 100644 index 9754c99..0000000 --- a/src/Application/TodoItems/Commands/UpdateTodoItemDetail/UpdateTodoItemDetailCommand.cs +++ /dev/null @@ -1,45 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Exceptions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Domain.Enums; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItemDetail; - -public record UpdateTodoItemDetailCommand : IRequest -{ - public int Id { get; init; } - - public int ListId { get; init; } - - public PriorityLevel Priority { get; init; } - - public string? Note { get; init; } -} - -public class UpdateTodoItemDetailCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public UpdateTodoItemDetailCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(UpdateTodoItemDetailCommand request, CancellationToken cancellationToken) - { - var entity = await _context.TodoItems - .FindAsync(new object[] { request.Id }, cancellationToken); - - if (entity == null) - { - throw new NotFoundException(nameof(TodoItem), request.Id); - } - - entity.ListId = request.ListId; - entity.Priority = request.Priority; - entity.Note = request.Note; - - await _context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs deleted file mode 100644 index 846d758..0000000 --- a/src/Application/TodoItems/EventHandlers/TodoItemCompletedEventHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using SWD_Laundry_Backend.Domain.Events; -using MediatR; -using Microsoft.Extensions.Logging; - -namespace SWD_Laundry_Backend.Application.TodoItems.EventHandlers; - -public class TodoItemCompletedEventHandler : INotificationHandler -{ - private readonly ILogger _logger; - - public TodoItemCompletedEventHandler(ILogger logger) - { - _logger = logger; - } - - public Task Handle(TodoItemCompletedEvent notification, CancellationToken cancellationToken) - { - _logger.LogInformation("SWD_Laundry_Backend Domain Event: {DomainEvent}", notification.GetType().Name); - - return Task.CompletedTask; - } -} diff --git a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs b/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs deleted file mode 100644 index 55e1c62..0000000 --- a/src/Application/TodoItems/EventHandlers/TodoItemCreatedEventHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using SWD_Laundry_Backend.Domain.Events; -using MediatR; -using Microsoft.Extensions.Logging; - -namespace SWD_Laundry_Backend.Application.TodoItems.EventHandlers; - -public class TodoItemCreatedEventHandler : INotificationHandler -{ - private readonly ILogger _logger; - - public TodoItemCreatedEventHandler(ILogger logger) - { - _logger = logger; - } - - public Task Handle(TodoItemCreatedEvent notification, CancellationToken cancellationToken) - { - _logger.LogInformation("SWD_Laundry_Backend Domain Event: {DomainEvent}", notification.GetType().Name); - - return Task.CompletedTask; - } -} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs deleted file mode 100644 index fca9224..0000000 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQuery.cs +++ /dev/null @@ -1,41 +0,0 @@ -using AutoMapper; -using AutoMapper.QueryableExtensions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Application.Common.Models; -using MediatR; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -public record GetTodoItemsWithPaginationQuery : IRequest> -{ - public int ListId { get; init; } - public int PageNumber { get; init; } = 1; - public int PageSize { get; init; } = 10; -} - -public class GetTodoItemsWithPaginationQueryHandler : IRequestHandler> -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetTodoItemsWithPaginationQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - - - - - public async Task> Handle(GetTodoItemsWithPaginationQuery request, CancellationToken cancellationToken) - { - return await _context.TodoItems - .Where(x => x.ListId == request.ListId) - .OrderBy(x => x.Title) - .ProjectTo(_mapper.ConfigurationProvider) - .PaginatedListAsync(request.PageNumber, request.PageSize); - } -} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs deleted file mode 100644 index d75dbf9..0000000 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/GetTodoItemsWithPaginationQueryValidator.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FluentValidation; - -namespace SWD_Laundry_Backend.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -public class GetTodoItemsWithPaginationQueryValidator : AbstractValidator -{ - public GetTodoItemsWithPaginationQueryValidator() - { - RuleFor(x => x.ListId) - .NotEmpty().WithMessage("ListId is required."); - - RuleFor(x => x.PageNumber) - .GreaterThanOrEqualTo(1).WithMessage("PageNumber at least greater than or equal to 1."); - - RuleFor(x => x.PageSize) - .GreaterThanOrEqualTo(1).WithMessage("PageSize at least greater than or equal to 1."); - } -} diff --git a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs b/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs deleted file mode 100644 index 0b6510f..0000000 --- a/src/Application/TodoItems/Queries/GetTodoItemsWithPagination/TodoItemBriefDto.cs +++ /dev/null @@ -1,15 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.TodoItems.Queries.GetTodoItemsWithPagination; - -public class TodoItemBriefDto : IMapFrom -{ - public int Id { get; init; } - - public int ListId { get; init; } - - public string? Title { get; init; } - - public bool Done { get; init; } -} diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommand.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommand.cs deleted file mode 100644 index 623534a..0000000 --- a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoLists.Commands.CreateTodoList; - -public record CreateTodoListCommand : IRequest -{ - public string? Title { get; init; } -} - -public class CreateTodoListCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public CreateTodoListCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(CreateTodoListCommand request, CancellationToken cancellationToken) - { - var entity = new TodoList(); - - entity.Title = request.Title; - - _context.TodoLists.Add(entity); - - await _context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} diff --git a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs deleted file mode 100644 index a4be877..0000000 --- a/src/Application/TodoLists/Commands/CreateTodoList/CreateTodoListCommandValidator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using FluentValidation; -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.TodoLists.Commands.CreateTodoList; - -public class CreateTodoListCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public CreateTodoListCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Title) - .NotEmpty().WithMessage("Title is required.") - .MaximumLength(200).WithMessage("Title must not exceed 200 characters.") - .MustAsync(BeUniqueTitle).WithMessage("The specified title already exists."); - } - - public async Task BeUniqueTitle(string title, CancellationToken cancellationToken) - { - return await _context.TodoLists - .AllAsync(l => l.Title != title, cancellationToken); - } -} diff --git a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoListCommand.cs b/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoListCommand.cs deleted file mode 100644 index 16607a9..0000000 --- a/src/Application/TodoLists/Commands/DeleteTodoList/DeleteTodoListCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Exceptions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.TodoLists.Commands.DeleteTodoList; - -public record DeleteTodoListCommand(int Id) : IRequest; - -public class DeleteTodoListCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public DeleteTodoListCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(DeleteTodoListCommand request, CancellationToken cancellationToken) - { - var entity = await _context.TodoLists - .Where(l => l.Id == request.Id) - .SingleOrDefaultAsync(cancellationToken); - - if (entity == null) - { - throw new NotFoundException(nameof(TodoList), request.Id); - } - - _context.TodoLists.Remove(entity); - - await _context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoListsCommand.cs b/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoListsCommand.cs deleted file mode 100644 index 8f0ba42..0000000 --- a/src/Application/TodoLists/Commands/PurgeTodoLists/PurgeTodoListsCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Application.Common.Security; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoLists.Commands.PurgeTodoLists; - -[Authorize(Roles = "Administrator")] -[Authorize(Policy = "CanPurge")] -public record PurgeTodoListsCommand : IRequest; - -public class PurgeTodoListsCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public PurgeTodoListsCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(PurgeTodoListsCommand request, CancellationToken cancellationToken) - { - _context.TodoLists.RemoveRange(_context.TodoLists); - - await _context.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommand.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommand.cs deleted file mode 100644 index 277f015..0000000 --- a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommand.cs +++ /dev/null @@ -1,39 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Exceptions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; -using MediatR; - -namespace SWD_Laundry_Backend.Application.TodoLists.Commands.UpdateTodoList; - -public record UpdateTodoListCommand : IRequest -{ - public int Id { get; init; } - - public string? Title { get; init; } -} - -public class UpdateTodoListCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public UpdateTodoListCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(UpdateTodoListCommand request, CancellationToken cancellationToken) - { - var entity = await _context.TodoLists - .FindAsync(new object[] { request.Id }, cancellationToken); - - if (entity == null) - { - throw new NotFoundException(nameof(TodoList), request.Id); - } - - entity.Title = request.Title; - - await _context.SaveChangesAsync(cancellationToken); - - } -} diff --git a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs b/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs deleted file mode 100644 index 55dd55d..0000000 --- a/src/Application/TodoLists/Commands/UpdateTodoList/UpdateTodoListCommandValidator.cs +++ /dev/null @@ -1,27 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using FluentValidation; -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.TodoLists.Commands.UpdateTodoList; - -public class UpdateTodoListCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public UpdateTodoListCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Title) - .NotEmpty().WithMessage("Title is required.") - .MaximumLength(200).WithMessage("Title must not exceed 200 characters.") - .MustAsync(BeUniqueTitle).WithMessage("The specified title already exists."); - } - - public async Task BeUniqueTitle(UpdateTodoListCommand model, string title, CancellationToken cancellationToken) - { - return await _context.TodoLists - .Where(l => l.Id != model.Id) - .AllAsync(l => l.Title != title, cancellationToken); - } -} diff --git a/src/Application/TodoLists/Queries/ExportTodos/ExportTodosQuery.cs b/src/Application/TodoLists/Queries/ExportTodos/ExportTodosQuery.cs deleted file mode 100644 index 54180c8..0000000 --- a/src/Application/TodoLists/Queries/ExportTodos/ExportTodosQuery.cs +++ /dev/null @@ -1,41 +0,0 @@ -using AutoMapper; -using AutoMapper.QueryableExtensions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; - -public record ExportTodosQuery : IRequest -{ - public int ListId { get; init; } -} - -public class ExportTodosQueryHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - private readonly ICsvFileBuilder _fileBuilder; - - public ExportTodosQueryHandler(IApplicationDbContext context, IMapper mapper, ICsvFileBuilder fileBuilder) - { - _context = context; - _mapper = mapper; - _fileBuilder = fileBuilder; - } - - public async Task Handle(ExportTodosQuery request, CancellationToken cancellationToken) - { - var records = await _context.TodoItems - .Where(t => t.ListId == request.ListId) - .ProjectTo(_mapper.ConfigurationProvider) - .ToListAsync(cancellationToken); - - var vm = new ExportTodosVm( - "TodoItems.csv", - "text/csv", - _fileBuilder.BuildTodoItemsFile(records)); - - return vm; - } -} diff --git a/src/Application/TodoLists/Queries/ExportTodos/ExportTodosVm.cs b/src/Application/TodoLists/Queries/ExportTodos/ExportTodosVm.cs deleted file mode 100644 index 11e750e..0000000 --- a/src/Application/TodoLists/Queries/ExportTodos/ExportTodosVm.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; - -public class ExportTodosVm -{ - public ExportTodosVm(string fileName, string contentType, byte[] content) - { - FileName = fileName; - ContentType = contentType; - Content = content; - } - - public string FileName { get; init; } - - public string ContentType { get; init; } - - public byte[] Content { get; init;} -} diff --git a/src/Application/TodoLists/Queries/ExportTodos/TodoItemFileRecord.cs b/src/Application/TodoLists/Queries/ExportTodos/TodoItemFileRecord.cs deleted file mode 100644 index a2a0137..0000000 --- a/src/Application/TodoLists/Queries/ExportTodos/TodoItemFileRecord.cs +++ /dev/null @@ -1,11 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; - -public class TodoItemRecord : IMapFrom -{ - public string? Title { get; init; } - - public bool Done { get; init; } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/GetTodosQuery.cs b/src/Application/TodoLists/Queries/GetTodos/GetTodosQuery.cs deleted file mode 100644 index e2f81a9..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/GetTodosQuery.cs +++ /dev/null @@ -1,40 +0,0 @@ -using AutoMapper; -using AutoMapper.QueryableExtensions; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Application.Common.Security; -using SWD_Laundry_Backend.Domain.Enums; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.GetTodos; - -public record GetTodosQuery : IRequest; - -public class GetTodosQueryHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetTodosQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task Handle(GetTodosQuery request, CancellationToken cancellationToken) - { - return new TodosVm - { - PriorityLevels = Enum.GetValues(typeof(PriorityLevel)) - .Cast() - .Select(p => new PriorityLevelDto { Value = (int)p, Name = p.ToString() }) - .ToList(), - - Lists = await _context.TodoLists - .AsNoTracking() - .ProjectTo(_mapper.ConfigurationProvider) - .OrderBy(t => t.Title) - .ToListAsync(cancellationToken) - }; - } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/PriorityLevelDto.cs b/src/Application/TodoLists/Queries/GetTodos/PriorityLevelDto.cs deleted file mode 100644 index aebb57b..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/PriorityLevelDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.GetTodos; - -public class PriorityLevelDto -{ - public int Value { get; init; } - - public string? Name { get; init; } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs deleted file mode 100644 index 49315bc..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/TodoItemDto.cs +++ /dev/null @@ -1,26 +0,0 @@ -using AutoMapper; -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.GetTodos; - -public class TodoItemDto : IMapFrom -{ - public int Id { get; init; } - - public int ListId { get; init; } - - public string? Title { get; init; } - - public bool Done { get; init; } - - public int Priority { get; init; } - - public string? Note { get; init; } - - public void Mapping(Profile profile) - { - profile.CreateMap() - .ForMember(d => d.Priority, opt => opt.MapFrom(s => (int)s.Priority)); - } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs b/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs deleted file mode 100644 index 896ec77..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/TodoListDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.GetTodos; - -public class TodoListDto : IMapFrom -{ - public TodoListDto() - { - Items = Array.Empty(); - } - - public int Id { get; init; } - - public string? Title { get; init; } - - public string? Colour { get; init; } - - public IReadOnlyCollection Items { get; init; } -} diff --git a/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs b/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs deleted file mode 100644 index fea4ca1..0000000 --- a/src/Application/TodoLists/Queries/GetTodos/TodosVm.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SWD_Laundry_Backend.Application.TodoLists.Queries.GetTodos; - -public class TodosVm -{ - public IReadOnlyCollection PriorityLevels { get; init; } = Array.Empty(); - - public IReadOnlyCollection Lists { get; init; } = Array.Empty(); -} diff --git a/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs b/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs deleted file mode 100644 index 33bff09..0000000 --- a/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommand.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MediatR; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Wallets.Commands.CreateWallet; -public class CreateWalletCommand : IRequest -{ - public double Balance { get; init; } -} - -public class CreateWalletCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - - public CreateWalletCommandHandler(IApplicationDbContext context) - { - _context = context; - } - public async Task Handle(CreateWalletCommand request, CancellationToken cancellationToken) - { - var entity = new Wallet - { - Balance = request.Balance - }; - - _context.Get().Add(entity); - - await _context.SaveChangesAsync(cancellationToken); - - return entity.Id; - } -} \ No newline at end of file diff --git a/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs b/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs deleted file mode 100644 index 526ea01..0000000 --- a/src/Application/Wallets/Commands/CreateWallet/CreateWalletCommandValidator.cs +++ /dev/null @@ -1,15 +0,0 @@ -using FluentValidation; -using SWD_Laundry_Backend.Application.Common.Interfaces; - -namespace SWD_Laundry_Backend.Application.Wallets.Commands.CreateWallet; -public class CreateWalletCommandValidator : AbstractValidator -{ - private readonly IApplicationDbContext _context; - - public CreateWalletCommandValidator(IApplicationDbContext context) - { - _context = context; - - RuleFor(v => v.Balance).GreaterThan(0); - } -} diff --git a/src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs b/src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs deleted file mode 100644 index 018219b..0000000 --- a/src/Application/Wallets/Commands/DeleteWallet/DeleteWalletCommand.cs +++ /dev/null @@ -1,25 +0,0 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Wallets.Commands.DeleteWallet; -public class DeleteWalletCommand : IRequest -{ - public int Id { get; init; } -} - -public class DeleteWalletCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - public DeleteWalletCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(DeleteWalletCommand request, CancellationToken cancellationToken) - { - var affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteDeleteAsync(cancellationToken); - return affectedRow; - } -} diff --git a/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs b/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs deleted file mode 100644 index 5bf1d36..0000000 --- a/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommand.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Wallets.Commands.UpdateWallet; -public class UpdateWalletCommand : IRequest -{ - public int Id { get; set; } - public double Balance { get; set; } -} - -public class UpdateWalletCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - public UpdateWalletCommandHandler(IApplicationDbContext context) - { - _context = context; - } - - public async Task Handle(UpdateWalletCommand request, CancellationToken cancellationToken) - { - int affectedRow = await _context.Get().Where(x => x.Id == request.Id).ExecuteUpdateAsync(x => - x.SetProperty(y => y.Balance, request.Balance), cancellationToken: cancellationToken); - return affectedRow; - } -} \ No newline at end of file diff --git a/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs b/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs deleted file mode 100644 index b13a861..0000000 --- a/src/Application/Wallets/Commands/UpdateWallet/UpdateWalletCommandValidator.cs +++ /dev/null @@ -1,10 +0,0 @@ -using FluentValidation; - -namespace SWD_Laundry_Backend.Application.Wallets.Commands.UpdateWallet; -public class UpdateWalletCommandValidator : AbstractValidator -{ - public UpdateWalletCommandValidator() - { - RuleFor(v => v.Balance).GreaterThan(0); - } -} diff --git a/src/Application/Wallets/Queries/GetAllWalletQuery.cs b/src/Application/Wallets/Queries/GetAllWalletQuery.cs deleted file mode 100644 index ca0406f..0000000 --- a/src/Application/Wallets/Queries/GetAllWalletQuery.cs +++ /dev/null @@ -1,30 +0,0 @@ -using AutoMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Wallets.Queries; -public class GetAllWalletQuery : IRequest> -{ - -} - -public class GetAllWalletQueryHandler : IRequestHandler> -{ - - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - public GetAllWalletQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task> Handle(GetAllWalletQuery request, CancellationToken cancellationToken) - { - var walletList = await _context.Get().AsNoTracking().ToListAsync(cancellationToken); - return _mapper.Map>(walletList); - } - -} diff --git a/src/Application/Wallets/Queries/GetWalletQuery.cs b/src/Application/Wallets/Queries/GetWalletQuery.cs deleted file mode 100644 index a2c0168..0000000 --- a/src/Application/Wallets/Queries/GetWalletQuery.cs +++ /dev/null @@ -1,29 +0,0 @@ -using AutoMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Wallets.Queries; -public class GetWalletQuery : IRequest -{ - public int Id { get; set; } -} - -public class GetWalletQueryHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IMapper _mapper; - - public GetWalletQueryHandler(IApplicationDbContext context, IMapper mapper) - { - _context = context; - _mapper = mapper; - } - - public async Task Handle(GetWalletQuery request, CancellationToken cancellationToken) - { - var entity = await _context.Get().FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); - return _mapper.Map(entity); - } -} diff --git a/src/Application/Wallets/Queries/WalletViewModel.cs b/src/Application/Wallets/Queries/WalletViewModel.cs deleted file mode 100644 index 67d4f7f..0000000 --- a/src/Application/Wallets/Queries/WalletViewModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Mappings; -using SWD_Laundry_Backend.Domain.Entities; - -namespace SWD_Laundry_Backend.Application.Wallets.Queries; -public class WalletViewModel : IMapFrom -{ - public double Balance { get; set; } -} diff --git a/src/Domain/Common/BaseAuditableEntity.cs b/src/Domain/Common/BaseAuditableEntity.cs deleted file mode 100644 index ddb756d..0000000 --- a/src/Domain/Common/BaseAuditableEntity.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Common; - -public abstract class BaseAuditableEntity : BaseEntity -{ - public DateTime Created { get; set; } - - public string? CreatedBy { get; set; } - - public DateTime? LastModified { get; set; } - - public string? LastModifiedBy { get; set; } -} diff --git a/src/Domain/Common/BaseEntity.cs b/src/Domain/Common/BaseEntity.cs deleted file mode 100644 index df0f36b..0000000 --- a/src/Domain/Common/BaseEntity.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace SWD_Laundry_Backend.Domain.Common; - -public abstract class BaseEntity -{ - public int Id { get; set; } - - private readonly List _domainEvents = new(); - - [NotMapped] - public IReadOnlyCollection DomainEvents => _domainEvents.AsReadOnly(); - - public void AddDomainEvent(BaseEvent domainEvent) - { - _domainEvents.Add(domainEvent); - } - - public void RemoveDomainEvent(BaseEvent domainEvent) - { - _domainEvents.Remove(domainEvent); - } - - public void ClearDomainEvents() - { - _domainEvents.Clear(); - } -} diff --git a/src/Domain/Common/BaseEvent.cs b/src/Domain/Common/BaseEvent.cs deleted file mode 100644 index a832ebe..0000000 --- a/src/Domain/Common/BaseEvent.cs +++ /dev/null @@ -1,7 +0,0 @@ -using MediatR; - -namespace SWD_Laundry_Backend.Domain.Common; - -public abstract class BaseEvent : INotification -{ -} diff --git a/src/Domain/Common/ValueObject.cs b/src/Domain/Common/ValueObject.cs deleted file mode 100644 index 87d159f..0000000 --- a/src/Domain/Common/ValueObject.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Common; - -// Learn more: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects -public abstract class ValueObject -{ - protected static bool EqualOperator(ValueObject left, ValueObject right) - { - if (left is null ^ right is null) - { - return false; - } - - return left?.Equals(right!) != false; - } - - protected static bool NotEqualOperator(ValueObject left, ValueObject right) - { - return !(EqualOperator(left, right)); - } - - protected abstract IEnumerable GetEqualityComponents(); - - public override bool Equals(object? obj) - { - if (obj == null || obj.GetType() != GetType()) - { - return false; - } - - var other = (ValueObject)obj; - return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); - } - - public override int GetHashCode() - { - return GetEqualityComponents() - .Select(x => x != null ? x.GetHashCode() : 0) - .Aggregate((x, y) => x ^ y); - } -} diff --git a/src/Domain/Domain.csproj b/src/Domain/Domain.csproj deleted file mode 100644 index 7f8fddb..0000000 --- a/src/Domain/Domain.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net7.0 - SWD_Laundry_Backend.Domain - SWD_Laundry_Backend.Domain - enable - enable - - - - - - - - diff --git a/src/Domain/Entities/Building.cs b/src/Domain/Entities/Building.cs deleted file mode 100644 index b775634..0000000 --- a/src/Domain/Entities/Building.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Building : BaseAuditableEntity -{ - public string Name { get; set; } - public string Address { get; set; } - public string Description { get; set; } - - #region Relationship - public List Customers { get; set; } - public List Staff_Trips { get; set; } - #endregion -} \ No newline at end of file diff --git a/src/Domain/Entities/Customer.cs b/src/Domain/Entities/Customer.cs deleted file mode 100644 index 2d38dcb..0000000 --- a/src/Domain/Entities/Customer.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Domain.Entities; - -#nullable disable - -public class Customer : BaseAuditableEntity -{ - //public string Name { get; set; } - //public string Address { get; set; } - - #region Relationship - - [ForeignKey("Building")] - public int BuildingID { get; set; } - - [ForeignKey("ApplicationUser")] - public string ApplicationUserID { get; set; } - - public Building Building { get; set; } - - public ApplicationUser ApplicationUser { get; set; } - public virtual List Order { get; set; } - - #endregion Relationship - - #region Special Attribute - - //private string _email; - - //private string _phone; - - //public string Email - //{ - // get { return _email; } - // set - // { - // _email = new Validate().IsValidEmail(value) - // ? value - // : throw new ArgumentException("Invalid email."); - // } - //} - - //public string Phone - //{ - // get { return _phone; } - // set - // { - // _phone = new Validate().IsValidPhone(value) - // ? value - // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - // } - //} - - #endregion Special Attribute -} \ No newline at end of file diff --git a/src/Domain/Entities/LaundryService.cs b/src/Domain/Entities/LaundryService.cs deleted file mode 100644 index fc4fb54..0000000 --- a/src/Domain/Entities/LaundryService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Domain.Entities; - -public class LaundryService : BaseAuditableEntity -{ - public double Price { get; set; } - #region Relationship - - [ForeignKey(nameof(LaundryStore))] - public int LaundryId { get; set; } - - [ForeignKey(nameof(LaundryStore))] - public int ServiceId { get; set; } - - public LaundryStore? LaundryStore { get; set; } - public Service? Service { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/LaundryStore.cs b/src/Domain/Entities/LaundryStore.cs deleted file mode 100644 index f6c7f17..0000000 --- a/src/Domain/Entities/LaundryStore.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class LaundryStore : BaseAuditableEntity -{ - public string Name { get; set; } - public string Address { get; set; } - - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } - public bool Status { get; set; } - - #region Relationship - - [ForeignKey("ApplicationUser")] - public string ApplicationUserID { get; set; } - - public ApplicationUser ApplicationUser { get; set; } - - public Wallet Wallet { get; set; } - - - public virtual List Services { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/LaundryStoreOrder.cs b/src/Domain/Entities/LaundryStoreOrder.cs deleted file mode 100644 index 89b83ac..0000000 --- a/src/Domain/Entities/LaundryStoreOrder.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace SWD_Laundry_Backend.Domain.Entities; - -public class LaundryStoreOrder : BaseAuditableEntity -#nullable disable -{ - public bool IsDone { get; set; } - - #region Relationship - - [ForeignKey("Order")] - public int OrderID { get; set; } - - [ForeignKey("LaundryStore")] - public int LaundryStoreID { get; set; } - - public LaundryStore LaundryStore { get; set; } - public Order Order { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/Order.cs b/src/Domain/Entities/Order.cs deleted file mode 100644 index 79250cd..0000000 --- a/src/Domain/Entities/Order.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Order : BaseAuditableEntity -{ - public DateTime OrderDate { get; set; } = DateTime.Now; - public TimeFrame TimeFrame { get; set; } - public DateTime ExpectedFinishDate { get; set; } - public string Address { get; set; } // Address = Customer's building location - public short Amount { get; set; } - - public double TotalPrice { get; set; } - - #region Relationship - - [ForeignKey("PaymentMethod")] - public int PaymentMethodID { get; set; } - - [ForeignKey("Customer")] - public int CustomerID { get; set; } - - ////=========================== - - - public virtual LaundryStore LaundryStore { get; set; } - public virtual Customer Customer { get; set; } - public virtual Staff Staff { get; set; } - - - public PaymentMethod PaymentMethod { get; set; } - public List OrderHistories { get; set; } - public List StaffOrders { get; set; } - //public LaundryStoreOrder LaundryStoreOrder { get; set; } - - #endregion Relationship - - #region Special Attribute - - public OrderType OrderType { get; set; } - - #endregion Special Attribute -} \ No newline at end of file diff --git a/src/Domain/Entities/OrderHistory.cs b/src/Domain/Entities/OrderHistory.cs deleted file mode 100644 index 0f8115b..0000000 --- a/src/Domain/Entities/OrderHistory.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class OrderHistory : BaseAuditableEntity -{ - #region Relationship - - [ForeignKey("Order")] - public int OrderID { get; set; } - - public Order Order { get; set; } - - #endregion Relationship - - #region Special attributes - - public OrderStatus Status { get; set;} - - #endregion Special attributes -} \ No newline at end of file diff --git a/src/Domain/Entities/PaymentMethod.cs b/src/Domain/Entities/PaymentMethod.cs deleted file mode 100644 index 36cc4ff..0000000 --- a/src/Domain/Entities/PaymentMethod.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class PaymentMethod : BaseAuditableEntity -{ - public string Description { get; set; } - - #region Relationship - - public List Orders { get; set; } - - #endregion Relationship - - #region Special Attributes - - public string Name { get; set; } - - #endregion - -} \ No newline at end of file diff --git a/src/Domain/Entities/Service.cs b/src/Domain/Entities/Service.cs deleted file mode 100644 index 939c895..0000000 --- a/src/Domain/Entities/Service.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Service : BaseAuditableEntity -{ - public string Name { get; set; } - public string Description { get; set; } - //public double Price { get; set; } - - #region Relationship - - public List LaundryStores{ get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/Staff.cs b/src/Domain/Entities/Staff.cs deleted file mode 100644 index ae26c6f..0000000 --- a/src/Domain/Entities/Staff.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Staff : BaseAuditableEntity -{ - public DateTime Dob { get; set; } - public string Address { get; set; } - public double Salary { get; set; } - - #region Relationship - - [ForeignKey("ApplicationUser")] - public string ApplicationUserID { get; set; } - - public ApplicationUser ApplicationUser { get; set; } - - public List Staff_Trips { get; set; } - public List StaffOrders { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/StaffOrder.cs b/src/Domain/Entities/StaffOrder.cs deleted file mode 100644 index 1ab6693..0000000 --- a/src/Domain/Entities/StaffOrder.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class StaffOrder : BaseAuditableEntity -{ - public bool IsDone { get; set; } - public StaffOrderType Type { get; set; } - - #region Relationship - - [ForeignKey("Staff")] - public int StaffID { get; set; } - - [ForeignKey("Order")] - public int OrderID { get; set; } - - public Staff Staff { get; set; } - public Order Order { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Entities/Staff_Trip.cs b/src/Domain/Entities/Staff_Trip.cs deleted file mode 100644 index edc23f0..0000000 --- a/src/Domain/Entities/Staff_Trip.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -namespace SWD_Laundry_Backend.Domain.Entities; - -#nullable disable - -public class Staff_Trip : BaseAuditableEntity -{ - public int TripCollect { get; set; } = 0; - - #region Relationship - - [ForeignKey("Staff")] - public int StaffID { get; set; } - - [ForeignKey("TimeSchedule")] - public int TimeScheduleID { get; set; } - - [ForeignKey("Building")] - public int BuildingID { get; set; } - - public Building Building { get; set; } - public Staff Staff { get; set; } - public TimeSchedule TimeSchedule { get; set; } - - #endregion Relationship - - #region Special Attribute - - public OrderStatus TripStatus { get; set; } - - #endregion Special Attribute -} \ No newline at end of file diff --git a/src/Domain/Entities/TimeSchedule.cs b/src/Domain/Entities/TimeSchedule.cs deleted file mode 100644 index 966531e..0000000 --- a/src/Domain/Entities/TimeSchedule.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class TimeSchedule : BaseAuditableEntity -{ - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } - - #region Special Attribute - - public DayOfWeek DayOfWeek { get; set; } - public TimeFrame TimeFrame { get; set; } - public List Staff_Trip { get; set; } - - #endregion Special Attribute -} \ No newline at end of file diff --git a/src/Domain/Entities/TodoItem.cs b/src/Domain/Entities/TodoItem.cs deleted file mode 100644 index fb189b8..0000000 --- a/src/Domain/Entities/TodoItem.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Entities; - -public class TodoItem : BaseAuditableEntity -{ - public int ListId { get; set; } - - public string? Title { get; set; } - - public string? Note { get; set; } - - public PriorityLevel Priority { get; set; } - - public DateTime? Reminder { get; set; } - - private bool _done; - public bool Done - { - get => _done; - set - { - if (value && !_done) - { - AddDomainEvent(new TodoItemCompletedEvent(this)); - } - - _done = value; - } - } - - public TodoList List { get; set; } = null!; -} diff --git a/src/Domain/Entities/TodoList.cs b/src/Domain/Entities/TodoList.cs deleted file mode 100644 index c499e50..0000000 --- a/src/Domain/Entities/TodoList.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Entities; - -public class TodoList : BaseAuditableEntity -{ - public string? Title { get; set; } - - public Colour Colour { get; set; } = Colour.White; - - public IList Items { get; private set; } = new List(); -} diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs deleted file mode 100644 index 190996f..0000000 --- a/src/Domain/Entities/Transaction.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Transaction : BaseAuditableEntity -{ - public string PaymentMethod { get; set; } - public int Amount { get; set; } - public string Description { get; set; } - - #region Relationship - - public int WalletID { get; set; } - - public Wallet Wallet { get; set; } - - #endregion Relationship - - #region Special Attribute - - //private string _transactiontype; - - //public string TransactionType - //{ - // get { return _transactiontype; } - // set - // { - // if (!new Validate().IsValidTransactionType(value)) - // throw new ArgumentException("Invalid transaction type {DEPOSIT, WITHDRAWAL, DEBT, PAID}."); - // _transactiontype = value; - // } - //} - - public AllowedTransactionType TransactionType { get; set; } - - public OrderStatus Status { get; set; } - - #endregion Special Attribute -} \ No newline at end of file diff --git a/src/Domain/Entities/Validation/Validate.cs b/src/Domain/Entities/Validation/Validate.cs deleted file mode 100644 index 1687108..0000000 --- a/src/Domain/Entities/Validation/Validate.cs +++ /dev/null @@ -1,78 +0,0 @@ -//using System.Text.RegularExpressions; - -//namespace SWD_Laundry_Backend.Domain.Entities.Validation; - -//public class Validate -//{ - -// public bool IsValidStaffRole(string roleName) -// { -// return StaffRole.Contains(roleName); -// } - -// public bool IsValidTransactionType(string type) -// { -// return AllowedTransactionType.Contains(type); -// } - -// public bool IsValidTransactionStatus(string status) -// { -// return Status.Contains(status); -// } - -// public bool IsValidPhone(string phone) -// { -// string pattern = @"^(09|01)\d{8,9}$"; -// return Regex.IsMatch(phone, pattern); -// } - -// public bool IsValidEmail(string email) -// { -// string pattern = @"^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$"; -// return Regex.IsMatch(email, pattern); -// } - -// public bool IsValidTripStatus(string status) -// { -// return Status.Contains(status); -// } - -// public bool IsValidPayment(string payment) -// { -// return Payment.Contains(payment); -// } - -// public bool IsValidOrderType(string value) -// { -// return OrderType.Contains(value); -// } - -// //======================================================= -// private readonly string[] OrderType = new string[] -// { -// "ONEWAY","TWOWAY" -// }; - -// private readonly string[] Payment = new string[] -// { -// "CASH","PAYPAL" -// }; -// private readonly string[] Status = new string[] -// { -// "FINISHED","PROCESSING","CANCELLED" -// }; - - -// private readonly string[] StaffRole = new string[] -// { -// "COLLECTOR","RECEIVER" -// }; - - -// private readonly string[] AllowedTransactionType = new string[] -// { -// "DEPOSIT","WITHDRAWAL", "DEBT", "PAID" -// }; - - -//} \ No newline at end of file diff --git a/src/Domain/Entities/Wallet.cs b/src/Domain/Entities/Wallet.cs deleted file mode 100644 index 7f3078a..0000000 --- a/src/Domain/Entities/Wallet.cs +++ /dev/null @@ -1,17 +0,0 @@ -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Domain.Entities; -#nullable disable - -public class Wallet : BaseAuditableEntity -{ - public double Balance { get; set; } - - #region Relationship - - public List Transactions { get; set; } - - public ApplicationUser ApplicationUser { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/Enums/AllowedTransactionType.cs b/src/Domain/Enums/AllowedTransactionType.cs deleted file mode 100644 index eb2fbbb..0000000 --- a/src/Domain/Enums/AllowedTransactionType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Enums; -public enum AllowedTransactionType -{ - Deposit = 1, - Withdraw = 2, - Debt = 3, - Paid = 4 -} diff --git a/src/Domain/Enums/OrderStatus.cs b/src/Domain/Enums/OrderStatus.cs deleted file mode 100644 index 492970f..0000000 --- a/src/Domain/Enums/OrderStatus.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Enums; -public enum OrderStatus -{ - Pending = 1, - Processing = 2, - Completed = 3, - Cancelled = 4 -} diff --git a/src/Domain/Enums/OrderType.cs b/src/Domain/Enums/OrderType.cs deleted file mode 100644 index cb5aa61..0000000 --- a/src/Domain/Enums/OrderType.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Enums; -public enum OrderType -{ - OneWay = 1, - TwoWay = 2 -} diff --git a/src/Domain/Enums/PaymentType.cs b/src/Domain/Enums/PaymentType.cs deleted file mode 100644 index 5779958..0000000 --- a/src/Domain/Enums/PaymentType.cs +++ /dev/null @@ -1,8 +0,0 @@ -//namespace SWD_Laundry_Backend.Domain.Enums; -//public enum PaymentType -//{ -// Cash = 1, -// CreditCard = 2, -// DebitCard = 3, -// EWallet = 4 -//} diff --git a/src/Domain/Enums/PriorityLevel.cs b/src/Domain/Enums/PriorityLevel.cs deleted file mode 100644 index 85a3188..0000000 --- a/src/Domain/Enums/PriorityLevel.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Enums; - -public enum PriorityLevel -{ - None = 0, - Low = 1, - Medium = 2, - High = 3 -} diff --git a/src/Domain/Enums/StaffOrderType.cs b/src/Domain/Enums/StaffOrderType.cs deleted file mode 100644 index 32c6d6e..0000000 --- a/src/Domain/Enums/StaffOrderType.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Domain.Enums; - -public enum StaffOrderType -{ - CollectFromCustomer = 0, - DeliveryToCustomer = 1 -} \ No newline at end of file diff --git a/src/Domain/Enums/TimeFrame.cs b/src/Domain/Enums/TimeFrame.cs deleted file mode 100644 index 18a252e..0000000 --- a/src/Domain/Enums/TimeFrame.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SWD_Laundry_Backend.Domain.Enums; -public enum TimeFrame -{ - Morning = 0, // 7h - 12h - Afternoon= 1, // 13h - 18h - Night = 2, // 19h - 24h -} diff --git a/src/Domain/Events/TodoItemCompletedEvent.cs b/src/Domain/Events/TodoItemCompletedEvent.cs deleted file mode 100644 index b6fd492..0000000 --- a/src/Domain/Events/TodoItemCompletedEvent.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Events; - -public class TodoItemCompletedEvent : BaseEvent -{ - public TodoItemCompletedEvent(TodoItem item) - { - Item = item; - } - - public TodoItem Item { get; } -} diff --git a/src/Domain/Events/TodoItemCreatedEvent.cs b/src/Domain/Events/TodoItemCreatedEvent.cs deleted file mode 100644 index 584b1f3..0000000 --- a/src/Domain/Events/TodoItemCreatedEvent.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Events; - -public class TodoItemCreatedEvent : BaseEvent -{ - public TodoItemCreatedEvent(TodoItem item) - { - Item = item; - } - - public TodoItem Item { get; } -} diff --git a/src/Domain/Events/TodoItemDeletedEvent.cs b/src/Domain/Events/TodoItemDeletedEvent.cs deleted file mode 100644 index a58336b..0000000 --- a/src/Domain/Events/TodoItemDeletedEvent.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Events; - -public class TodoItemDeletedEvent : BaseEvent -{ - public TodoItemDeletedEvent(TodoItem item) - { - Item = item; - } - - public TodoItem Item { get; } -} diff --git a/src/Domain/Exceptions/UnsupportedColourException.cs b/src/Domain/Exceptions/UnsupportedColourException.cs deleted file mode 100644 index eead808..0000000 --- a/src/Domain/Exceptions/UnsupportedColourException.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.Exceptions; - -public class UnsupportedColourException : Exception -{ - public UnsupportedColourException(string code) - : base($"Colour \"{code}\" is unsupported.") - { - } -} diff --git a/src/Domain/GlobalUsings.cs b/src/Domain/GlobalUsings.cs deleted file mode 100644 index ab5d45d..0000000 --- a/src/Domain/GlobalUsings.cs +++ /dev/null @@ -1,6 +0,0 @@ -global using SWD_Laundry_Backend.Domain.Common; -global using SWD_Laundry_Backend.Domain.Entities; -global using SWD_Laundry_Backend.Domain.Enums; -global using SWD_Laundry_Backend.Domain.Events; -global using SWD_Laundry_Backend.Domain.Exceptions; -global using SWD_Laundry_Backend.Domain.ValueObjects; \ No newline at end of file diff --git a/src/Domain/IdentityModel/ApplicationRole.cs b/src/Domain/IdentityModel/ApplicationRole.cs deleted file mode 100644 index 86cdb24..0000000 --- a/src/Domain/IdentityModel/ApplicationRole.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.AspNetCore.Identity; - -namespace SWD_Laundry_Backend.Domain.IdentityModel; - - -public class ApplicationRole : IdentityRole -{ - public string? Description { get; set; } -} \ No newline at end of file diff --git a/src/Domain/IdentityModel/ApplicationUser.cs b/src/Domain/IdentityModel/ApplicationUser.cs deleted file mode 100644 index f6152ab..0000000 --- a/src/Domain/IdentityModel/ApplicationUser.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -using Microsoft.AspNetCore.Identity; - -namespace SWD_Laundry_Backend.Domain.IdentityModel; - -public class ApplicationUser : IdentityUser -{ -#nullable disable - public string Name { get; set; } - - #region Relationship - - [ForeignKey("Wallet")] - public int WalletID { get; set; } - - public Wallet Wallet { get; set; } - - #endregion Relationship -} \ No newline at end of file diff --git a/src/Domain/ValueObjects/Colour.cs b/src/Domain/ValueObjects/Colour.cs deleted file mode 100644 index c4f3e38..0000000 --- a/src/Domain/ValueObjects/Colour.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace SWD_Laundry_Backend.Domain.ValueObjects; - -public class Colour : ValueObject -{ - static Colour() - { - } - - private Colour() - { - } - - private Colour(string code) - { - Code = code; - } - - public static Colour From(string code) - { - var colour = new Colour { Code = code }; - - if (!SupportedColours.Contains(colour)) - { - throw new UnsupportedColourException(code); - } - - return colour; - } - - public static Colour White => new("#FFFFFF"); - - public static Colour Red => new("#FF5733"); - - public static Colour Orange => new("#FFC300"); - - public static Colour Yellow => new("#FFFF66"); - - public static Colour Green => new("#CCFF99"); - - public static Colour Blue => new("#6666FF"); - - public static Colour Purple => new("#9966CC"); - - public static Colour Grey => new("#999999"); - - public string Code { get; private set; } = "#000000"; - - public static implicit operator string(Colour colour) - { - return colour.ToString(); - } - - public static explicit operator Colour(string code) - { - return From(code); - } - - public override string ToString() - { - return Code; - } - - protected static IEnumerable SupportedColours - { - get - { - yield return White; - yield return Red; - yield return Orange; - yield return Yellow; - yield return Green; - yield return Blue; - yield return Purple; - yield return Grey; - } - } - - protected override IEnumerable GetEqualityComponents() - { - yield return Code; - } -} diff --git a/src/Infrastructure/Common/MediatorExtensions.cs b/src/Infrastructure/Common/MediatorExtensions.cs deleted file mode 100644 index 28bb406..0000000 --- a/src/Infrastructure/Common/MediatorExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using SWD_Laundry_Backend.Domain.Common; -using Microsoft.EntityFrameworkCore; - -namespace MediatR; - -public static class MediatorExtensions -{ - public static async Task DispatchDomainEvents(this IMediator mediator, DbContext context) - { - var entities = context.ChangeTracker - .Entries() - .Where(e => e.Entity.DomainEvents.Any()) - .Select(e => e.Entity); - - var domainEvents = entities - .SelectMany(e => e.DomainEvents) - .ToList(); - - entities.ToList().ForEach(e => e.ClearDomainEvents()); - - foreach (var domainEvent in domainEvents) - await mediator.Publish(domainEvent); - } -} diff --git a/src/Infrastructure/ConfigureServices.cs b/src/Infrastructure/ConfigureServices.cs deleted file mode 100644 index 2f9bb88..0000000 --- a/src/Infrastructure/ConfigureServices.cs +++ /dev/null @@ -1,83 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Infrastructure.Files; -using SWD_Laundry_Backend.Infrastructure.Identity; -using SWD_Laundry_Backend.Infrastructure.Persistence; -using SWD_Laundry_Backend.Infrastructure.Persistence.Interceptors; -using SWD_Laundry_Backend.Infrastructure.Services; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.AspNetCore.Authorization; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace Microsoft.Extensions.DependencyInjection; - -public static class ConfigureServices -{ - public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration) - { - services.AddScoped(); - - if (configuration.GetValue("UseInMemoryDatabase")) - { - services.AddDbContext(options => - options.UseInMemoryDatabase("SWD_Laundry_BackendDb")); - } - else - { - services.AddDbContext(options => - options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"), - builder => builder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName))); - } - - services.AddScoped(provider => provider.GetRequiredService()); - - services.AddScoped(); - - services - .AddDefaultIdentity() - .AddRoles() - .AddEntityFrameworkStores(); - - services.AddIdentityServer() - .AddApiAuthorization(); - - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddAuthentication() - .AddIdentityServerJwt(); - - //services.AddAuthorization(options => - // options.AddPolicy("CanPurge", policy => policy.RequireRole("Administrator"))); - - services.AddAuthorization(options => - { - options.DefaultPolicy = new AuthorizationPolicyBuilder() - .RequireAuthenticatedUser() - .Build(); - - options.AddPolicy("Admin", policy => policy - .Combine(options.DefaultPolicy) - .RequireRole("Admin") - .Build()); - options.AddPolicy("Staff", policy => policy - .Combine(options.DefaultPolicy) - .RequireRole("Staff") - .Build()); - options.AddPolicy("Customer", policy => policy - .Combine(options.DefaultPolicy) - .RequireRole("Customer") - .Build()); - options.AddPolicy("AdminOrStaff", policy => policy - .Combine(options.DefaultPolicy) - .RequireRole("Admin", "Staff") - .Build()); - - }); - - return services; - } -} diff --git a/src/Infrastructure/Files/CsvFileBuilder.cs b/src/Infrastructure/Files/CsvFileBuilder.cs deleted file mode 100644 index 5054ea0..0000000 --- a/src/Infrastructure/Files/CsvFileBuilder.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Globalization; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; -using SWD_Laundry_Backend.Infrastructure.Files.Maps; -using CsvHelper; - -namespace SWD_Laundry_Backend.Infrastructure.Files; - -public class CsvFileBuilder : ICsvFileBuilder -{ - public byte[] BuildTodoItemsFile(IEnumerable records) - { - using var memoryStream = new MemoryStream(); - using (var streamWriter = new StreamWriter(memoryStream)) - { - using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture); - - csvWriter.Context.RegisterClassMap(); - csvWriter.WriteRecords(records); - } - - return memoryStream.ToArray(); - } -} diff --git a/src/Infrastructure/Files/Maps/TodoItemRecordMap.cs b/src/Infrastructure/Files/Maps/TodoItemRecordMap.cs deleted file mode 100644 index 71198f1..0000000 --- a/src/Infrastructure/Files/Maps/TodoItemRecordMap.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Globalization; -using SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; -using CsvHelper.Configuration; - -namespace SWD_Laundry_Backend.Infrastructure.Files.Maps; - -public class TodoItemRecordMap : ClassMap -{ - public TodoItemRecordMap() - { - AutoMap(CultureInfo.InvariantCulture); - - Map(m => m.Done).Convert(c => c.Value.Done ? "Yes" : "No"); - } -} diff --git a/src/Infrastructure/Identity/IdentityResultExtensions.cs b/src/Infrastructure/Identity/IdentityResultExtensions.cs deleted file mode 100644 index 99ab0cd..0000000 --- a/src/Infrastructure/Identity/IdentityResultExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Models; -using Microsoft.AspNetCore.Identity; - -namespace SWD_Laundry_Backend.Infrastructure.Identity; - -public static class IdentityResultExtensions -{ - public static Result ToApplicationResult(this IdentityResult result) - { - return result.Succeeded - ? Result.Success() - : Result.Failure(result.Errors.Select(e => e.Description)); - } -} diff --git a/src/Infrastructure/Identity/IdentityService.cs b/src/Infrastructure/Identity/IdentityService.cs deleted file mode 100644 index c83b6ff..0000000 --- a/src/Infrastructure/Identity/IdentityService.cs +++ /dev/null @@ -1,82 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Application.Common.Models; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Infrastructure.Identity; - -public class IdentityService : IIdentityService -{ - private readonly UserManager _userManager; - private readonly IUserClaimsPrincipalFactory _userClaimsPrincipalFactory; - private readonly IAuthorizationService _authorizationService; - - public IdentityService( - UserManager userManager, - IUserClaimsPrincipalFactory userClaimsPrincipalFactory, - IAuthorizationService authorizationService) - { - _userManager = userManager; - _userClaimsPrincipalFactory = userClaimsPrincipalFactory; - _authorizationService = authorizationService; - } - - public async Task GetUserNameAsync(string userId) - { - var user = await _userManager.Users.FirstAsync(u => u.Id == userId); - - return user.UserName; - } - - public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password) - { - var user = new ApplicationUser - { - UserName = userName, - Email = userName, - }; - - var result = await _userManager.CreateAsync(user, password); - - return (result.ToApplicationResult(), user.Id); - } - - public async Task IsInRoleAsync(string userId, string role) - { - var user = _userManager.Users.SingleOrDefault(u => u.Id == userId); - - return user != null && await _userManager.IsInRoleAsync(user, role); - } - - public async Task AuthorizeAsync(string userId, string policyName) - { - var user = _userManager.Users.SingleOrDefault(u => u.Id == userId); - - if (user == null) - { - return false; - } - - var principal = await _userClaimsPrincipalFactory.CreateAsync(user); - - var result = await _authorizationService.AuthorizeAsync(principal, policyName); - - return result.Succeeded; - } - - public async Task DeleteUserAsync(string userId) - { - var user = _userManager.Users.SingleOrDefault(u => u.Id == userId); - - return user != null ? await DeleteUserAsync(user) : Result.Success(); - } - - public async Task DeleteUserAsync(ApplicationUser user) - { - var result = await _userManager.DeleteAsync(user); - - return result.ToApplicationResult(); - } -} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj deleted file mode 100644 index df1a672..0000000 --- a/src/Infrastructure/Infrastructure.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - - net7.0 - SWD_Laundry_Backend.Infrastructure - SWD_Laundry_Backend.Infrastructure - enable - enable - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs b/src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs deleted file mode 100644 index 388ad39..0000000 --- a/src/Infrastructure/Migrations/20230926215325_InitMigration.Designer.cs +++ /dev/null @@ -1,1346 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SWD_Laundry_Backend.Infrastructure.Persistence; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20230926215325_InitMigration")] - partial class InitMigration - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("LaundryStoreService", b => - { - b.Property("LaundryStoresId") - .HasColumnType("int"); - - b.Property("ServicesId") - .HasColumnType("int"); - - b.HasKey("LaundryStoresId", "ServicesId"); - - b.HasIndex("ServicesId"); - - b.ToTable("LaundryStoreService"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Buildings"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("BuildingID"); - - b.ToTable("Customers"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("Status") - .HasColumnType("bit"); - - b.Property("WalletId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("WalletId"); - - b.ToTable("LaundryStores"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDone") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LaundryStoreID") - .HasColumnType("int"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("LaundryStoreID"); - - b.HasIndex("OrderID"); - - b.ToTable("LaundryStoreOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Amount") - .HasColumnType("smallint"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("CustomerID") - .HasColumnType("int"); - - b.Property("ExpectedFinishDate") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LaundryStoreId") - .HasColumnType("int"); - - b.Property("OrderDate") - .HasColumnType("datetime2"); - - b.Property("OrderType") - .HasColumnType("int"); - - b.Property("PaymentMethodID") - .HasColumnType("int"); - - b.Property("StaffId") - .HasColumnType("int"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.Property("TotalPrice") - .HasColumnType("float"); - - b.HasKey("Id"); - - b.HasIndex("CustomerID"); - - b.HasIndex("LaundryStoreId"); - - b.HasIndex("PaymentMethodID"); - - b.HasIndex("StaffId"); - - b.ToTable("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("Status") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.ToTable("OrdersHistory"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("PaymentMethods"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Service"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Dob") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Salary") - .HasColumnType("float"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.ToTable("Staffs"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDone") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.HasIndex("StaffID"); - - b.ToTable("StaffOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("TimeScheduleID") - .HasColumnType("int"); - - b.Property("TripCollect") - .HasColumnType("int"); - - b.Property("TripStatus") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("BuildingID"); - - b.HasIndex("StaffID"); - - b.HasIndex("TimeScheduleID"); - - b.ToTable("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("DayOfWeek") - .HasColumnType("int"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TimeSchedules"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("PaymentMethod") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TransactionType") - .HasColumnType("int"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WalletID"); - - b.ToTable("Transactions"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Balance") - .HasColumnType("float"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Wallets"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.HasIndex("WalletID") - .IsUnique(); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("LaundryStoreService", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", null) - .WithMany() - .HasForeignKey("LaundryStoresId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", null) - .WithMany() - .HasForeignKey("ServicesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany("Customers") - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Building"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletId"); - - b.Navigation("ApplicationUser"); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany() - .HasForeignKey("LaundryStoreID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany() - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("LaundryStore"); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") - .WithMany("Order") - .HasForeignKey("CustomerID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany() - .HasForeignKey("LaundryStoreId"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") - .WithMany("Orders") - .HasForeignKey("PaymentMethodID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany() - .HasForeignKey("StaffId"); - - b.Navigation("Customer"); - - b.Navigation("LaundryStore"); - - b.Navigation("PaymentMethod"); - - b.Navigation("Staff"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany("OrderHistories") - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.Navigation("ApplicationUser"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany("StaffOrders") - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("StaffOrders") - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - - b.Navigation("Staff"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany("Staff_Trips") - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Staff_Trips") - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") - .WithMany("Staff_Trip") - .HasForeignKey("TimeScheduleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Building"); - - b.Navigation("Staff"); - - b.Navigation("TimeSchedule"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.OwnsOne("SWD_Laundry_Backend.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany("Transactions") - .HasForeignKey("WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("ApplicationUser") - .HasForeignKey("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Navigation("Customers"); - - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Navigation("OrderHistories"); - - b.Navigation("StaffOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Navigation("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Navigation("StaffOrders"); - - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => - { - b.Navigation("Staff_Trip"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Navigation("ApplicationUser"); - - b.Navigation("Transactions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Migrations/20230926215325_InitMigration.cs b/src/Infrastructure/Migrations/20230926215325_InitMigration.cs deleted file mode 100644 index 90cf6da..0000000 --- a/src/Infrastructure/Migrations/20230926215325_InitMigration.cs +++ /dev/null @@ -1,943 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Migrations -{ - /// - public partial class InitMigration : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Buildings", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Buildings", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: false), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Version = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Use = table.Column(type: "nvarchar(450)", nullable: true), - Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - IsX509Certificate = table.Column(type: "bit", nullable: false), - DataProtected = table.Column(type: "bit", nullable: false), - Data = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PaymentMethods", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_PaymentMethods", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - ConsumedTime = table.Column(type: "datetime2", nullable: true), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - - migrationBuilder.CreateTable( - name: "Service", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Service", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "TimeSchedules", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - StartTime = table.Column(type: "datetime2", nullable: false), - EndTime = table.Column(type: "datetime2", nullable: false), - DayOfWeek = table.Column(type: "int", nullable: false), - TimeFrame = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TimeSchedules", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "TodoLists", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Colour_Code = table.Column(type: "nvarchar(max)", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoLists", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Wallets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Balance = table.Column(type: "float", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Wallets", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "TodoItems", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ListId = table.Column(type: "int", nullable: false), - Title = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Note = table.Column(type: "nvarchar(max)", nullable: true), - Priority = table.Column(type: "int", nullable: false), - Reminder = table.Column(type: "datetime2", nullable: true), - Done = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_TodoItems", x => x.Id); - table.ForeignKey( - name: "FK_TodoItems_TodoLists_ListId", - column: x => x.ListId, - principalTable: "TodoLists", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUsers_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Transactions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: true), - WalletID = table.Column(type: "int", nullable: false), - TransactionType = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Transactions", x => x.Id); - table.ForeignKey( - name: "FK_Transactions_Wallets_WalletID", - column: x => x.WalletID, - principalTable: "Wallets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), - UserId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - RoleId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Customers", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - BuildingID = table.Column(type: "int", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Customers", x => x.Id); - table.ForeignKey( - name: "FK_Customers_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Customers_Buildings_BuildingID", - column: x => x.BuildingID, - principalTable: "Buildings", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "LaundryStores", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: true), - Address = table.Column(type: "nvarchar(max)", nullable: true), - StartTime = table.Column(type: "datetime2", nullable: false), - EndTime = table.Column(type: "datetime2", nullable: false), - Status = table.Column(type: "bit", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - WalletId = table.Column(type: "int", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStores", x => x.Id); - table.ForeignKey( - name: "FK_LaundryStores_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_LaundryStores_Wallets_WalletId", - column: x => x.WalletId, - principalTable: "Wallets", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "Staffs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Dob = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Salary = table.Column(type: "float", nullable: false), - ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Staffs", x => x.Id); - table.ForeignKey( - name: "FK_Staffs_AspNetUsers_ApplicationUserID", - column: x => x.ApplicationUserID, - principalTable: "AspNetUsers", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "LaundryStoreService", - columns: table => new - { - LaundryStoresId = table.Column(type: "int", nullable: false), - ServicesId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStoreService", x => new { x.LaundryStoresId, x.ServicesId }); - table.ForeignKey( - name: "FK_LaundryStoreService_LaundryStores_LaundryStoresId", - column: x => x.LaundryStoresId, - principalTable: "LaundryStores", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_LaundryStoreService_Service_ServicesId", - column: x => x.ServicesId, - principalTable: "Service", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Orders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderDate = table.Column(type: "datetime2", nullable: false), - TimeFrame = table.Column(type: "int", nullable: false), - ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), - Address = table.Column(type: "nvarchar(max)", nullable: true), - Amount = table.Column(type: "smallint", nullable: false), - TotalPrice = table.Column(type: "float", nullable: false), - PaymentMethodID = table.Column(type: "int", nullable: false), - CustomerID = table.Column(type: "int", nullable: false), - LaundryStoreId = table.Column(type: "int", nullable: true), - StaffId = table.Column(type: "int", nullable: true), - OrderType = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Orders", x => x.Id); - table.ForeignKey( - name: "FK_Orders_Customers_CustomerID", - column: x => x.CustomerID, - principalTable: "Customers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_LaundryStores_LaundryStoreId", - column: x => x.LaundryStoreId, - principalTable: "LaundryStores", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Orders_PaymentMethods_PaymentMethodID", - column: x => x.PaymentMethodID, - principalTable: "PaymentMethods", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Orders_Staffs_StaffId", - column: x => x.StaffId, - principalTable: "Staffs", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "Staff_Trips", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - TripCollect = table.Column(type: "int", nullable: false), - StaffID = table.Column(type: "int", nullable: false), - TimeScheduleID = table.Column(type: "int", nullable: false), - BuildingID = table.Column(type: "int", nullable: false), - TripStatus = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Staff_Trips", x => x.Id); - table.ForeignKey( - name: "FK_Staff_Trips_Buildings_BuildingID", - column: x => x.BuildingID, - principalTable: "Buildings", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Staff_Trips_Staffs_StaffID", - column: x => x.StaffID, - principalTable: "Staffs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Staff_Trips_TimeSchedules_TimeScheduleID", - column: x => x.TimeScheduleID, - principalTable: "TimeSchedules", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "LaundryStoreOrders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IsDone = table.Column(type: "bit", nullable: false), - OrderID = table.Column(type: "int", nullable: false), - LaundryStoreID = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_LaundryStoreOrders", x => x.Id); - table.ForeignKey( - name: "FK_LaundryStoreOrders_LaundryStores_LaundryStoreID", - column: x => x.LaundryStoreID, - principalTable: "LaundryStores", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_LaundryStoreOrders_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "OrdersHistory", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - OrderID = table.Column(type: "int", nullable: false), - Status = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OrdersHistory", x => x.Id); - table.ForeignKey( - name: "FK_OrdersHistory_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "StaffOrders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IsDone = table.Column(type: "bit", nullable: false), - Type = table.Column(type: "int", nullable: false), - StaffID = table.Column(type: "int", nullable: false), - OrderID = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_StaffOrders", x => x.Id); - table.ForeignKey( - name: "FK_StaffOrders_Orders_OrderID", - column: x => x.OrderID, - principalTable: "Orders", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_StaffOrders_Staffs_StaffID", - column: x => x.StaffID, - principalTable: "Staffs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUsers_WalletID", - table: "AspNetUsers", - column: "WalletID", - unique: true); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_Customers_ApplicationUserID", - table: "Customers", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_Customers_BuildingID", - table: "Customers", - column: "BuildingID"); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStoreOrders_LaundryStoreID", - table: "LaundryStoreOrders", - column: "LaundryStoreID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStoreOrders_OrderID", - table: "LaundryStoreOrders", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStores_ApplicationUserID", - table: "LaundryStores", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStores_WalletId", - table: "LaundryStores", - column: "WalletId"); - - migrationBuilder.CreateIndex( - name: "IX_LaundryStoreService_ServicesId", - table: "LaundryStoreService", - column: "ServicesId"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_CustomerID", - table: "Orders", - column: "CustomerID"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_LaundryStoreId", - table: "Orders", - column: "LaundryStoreId"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_PaymentMethodID", - table: "Orders", - column: "PaymentMethodID"); - - migrationBuilder.CreateIndex( - name: "IX_Orders_StaffId", - table: "Orders", - column: "StaffId"); - - migrationBuilder.CreateIndex( - name: "IX_OrdersHistory_OrderID", - table: "OrdersHistory", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_Staff_Trips_BuildingID", - table: "Staff_Trips", - column: "BuildingID"); - - migrationBuilder.CreateIndex( - name: "IX_Staff_Trips_StaffID", - table: "Staff_Trips", - column: "StaffID"); - - migrationBuilder.CreateIndex( - name: "IX_Staff_Trips_TimeScheduleID", - table: "Staff_Trips", - column: "TimeScheduleID"); - - migrationBuilder.CreateIndex( - name: "IX_StaffOrders_OrderID", - table: "StaffOrders", - column: "OrderID"); - - migrationBuilder.CreateIndex( - name: "IX_StaffOrders_StaffID", - table: "StaffOrders", - column: "StaffID"); - - migrationBuilder.CreateIndex( - name: "IX_Staffs_ApplicationUserID", - table: "Staffs", - column: "ApplicationUserID"); - - migrationBuilder.CreateIndex( - name: "IX_TodoItems_ListId", - table: "TodoItems", - column: "ListId"); - - migrationBuilder.CreateIndex( - name: "IX_Transactions_WalletID", - table: "Transactions", - column: "WalletID"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - - migrationBuilder.DropTable( - name: "LaundryStoreOrders"); - - migrationBuilder.DropTable( - name: "LaundryStoreService"); - - migrationBuilder.DropTable( - name: "OrdersHistory"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - - migrationBuilder.DropTable( - name: "Staff_Trips"); - - migrationBuilder.DropTable( - name: "StaffOrders"); - - migrationBuilder.DropTable( - name: "TodoItems"); - - migrationBuilder.DropTable( - name: "Transactions"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "Service"); - - migrationBuilder.DropTable( - name: "TimeSchedules"); - - migrationBuilder.DropTable( - name: "Orders"); - - migrationBuilder.DropTable( - name: "TodoLists"); - - migrationBuilder.DropTable( - name: "Customers"); - - migrationBuilder.DropTable( - name: "LaundryStores"); - - migrationBuilder.DropTable( - name: "PaymentMethods"); - - migrationBuilder.DropTable( - name: "Staffs"); - - migrationBuilder.DropTable( - name: "Buildings"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - - migrationBuilder.DropTable( - name: "Wallets"); - } - } -} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 306b86a..0000000 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,1343 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SWD_Laundry_Backend.Infrastructure.Persistence; - -#nullable disable - -namespace SWD_Laundry_Backend.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("LaundryStoreService", b => - { - b.Property("LaundryStoresId") - .HasColumnType("int"); - - b.Property("ServicesId") - .HasColumnType("int"); - - b.HasKey("LaundryStoresId", "ServicesId"); - - b.HasIndex("ServicesId"); - - b.ToTable("LaundryStoreService"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderKey") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Name") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Buildings"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("BuildingID"); - - b.ToTable("Customers"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("Status") - .HasColumnType("bit"); - - b.Property("WalletId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.HasIndex("WalletId"); - - b.ToTable("LaundryStores"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDone") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LaundryStoreID") - .HasColumnType("int"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("LaundryStoreID"); - - b.HasIndex("OrderID"); - - b.ToTable("LaundryStoreOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Amount") - .HasColumnType("smallint"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("CustomerID") - .HasColumnType("int"); - - b.Property("ExpectedFinishDate") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LaundryStoreId") - .HasColumnType("int"); - - b.Property("OrderDate") - .HasColumnType("datetime2"); - - b.Property("OrderType") - .HasColumnType("int"); - - b.Property("PaymentMethodID") - .HasColumnType("int"); - - b.Property("StaffId") - .HasColumnType("int"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.Property("TotalPrice") - .HasColumnType("float"); - - b.HasKey("Id"); - - b.HasIndex("CustomerID"); - - b.HasIndex("LaundryStoreId"); - - b.HasIndex("PaymentMethodID"); - - b.HasIndex("StaffId"); - - b.ToTable("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("Status") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.ToTable("OrdersHistory"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("PaymentMethods"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Service", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Service"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("ApplicationUserID") - .HasColumnType("nvarchar(450)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Dob") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Salary") - .HasColumnType("float"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationUserID"); - - b.ToTable("Staffs"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDone") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("OrderID") - .HasColumnType("int"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OrderID"); - - b.HasIndex("StaffID"); - - b.ToTable("StaffOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("BuildingID") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StaffID") - .HasColumnType("int"); - - b.Property("TimeScheduleID") - .HasColumnType("int"); - - b.Property("TripCollect") - .HasColumnType("int"); - - b.Property("TripStatus") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("BuildingID"); - - b.HasIndex("StaffID"); - - b.HasIndex("TimeScheduleID"); - - b.ToTable("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("DayOfWeek") - .HasColumnType("int"); - - b.Property("EndTime") - .HasColumnType("datetime2"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("StartTime") - .HasColumnType("datetime2"); - - b.Property("TimeFrame") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("TimeSchedules"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Done") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("ListId") - .HasColumnType("int"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("Priority") - .HasColumnType("int"); - - b.Property("Reminder") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ListId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.ToTable("TodoLists"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Amount") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("PaymentMethod") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TransactionType") - .HasColumnType("int"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WalletID"); - - b.ToTable("Transactions"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Balance") - .HasColumnType("float"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Wallets"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - 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") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("WalletID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.HasIndex("WalletID") - .IsUnique(); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("LaundryStoreService", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", null) - .WithMany() - .HasForeignKey("LaundryStoresId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Service", null) - .WithMany() - .HasForeignKey("ServicesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany("Customers") - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApplicationUser"); - - b.Navigation("Building"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStore", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany() - .HasForeignKey("WalletId"); - - b.Navigation("ApplicationUser"); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.LaundryStoreOrder", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany() - .HasForeignKey("LaundryStoreID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany() - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("LaundryStore"); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Customer", "Customer") - .WithMany("Order") - .HasForeignKey("CustomerID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.LaundryStore", "LaundryStore") - .WithMany() - .HasForeignKey("LaundryStoreId"); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", "PaymentMethod") - .WithMany("Orders") - .HasForeignKey("PaymentMethodID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany() - .HasForeignKey("StaffId"); - - b.Navigation("Customer"); - - b.Navigation("LaundryStore"); - - b.Navigation("PaymentMethod"); - - b.Navigation("Staff"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.OrderHistory", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany("OrderHistories") - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "ApplicationUser") - .WithMany() - .HasForeignKey("ApplicationUserID"); - - b.Navigation("ApplicationUser"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.StaffOrder", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Order", "Order") - .WithMany("StaffOrders") - .HasForeignKey("OrderID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("StaffOrders") - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Order"); - - b.Navigation("Staff"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff_Trip", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Building", "Building") - .WithMany("Staff_Trips") - .HasForeignKey("BuildingID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Staff", "Staff") - .WithMany("Staff_Trips") - .HasForeignKey("StaffID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", "TimeSchedule") - .WithMany("Staff_Trip") - .HasForeignKey("TimeScheduleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Building"); - - b.Navigation("Staff"); - - b.Navigation("TimeSchedule"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoItem", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.TodoList", "List") - .WithMany("Items") - .HasForeignKey("ListId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("List"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.OwnsOne("SWD_Laundry_Backend.Domain.ValueObjects.Colour", "Colour", b1 => - { - b1.Property("TodoListId") - .HasColumnType("int"); - - b1.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TodoListId"); - - b1.ToTable("TodoLists"); - - b1.WithOwner() - .HasForeignKey("TodoListId"); - }); - - b.Navigation("Colour") - .IsRequired(); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Transaction", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithMany("Transactions") - .HasForeignKey("WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", b => - { - b.HasOne("SWD_Laundry_Backend.Domain.Entities.Wallet", "Wallet") - .WithOne("ApplicationUser") - .HasForeignKey("SWD_Laundry_Backend.Domain.IdentityModel.ApplicationUser", "WalletID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Wallet"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Building", b => - { - b.Navigation("Customers"); - - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Customer", b => - { - b.Navigation("Order"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Order", b => - { - b.Navigation("OrderHistories"); - - b.Navigation("StaffOrders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.PaymentMethod", b => - { - b.Navigation("Orders"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Staff", b => - { - b.Navigation("StaffOrders"); - - b.Navigation("Staff_Trips"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TimeSchedule", b => - { - b.Navigation("Staff_Trip"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.TodoList", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("SWD_Laundry_Backend.Domain.Entities.Wallet", b => - { - b.Navigation("ApplicationUser"); - - b.Navigation("Transactions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Infrastructure/Persistence/ApplicationDbContext.cs b/src/Infrastructure/Persistence/ApplicationDbContext.cs deleted file mode 100644 index c07c24e..0000000 --- a/src/Infrastructure/Persistence/ApplicationDbContext.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Reflection; -using Duende.IdentityServer.EntityFramework.Options; -using MediatR; -using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Common; -using SWD_Laundry_Backend.Domain.Entities; - -using SWD_Laundry_Backend.Domain.IdentityModel; -using SWD_Laundry_Backend.Infrastructure.Persistence.Interceptors; - -namespace SWD_Laundry_Backend.Infrastructure.Persistence; - -public class ApplicationDbContext : ApiAuthorizationDbContext, IApplicationDbContext -{ - private readonly IMediator _mediator; - private readonly AuditableEntitySaveChangesInterceptor _auditableEntitySaveChangesInterceptor; - - public ApplicationDbContext( - DbContextOptions options, - IOptions operationalStoreOptions, - IMediator mediator, - AuditableEntitySaveChangesInterceptor auditableEntitySaveChangesInterceptor) - : base(options, operationalStoreOptions) - { - _mediator = mediator; - _auditableEntitySaveChangesInterceptor = auditableEntitySaveChangesInterceptor; - } - - public DbSet TodoLists => Set(); - - public DbSet TodoItems => Set(); - - - public DbSet TimeSchedules => Set(); - public DbSet ApplicationUsers => Set(); - public DbSet LaundryStoreOrders => Set(); - public DbSet StaffOrders => Set(); - public DbSet Buildings => Set(); - public DbSet Customers => Set(); - public DbSet LaundryStores => Set(); - public DbSet Orders => Set(); - public DbSet OrdersHistory => Set(); - public DbSet PaymentMethods => Set(); - public DbSet Staff_Trips => Set(); - public DbSet Staffs => Set(); - - - public DbSet Transactions => Set(); - public DbSet Wallets => Set(); - - protected override void OnModelCreating(ModelBuilder builder) - { - builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); - - base.OnModelCreating(builder); - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.AddInterceptors(_auditableEntitySaveChangesInterceptor); - } - - public override async Task SaveChangesAsync(CancellationToken cancellationToken = default) - { - await _mediator.DispatchDomainEvents(this); - - return await base.SaveChangesAsync(cancellationToken); - } - - public DbSet Get() where T : BaseAuditableEntity => Set(); -} \ No newline at end of file diff --git a/src/Infrastructure/Persistence/ApplicationDbContextInitialiser.cs b/src/Infrastructure/Persistence/ApplicationDbContextInitialiser.cs deleted file mode 100644 index 243c9aa..0000000 --- a/src/Infrastructure/Persistence/ApplicationDbContextInitialiser.cs +++ /dev/null @@ -1,115 +0,0 @@ -using SWD_Laundry_Backend.Domain.Entities; -using SWD_Laundry_Backend.Infrastructure.Identity; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using SWD_Laundry_Backend.Domain.IdentityModel; - -namespace SWD_Laundry_Backend.Infrastructure.Persistence; - -public class ApplicationDbContextInitialiser -{ - private readonly ILogger _logger; - private readonly ApplicationDbContext _context; - private readonly UserManager _userManager; - private readonly RoleManager _roleManager; - - public ApplicationDbContextInitialiser(ILogger logger, ApplicationDbContext context, UserManager userManager, RoleManager roleManager) - { - _logger = logger; - _context = context; - _userManager = userManager; - _roleManager = roleManager; - } - - public async Task InitialiseAsync() - { - try - { - if (_context.Database.IsSqlServer()) - { - await _context.Database.MigrateAsync(); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "An error occurred while initialising the database."); - throw; - } - } - - public async Task SeedAsync() - { - try - { - await TrySeedAsync(); - } - catch (Exception ex) - { - _logger.LogError(ex, "An error occurred while seeding the database."); - throw; - } - } - - public async Task TrySeedAsync() - { - { - // Roles - var roles = new List - { - new IdentityRole("Customer"), - new IdentityRole("Staff"), - new IdentityRole("Store"), - new IdentityRole("Admin") - }; - - foreach (var role in roles) - { - - if (_roleManager.Roles.All(r => r.Name != role.Name)) - { - await _roleManager.CreateAsync(role); - } - } - - // Manager - var administrator = new ApplicationUser - { - UserName = "@dmin", - Email = "administrator@localhost", - - }; - - if (_userManager.Users.All(u => u.UserName != administrator.UserName)) - { - await _userManager.CreateAsync(administrator, "Aa123@"); - - var administratorRole = roles.FirstOrDefault(r => r.Name == "Admin"); - if (administratorRole != null) - { - await _userManager.AddToRoleAsync(administrator, administratorRole.Name); - } - - } - - // Default data - // Seed, if necessary - if (!_context.TodoLists.Any()) - { - _context.TodoLists.Add(new TodoList - { - Title = "Todo List", - Items = - { - new TodoItem { Title = "Make a todo list 📃" }, - new TodoItem { Title = "Check off the first item ✅" }, - new TodoItem { Title = "Realise you've already done two things on the list! 🤯"}, - new TodoItem { Title = "Reward yourself with a nice, long nap 🏆" }, - } - }); - - await _context.SaveChangesAsync(); - } - } - } -} \ No newline at end of file diff --git a/src/Infrastructure/Persistence/Configurations/TodoItemConfiguration.cs b/src/Infrastructure/Persistence/Configurations/TodoItemConfiguration.cs deleted file mode 100644 index 577a848..0000000 --- a/src/Infrastructure/Persistence/Configurations/TodoItemConfiguration.cs +++ /dev/null @@ -1,15 +0,0 @@ -using SWD_Laundry_Backend.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Configurations; - -public class TodoItemConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.Property(t => t.Title) - .HasMaxLength(200) - .IsRequired(); - } -} diff --git a/src/Infrastructure/Persistence/Configurations/TodoListConfiguration.cs b/src/Infrastructure/Persistence/Configurations/TodoListConfiguration.cs deleted file mode 100644 index ecfe530..0000000 --- a/src/Infrastructure/Persistence/Configurations/TodoListConfiguration.cs +++ /dev/null @@ -1,18 +0,0 @@ -using SWD_Laundry_Backend.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Configurations; - -public class TodoListConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.Property(t => t.Title) - .HasMaxLength(200) - .IsRequired(); - - builder - .OwnsOne(b => b.Colour); - } -} diff --git a/src/Infrastructure/Persistence/Interceptors/AuditableEntitySaveChangesInterceptor.cs b/src/Infrastructure/Persistence/Interceptors/AuditableEntitySaveChangesInterceptor.cs deleted file mode 100644 index 6cf8d62..0000000 --- a/src/Infrastructure/Persistence/Interceptors/AuditableEntitySaveChangesInterceptor.cs +++ /dev/null @@ -1,64 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Domain.Common; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Diagnostics; - -namespace SWD_Laundry_Backend.Infrastructure.Persistence.Interceptors; - -public class AuditableEntitySaveChangesInterceptor : SaveChangesInterceptor -{ - private readonly ICurrentUserService _currentUserService; - private readonly IDateTime _dateTime; - - public AuditableEntitySaveChangesInterceptor( - ICurrentUserService currentUserService, - IDateTime dateTime) - { - _currentUserService = currentUserService; - _dateTime = dateTime; - } - - public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) - { - UpdateEntities(eventData.Context); - - return base.SavingChanges(eventData, result); - } - - public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default) - { - UpdateEntities(eventData.Context); - - return base.SavingChangesAsync(eventData, result, cancellationToken); - } - - public void UpdateEntities(DbContext? context) - { - if (context == null) return; - - foreach (var entry in context.ChangeTracker.Entries()) - { - if (entry.State == EntityState.Added) - { - entry.Entity.CreatedBy = _currentUserService.UserId; - entry.Entity.Created = _dateTime.Now; - } - - if (entry.State == EntityState.Added || entry.State == EntityState.Modified || entry.HasChangedOwnedEntities()) - { - entry.Entity.LastModifiedBy = _currentUserService.UserId; - entry.Entity.LastModified = _dateTime.Now; - } - } - } -} - -public static class Extensions -{ - public static bool HasChangedOwnedEntities(this EntityEntry entry) => - entry.References.Any(r => - r.TargetEntry != null && - r.TargetEntry.Metadata.IsOwned() && - (r.TargetEntry.State == EntityState.Added || r.TargetEntry.State == EntityState.Modified)); -} diff --git a/src/Infrastructure/Services/DateTimeService.cs b/src/Infrastructure/Services/DateTimeService.cs deleted file mode 100644 index de89b99..0000000 --- a/src/Infrastructure/Services/DateTimeService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; - -namespace SWD_Laundry_Backend.Infrastructure.Services; - -public class DateTimeService : IDateTime -{ - public DateTime Now => DateTime.Now; -} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Class1.cs b/src/SWD-Laundry-Backend.Contract.Repository/Class1.cs new file mode 100644 index 0000000..e8f30e5 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Class1.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Contract.Repository; + +public class Class1 +{ + +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj new file mode 100644 index 0000000..77dcfe3 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj @@ -0,0 +1,10 @@ + + + + net7.0 + SWD_Laundry_Backend.Contract.Repository + enable + enable + + + diff --git a/src/SWD-Laundry-Backend.Contract.Service/Class1.cs b/src/SWD-Laundry-Backend.Contract.Service/Class1.cs new file mode 100644 index 0000000..522b55a --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Class1.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Contract.Service; + +public class Class1 +{ + +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj new file mode 100644 index 0000000..c7f524b --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj @@ -0,0 +1,10 @@ + + + + net7.0 + SWD_Laundry_Backend.Contract.Service + enable + enable + + + diff --git a/src/SWD-Laundry-Backend.Core/Class1.cs b/src/SWD-Laundry-Backend.Core/Class1.cs new file mode 100644 index 0000000..90950a3 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Class1.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Core; + +public class Class1 +{ + +} diff --git a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj new file mode 100644 index 0000000..6f6cf3a --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + SWD_Laundry_Backend.Core + enable + enable + + + + + + + diff --git a/src/SWD-Laundry-Backend.Mapper/Class1.cs b/src/SWD-Laundry-Backend.Mapper/Class1.cs new file mode 100644 index 0000000..2d79800 --- /dev/null +++ b/src/SWD-Laundry-Backend.Mapper/Class1.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Mapper; + +public class Class1 +{ + +} diff --git a/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj b/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj new file mode 100644 index 0000000..02abd3d --- /dev/null +++ b/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj @@ -0,0 +1,10 @@ + + + + net7.0 + SWD_Laundry_Backend.Mapper + enable + enable + + + diff --git a/src/SWD-Laundry-Backend.Repository/Class1.cs b/src/SWD-Laundry-Backend.Repository/Class1.cs new file mode 100644 index 0000000..3d9a4c3 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Class1.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Repository; + +public class Class1 +{ + +} diff --git a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj new file mode 100644 index 0000000..0dbe32a --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj @@ -0,0 +1,10 @@ + + + + net7.0 + SWD_Laundry_Backend.Repository + enable + enable + + + diff --git a/src/SWD-Laundry-Backend.Service/Class1.cs b/src/SWD-Laundry-Backend.Service/Class1.cs new file mode 100644 index 0000000..f9afaaa --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Class1.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Service; + +public class Class1 +{ + +} diff --git a/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj b/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj new file mode 100644 index 0000000..4089cd6 --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj @@ -0,0 +1,10 @@ + + + + net7.0 + SWD_Laundry_Backend.Service + enable + enable + + + diff --git a/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs b/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..87bbfeb --- /dev/null +++ b/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Mvc; + +namespace SWD_Laundry_Backend.Controllers; +[ApiController] +[Route("[controller]")] +public class WeatherForecastController : ControllerBase +{ + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } +} diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs new file mode 100644 index 0000000..93efa15 --- /dev/null +++ b/src/SWD-Laundry-Backend/Program.cs @@ -0,0 +1,39 @@ +using Serilog; +namespace SWD_Laundry_Backend; + +public class Program +{ + public static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + + // Add services to the container. + + builder.Host.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration + .ReadFrom.Configuration(hostingContext.Configuration) + .Enrich.FromLogContext() + .WriteTo.Console()); + builder.Services.AddControllers(); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen(); + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(); + } + + app.UseHttpsRedirection(); + + app.UseAuthorization(); + + + app.MapControllers(); + + app.Run(); + } +} diff --git a/src/SWD-Laundry-Backend/Properties/launchSettings.json b/src/SWD-Laundry-Backend/Properties/launchSettings.json new file mode 100644 index 0000000..2cb5d0e --- /dev/null +++ b/src/SWD-Laundry-Backend/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:52121", + "sslPort": 44389 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5130", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7220;http://localhost:5130", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj new file mode 100644 index 0000000..c657e66 --- /dev/null +++ b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj @@ -0,0 +1,19 @@ + + + + net7.0 + enable + enable + SWD_Laundry_Backend + + + + + + + + + + + + diff --git a/src/SWD-Laundry-Backend/WeatherForecast.cs b/src/SWD-Laundry-Backend/WeatherForecast.cs new file mode 100644 index 0000000..205d2ab --- /dev/null +++ b/src/SWD-Laundry-Backend/WeatherForecast.cs @@ -0,0 +1,12 @@ +namespace SWD_Laundry_Backend; + +public class WeatherForecast +{ + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } +} diff --git a/src/SWD-Laundry-Backend/appsettings.Development.json b/src/SWD-Laundry-Backend/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/src/SWD-Laundry-Backend/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/SWD-Laundry-Backend/appsettings.json b/src/SWD-Laundry-Backend/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/src/SWD-Laundry-Backend/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/WebUI/.config/dotnet-tools.json b/src/WebUI/.config/dotnet-tools.json deleted file mode 100644 index 96be437..0000000 --- a/src/WebUI/.config/dotnet-tools.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "dotnet-ef": { - "version": "7.0.11", - "commands": [ - "dotnet-ef" - ] - } - } -} \ No newline at end of file diff --git a/src/WebUI/ConfigureServices.cs b/src/WebUI/ConfigureServices.cs deleted file mode 100644 index b73980b..0000000 --- a/src/WebUI/ConfigureServices.cs +++ /dev/null @@ -1,61 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Interfaces; -using SWD_Laundry_Backend.Infrastructure.Persistence; -using SWD_Laundry_Backend.WebUI.Services; -using Microsoft.AspNetCore.Mvc; -using NSwag; -using NSwag.Generation.Processors.Security; -using ZymLabs.NSwag.FluentValidation; - -namespace Microsoft.Extensions.DependencyInjection; - -public static class ConfigureServices -{ - public static IServiceCollection AddWebUIServices(this IServiceCollection services) - { - services.AddDatabaseDeveloperPageExceptionFilter(); - - services.AddScoped(); - - services.AddHttpContextAccessor(); - - services.AddHealthChecks() - .AddDbContextCheck(); - - services.AddControllersWithViews(); - - services.AddRazorPages(); - - services.AddScoped(provider => - { - var validationRules = provider.GetService>(); - var loggerFactory = provider.GetService(); - - return new FluentValidationSchemaProcessor(provider, validationRules, loggerFactory); - }); - - // Customise default API behaviour - services.Configure(options => - options.SuppressModelStateInvalidFilter = true); - - services.AddOpenApiDocument((configure, serviceProvider) => - { - var fluentValidationSchemaProcessor = serviceProvider.CreateScope().ServiceProvider.GetRequiredService(); - - // Add the fluent validations schema processor - configure.SchemaProcessors.Add(fluentValidationSchemaProcessor); - - configure.Title = "SWD_Laundry_Backend API"; - configure.AddSecurity("JWT", Enumerable.Empty(), new OpenApiSecurityScheme - { - Type = OpenApiSecuritySchemeType.ApiKey, - Name = "Authorization", - In = OpenApiSecurityApiKeyLocation.Header, - Description = "Type into the textbox: Bearer {your JWT token}." - }); - - configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("JWT")); - }); - - return services; - } -} diff --git a/src/WebUI/Controllers/ApiControllerBase.cs b/src/WebUI/Controllers/ApiControllerBase.cs deleted file mode 100644 index 48dcf5f..0000000 --- a/src/WebUI/Controllers/ApiControllerBase.cs +++ /dev/null @@ -1,15 +0,0 @@ -using SWD_Laundry_Backend.WebUI.Filters; -using MediatR; -using Microsoft.AspNetCore.Mvc; - -namespace SWD_Laundry_Backend.WebUI.Controllers; - -[ApiController] -[ApiExceptionFilter] -[Route("api/[controller]")] -public abstract class ApiControllerBase : ControllerBase -{ - private ISender? _mediator; - - protected ISender Mediator => _mediator ??= HttpContext.RequestServices.GetRequiredService(); -} diff --git a/src/WebUI/Controllers/BuildingController.cs b/src/WebUI/Controllers/BuildingController.cs deleted file mode 100644 index 1fa3117..0000000 --- a/src/WebUI/Controllers/BuildingController.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using SWD_Laundry_Backend.Application.Buildings.Commands.CreateBuilding; -using SWD_Laundry_Backend.Application.Buildings.Commands.DeleteBuilding; -using SWD_Laundry_Backend.Application.Buildings.Commands.UpdateBuilding; -using SWD_Laundry_Backend.Application.Buildings.Queries; -using SWD_Laundry_Backend.WebUI.Controllers; - -// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 - -namespace WebUI.Controllers; -[ApiController] -public class BuildingController : ApiControllerBase -{ - // GET: api/ - [HttpGet] - public async Task>> Get() - { - return await Mediator.Send(new GetAllBuildingQuery()); - } - - // GET api//5 - [HttpGet("{id}")] - public async Task> Get(int id) - { - return await Mediator.Send(new GetBuildingQuery { Id = id }); - } - - // POST api/ - [HttpPost] - public async Task> Post([FromBody] CreateBuildingCommand command) - { - return await Mediator.Send(command); - } - - // PUT api//5 - [HttpPut] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [ProducesDefaultResponseType] - public async Task> Put([FromBody] UpdateBuildingCommand command) - { - return await Mediator.Send(command); - } - - // DELETE api//5 - [HttpDelete("{id}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesDefaultResponseType] - public async Task> Delete(int id) - { - return await Mediator.Send(new DeleteBuildingCommand { Id = id }); - } -} diff --git a/src/WebUI/Controllers/OidcConfigurationController.cs b/src/WebUI/Controllers/OidcConfigurationController.cs deleted file mode 100644 index 1d9874e..0000000 --- a/src/WebUI/Controllers/OidcConfigurationController.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; -using Microsoft.AspNetCore.Mvc; - -namespace SWD_Laundry_Backend.WebUI.Controllers; - -[ApiExplorerSettings(IgnoreApi = true)] -public class OidcConfigurationController : Controller -{ - private readonly ILogger _logger; - - public OidcConfigurationController( - IClientRequestParametersProvider clientRequestParametersProvider, - ILogger logger) - { - ClientRequestParametersProvider = clientRequestParametersProvider; - _logger = logger; - } - - public IClientRequestParametersProvider ClientRequestParametersProvider { get; } - - [HttpGet("_configuration/{clientId}")] - public IActionResult GetClientRequestParameters([FromRoute]string clientId) - { - var parameters = ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId); - return Ok(parameters); - } -} diff --git a/src/WebUI/Controllers/TodoItemsController.cs b/src/WebUI/Controllers/TodoItemsController.cs deleted file mode 100644 index bec3bf3..0000000 --- a/src/WebUI/Controllers/TodoItemsController.cs +++ /dev/null @@ -1,66 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Models; -using SWD_Laundry_Backend.Application.TodoItems.Commands.CreateTodoItem; -using SWD_Laundry_Backend.Application.TodoItems.Commands.DeleteTodoItem; -using SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItem; -using SWD_Laundry_Backend.Application.TodoItems.Commands.UpdateTodoItemDetail; -using SWD_Laundry_Backend.Application.TodoItems.Queries.GetTodoItemsWithPagination; -using Microsoft.AspNetCore.Mvc; - -namespace SWD_Laundry_Backend.WebUI.Controllers; - -public class TodoItemsController : ApiControllerBase -{ - [HttpGet] - public async Task>> GetTodoItemsWithPagination([FromQuery] GetTodoItemsWithPaginationQuery query) - { - return await Mediator.Send(query); - } - - [HttpPost] - public async Task> Create(CreateTodoItemCommand command) - { - return await Mediator.Send(command); - } - - [HttpPut("{id}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [ProducesDefaultResponseType] - public async Task Update(int id, UpdateTodoItemCommand command) - { - if (id != command.Id) - { - return BadRequest(); - } - - await Mediator.Send(command); - - return NoContent(); - } - - [HttpPut("[action]")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [ProducesDefaultResponseType] - public async Task UpdateItemDetails(int id, UpdateTodoItemDetailCommand command) - { - if (id != command.Id) - { - return BadRequest(); - } - - await Mediator.Send(command); - - return NoContent(); - } - - [HttpDelete("{id}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesDefaultResponseType] - public async Task Delete(int id) - { - await Mediator.Send(new DeleteTodoItemCommand(id)); - - return NoContent(); - } -} diff --git a/src/WebUI/Controllers/TodoListsController.cs b/src/WebUI/Controllers/TodoListsController.cs deleted file mode 100644 index 058ad45..0000000 --- a/src/WebUI/Controllers/TodoListsController.cs +++ /dev/null @@ -1,58 +0,0 @@ -using SWD_Laundry_Backend.Application.TodoLists.Commands.CreateTodoList; -using SWD_Laundry_Backend.Application.TodoLists.Commands.DeleteTodoList; -using SWD_Laundry_Backend.Application.TodoLists.Commands.UpdateTodoList; -using SWD_Laundry_Backend.Application.TodoLists.Queries.ExportTodos; -using SWD_Laundry_Backend.Application.TodoLists.Queries.GetTodos; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -namespace SWD_Laundry_Backend.WebUI.Controllers; - -public class TodoListsController : ApiControllerBase -{ - [HttpGet] - public async Task> Get() - { - return await Mediator.Send(new GetTodosQuery()); - } - - [HttpGet("{id}")] - public async Task Get(int id) - { - var vm = await Mediator.Send(new ExportTodosQuery { ListId = id }); - - return File(vm.Content, vm.ContentType, vm.FileName); - } - - [HttpPost] - public async Task> Create(CreateTodoListCommand command) - { - return await Mediator.Send(command); - } - - [HttpPut("{id}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [ProducesDefaultResponseType] - public async Task Update(int id, UpdateTodoListCommand command) - { - if (id != command.Id) - { - return BadRequest(); - } - - await Mediator.Send(command); - - return NoContent(); - } - - [HttpDelete("{id}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesDefaultResponseType] - public async Task Delete(int id) - { - await Mediator.Send(new DeleteTodoListCommand(id)); - - return NoContent(); - } -} diff --git a/src/WebUI/Controllers/WalletController.cs b/src/WebUI/Controllers/WalletController.cs deleted file mode 100644 index 8ca569d..0000000 --- a/src/WebUI/Controllers/WalletController.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using SWD_Laundry_Backend.Application.Wallets.Commands.CreateWallet; -using SWD_Laundry_Backend.Application.Wallets.Commands.DeleteWallet; -using SWD_Laundry_Backend.Application.Wallets.Commands.UpdateWallet; -using SWD_Laundry_Backend.Application.Wallets.Queries; -using SWD_Laundry_Backend.WebUI.Controllers; - -namespace WebUI.Controllers; - -public class WalletController : ApiControllerBase -{ - // GET: api/ - [HttpGet] - public async Task>> Get() - { - return await Mediator.Send(new GetAllWalletQuery()); - } - - // GET api//5 - [HttpGet("{id}")] - public async Task> Get(int id) - { - return await Mediator.Send(new GetWalletQuery { Id = id }); - } - - // POST api/ - [HttpPost] - public async Task> Post([FromBody] CreateWalletCommand command) - { - return await Mediator.Send(command); - } - - // PUT api//5 - [HttpPut] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [ProducesDefaultResponseType] - public async Task> Put([FromBody] UpdateWalletCommand command) - { - return await Mediator.Send(command); - } - - // DELETE api//5 - [HttpDelete("{id}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesDefaultResponseType] - public async Task> Delete(int id) - { - return await Mediator.Send(new DeleteWalletCommand { Id = id }); - } -} diff --git a/src/WebUI/Filters/ApiExceptionFilterAttribute.cs b/src/WebUI/Filters/ApiExceptionFilterAttribute.cs deleted file mode 100644 index 03ba816..0000000 --- a/src/WebUI/Filters/ApiExceptionFilterAttribute.cs +++ /dev/null @@ -1,122 +0,0 @@ -using SWD_Laundry_Backend.Application.Common.Exceptions; - -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; - -namespace SWD_Laundry_Backend.WebUI.Filters; - -public class ApiExceptionFilterAttribute : ExceptionFilterAttribute -{ - private readonly IDictionary> _exceptionHandlers; - - public ApiExceptionFilterAttribute() - { - // Register known exception types and handlers. - _exceptionHandlers = new Dictionary> - { - { typeof(ValidationException), HandleValidationException }, - { typeof(NotFoundException), HandleNotFoundException }, - { typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException }, - { typeof(ForbiddenAccessException), HandleForbiddenAccessException }, - }; - } - - public override void OnException(ExceptionContext context) - { - HandleException(context); - - base.OnException(context); - } - - private void HandleException(ExceptionContext context) - { - Type type = context.Exception.GetType(); - if (_exceptionHandlers.ContainsKey(type)) - { - _exceptionHandlers[type].Invoke(context); - return; - } - - if (!context.ModelState.IsValid) - { - HandleInvalidModelStateException(context); - return; - } - } - - private void HandleValidationException(ExceptionContext context) - { - var exception = (ValidationException)context.Exception; - - var details = new ValidationProblemDetails(exception.Errors) - { - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1" - }; - - context.Result = new BadRequestObjectResult(details); - - context.ExceptionHandled = true; - } - - private void HandleInvalidModelStateException(ExceptionContext context) - { - var details = new ValidationProblemDetails(context.ModelState) - { - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.1" - }; - - context.Result = new BadRequestObjectResult(details); - - context.ExceptionHandled = true; - } - - private void HandleNotFoundException(ExceptionContext context) - { - var exception = (NotFoundException)context.Exception; - - var details = new ProblemDetails() - { - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.4", - Title = "The specified resource was not found.", - Detail = exception.Message - }; - - context.Result = new NotFoundObjectResult(details); - - context.ExceptionHandled = true; - } - - private void HandleUnauthorizedAccessException(ExceptionContext context) - { - var details = new ProblemDetails - { - Status = StatusCodes.Status401Unauthorized, - Title = "Unauthorized", - Type = "https://tools.ietf.org/html/rfc7235#section-3.1" - }; - - context.Result = new ObjectResult(details) - { - StatusCode = StatusCodes.Status401Unauthorized - }; - - context.ExceptionHandled = true; - } - - private void HandleForbiddenAccessException(ExceptionContext context) - { - var details = new ProblemDetails - { - Status = StatusCodes.Status403Forbidden, - Title = "Forbidden", - Type = "https://tools.ietf.org/html/rfc7231#section-6.5.3" - }; - - context.Result = new ObjectResult(details) - { - StatusCode = StatusCodes.Status403Forbidden - }; - - context.ExceptionHandled = true; - } -} diff --git a/src/WebUI/Pages/Error.cshtml b/src/WebUI/Pages/Error.cshtml deleted file mode 100644 index 6f92b95..0000000 --- a/src/WebUI/Pages/Error.cshtml +++ /dev/null @@ -1,26 +0,0 @@ -@page -@model ErrorModel -@{ - ViewData["Title"] = "Error"; -} - -

Error.

-

An error occurred while processing your request.

- -@if (Model.ShowRequestId) -{ -

- Request ID: @Model.RequestId -

-} - -

Development Mode

-

- Swapping to the Development environment displays detailed information about the error that occurred. -

-

- The Development environment shouldn't be enabled for deployed applications. - It can result in displaying sensitive information from exceptions to end users. - For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development - and restarting the app. -

diff --git a/src/WebUI/Pages/Error.cshtml.cs b/src/WebUI/Pages/Error.cshtml.cs deleted file mode 100644 index 7ff1f7d..0000000 --- a/src/WebUI/Pages/Error.cshtml.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Diagnostics; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace SWD_Laundry_Backend.WebUI.Pages; - -[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] -public class ErrorModel : PageModel -{ - private readonly ILogger _logger; - - public ErrorModel(ILogger logger) - { - _logger = logger; - } - - public string? RequestId { get; set; } - - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } -} diff --git a/src/WebUI/Pages/_ViewImports.cshtml b/src/WebUI/Pages/_ViewImports.cshtml deleted file mode 100644 index 2eb7c2a..0000000 --- a/src/WebUI/Pages/_ViewImports.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@using SWD_Laundry_Backend.WebUI -@namespace SWD_Laundry_Backend.WebUI.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/WebUI/Program.cs b/src/WebUI/Program.cs deleted file mode 100644 index 9bd391b..0000000 --- a/src/WebUI/Program.cs +++ /dev/null @@ -1,58 +0,0 @@ -using NSwag.AspNetCore; -using SWD_Laundry_Backend.Infrastructure.Persistence; - -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. -builder.Services.AddLogging(); -builder.Services.AddApplicationServices(); -builder.Services.AddInfrastructureServices(builder.Configuration); -builder.Services.AddWebUIServices(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseDeveloperExceptionPage(); - app.UseMigrationsEndPoint(); - - // Initialise and seed database - using var scope = app.Services.CreateScope(); - var initialiser = scope.ServiceProvider.GetRequiredService(); - await initialiser.InitialiseAsync(); - await initialiser.SeedAsync(); -} -else -{ - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); -} - -app.UseHealthChecks("/health"); -app.UseHttpsRedirection(); -app.UseStaticFiles(); - -app.UseSwaggerUi3(settings => -{ - settings.Path = "/swagger/api"; - settings.DocumentPath = "/api/specification.json"; - settings.SwaggerRoutes.Add(new SwaggerUi3Route("v1.0", "/api/specification.json")); -}); - - -app.UseRouting(); - -app.UseAuthentication(); -app.UseIdentityServer(); -app.UseAuthorization(); - -app.MapControllerRoute( - name: "default", - pattern: "{controller}/{action=Index}/{id?}"); - -app.MapRazorPages(); - -app.MapFallbackToFile("index.html"); - -app.Run(); \ No newline at end of file diff --git a/src/WebUI/Properties/launchSettings.json b/src/WebUI/Properties/launchSettings.json deleted file mode 100644 index 8ea8aa1..0000000 --- a/src/WebUI/Properties/launchSettings.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:61846", - "sslPort": 44312 - } - }, - "profiles": { - "SWD_Laundry_Backend.WebUI": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "swagger/api/index.html", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "swagger/api/index.html", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/src/WebUI/Services/CurrentUserService.cs b/src/WebUI/Services/CurrentUserService.cs deleted file mode 100644 index 8ec2bfa..0000000 --- a/src/WebUI/Services/CurrentUserService.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Security.Claims; - -using SWD_Laundry_Backend.Application.Common.Interfaces; - -namespace SWD_Laundry_Backend.WebUI.Services; - -public class CurrentUserService : ICurrentUserService -{ - private readonly IHttpContextAccessor _httpContextAccessor; - - public CurrentUserService(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } - - public string? UserId => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); -} diff --git a/src/WebUI/WebUI.csproj b/src/WebUI/WebUI.csproj deleted file mode 100644 index 451a231..0000000 --- a/src/WebUI/WebUI.csproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - net7.0 - enable - true - enable - true - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - OnBuildSuccess - - - - - diff --git a/src/WebUI/appsettings.Development.json b/src/WebUI/appsettings.Development.json deleted file mode 100644 index 20847b8..0000000 --- a/src/WebUI/appsettings.Development.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.AspNetCore.SpaProxy": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "IdentityServer": { - "Key": { - "Type": "Development" - } - } -} diff --git a/src/WebUI/appsettings.Production.json b/src/WebUI/appsettings.Production.json deleted file mode 100644 index c97a10f..0000000 --- a/src/WebUI/appsettings.Production.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "UseInMemoryDatabase": false, - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - }, - "IdentityServer": { - "Key": { - "Type": "Store", - "StoreName": "My", - "StoreLocation": "LocalMachine", - "Name": "CN=IdentityServerCN" - } - } -} diff --git a/src/WebUI/nswag.json b/src/WebUI/nswag.json deleted file mode 100644 index aebf4b2..0000000 --- a/src/WebUI/nswag.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "runtime": "Net70", - "defaultVariables": null, - "documentGenerator": { - "aspNetCoreToOpenApi": { - "project": "WebUI.csproj", - "msBuildProjectExtensionsPath": null, - "configuration": null, - "runtime": null, - "targetFramework": null, - "noBuild": true, - "msBuildOutputPath": null, - "verbose": false, - "workingDirectory": null, - "requireParametersWithoutDefault": true, - "apiGroupNames": null, - "defaultPropertyNameHandling": "CamelCase", - "defaultReferenceTypeNullHandling": "Null", - "defaultDictionaryValueReferenceTypeNullHandling": "NotNull", - "defaultResponseReferenceTypeNullHandling": "NotNull", - "generateOriginalParameterNames": true, - "defaultEnumHandling": "Integer", - "flattenInheritanceHierarchy": false, - "generateKnownTypes": true, - "generateEnumMappingDescription": false, - "generateXmlObjects": false, - "generateAbstractProperties": false, - "generateAbstractSchemas": true, - "ignoreObsoleteProperties": false, - "allowReferencesWithProperties": false, - "useXmlDocumentation": true, - "resolveExternalXmlDocumentation": true, - "excludedTypeNames": [], - "serviceHost": null, - "serviceBasePath": null, - "serviceSchemes": [], - "infoTitle": "SWD_Laundry_Backend API", - "infoDescription": null, - "infoVersion": "1.0.0", - "documentTemplate": null, - "documentProcessorTypes": [], - "operationProcessorTypes": [], - "typeNameGeneratorType": null, - "schemaNameGeneratorType": null, - "contractResolverType": null, - "serializerSettingsType": null, - "useDocumentProvider": true, - "documentName": "v1", - "aspNetCoreEnvironment": null, - "createWebHostBuilderMethod": null, - "startupType": null, - "allowNullableBodyParameters": true, - "useHttpAttributeNameAsOperationId": false, - "output": "wwwroot/api/specification.json", - "outputType": "OpenApi3", - "newLineBehavior": "Auto", - "assemblyPaths": [], - "assemblyConfig": null, - "referencePaths": [], - "useNuGetCache": false - } - }, - "codeGenerators": { - - } -} diff --git a/src/WebUI/wwwroot/api/specification.json b/src/WebUI/wwwroot/api/specification.json deleted file mode 100644 index 8bb1168..0000000 --- a/src/WebUI/wwwroot/api/specification.json +++ /dev/null @@ -1,1168 +0,0 @@ -{ - "x-generator": "NSwag v13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0))", - "openapi": "3.0.0", - "info": { - "title": "SWD_Laundry_Backend API", - "version": "1.0.0" - }, - "paths": { - "/api/Building": { - "get": { - "tags": [ - "Building" - ], - "operationId": "Building_GetAll", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BuildingViewModel" - } - } - } - } - } - } - }, - "post": { - "tags": [ - "Building" - ], - "operationId": "Building_Post", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateBuildingCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - } - } - }, - "put": { - "tags": [ - "Building" - ], - "operationId": "Building_Put", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateBuildingCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - }, - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - }, - "/api/Building/{id}": { - "get": { - "tags": [ - "Building" - ], - "operationId": "Building_Get", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BuildingViewModel" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Building" - ], - "operationId": "Building_Delete", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - }, - "204": { - "description": "" - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - }, - "/api/Wallet": { - "get": { - "tags": [ - "Wallet" - ], - "operationId": "Wallet_GetAll", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WalletViewModel" - } - } - } - } - } - } - }, - "post": { - "tags": [ - "Wallet" - ], - "operationId": "Wallet_Post", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWalletCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - } - } - }, - "put": { - "tags": [ - "Wallet" - ], - "operationId": "Wallet_Put", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateWalletCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - }, - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - }, - "/api/Wallet/{id}": { - "get": { - "tags": [ - "Wallet" - ], - "operationId": "Wallet_Get", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WalletViewModel" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Wallet" - ], - "operationId": "Wallet_Delete", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - }, - "204": { - "description": "" - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - }, - "/api/TodoItems": { - "get": { - "tags": [ - "TodoItems" - ], - "operationId": "TodoItems_GetTodoItemsWithPagination", - "parameters": [ - { - "name": "ListId", - "in": "query", - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - }, - { - "name": "PageNumber", - "in": "query", - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 2 - }, - { - "name": "PageSize", - "in": "query", - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 3 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto" - } - } - } - } - } - }, - "post": { - "tags": [ - "TodoItems" - ], - "operationId": "TodoItems_Create", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTodoItemCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - } - } - } - }, - "/api/TodoItems/{id}": { - "put": { - "tags": [ - "TodoItems" - ], - "operationId": "TodoItems_Update", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTodoItemCommand" - } - } - }, - "required": true, - "x-position": 2 - }, - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - }, - "delete": { - "tags": [ - "TodoItems" - ], - "operationId": "TodoItems_Delete", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "204": { - "description": "" - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - }, - "/api/TodoItems/UpdateItemDetails": { - "put": { - "tags": [ - "TodoItems" - ], - "operationId": "TodoItems_UpdateItemDetails", - "parameters": [ - { - "name": "id", - "in": "query", - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTodoItemDetailCommand" - } - } - }, - "required": true, - "x-position": 2 - }, - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - }, - "/api/TodoLists": { - "get": { - "tags": [ - "TodoLists" - ], - "operationId": "TodoLists_Get", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TodosVm" - } - } - } - } - } - }, - "post": { - "tags": [ - "TodoLists" - ], - "operationId": "TodoLists_Create", - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTodoListCommand" - } - } - }, - "required": true, - "x-position": 1 - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "integer", - "format": "int32" - } - } - } - } - } - } - }, - "/api/TodoLists/{id}": { - "get": { - "tags": [ - "TodoLists" - ], - "operationId": "TodoLists_Get2", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - } - } - }, - "put": { - "tags": [ - "TodoLists" - ], - "operationId": "TodoLists_Update", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "requestBody": { - "x-name": "command", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTodoListCommand" - } - } - }, - "required": true, - "x-position": 2 - }, - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - }, - "delete": { - "tags": [ - "TodoLists" - ], - "operationId": "TodoLists_Delete", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - }, - "x-position": 1 - } - ], - "responses": { - "204": { - "description": "" - }, - "default": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "BuildingViewModel": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "address": { - "type": "string" - }, - "description": { - "type": "string" - } - } - }, - "CreateBuildingCommand": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "address", - "description" - ], - "properties": { - "name": { - "type": "string", - "minLength": 1, - "nullable": false - }, - "address": { - "type": "string", - "minLength": 1, - "nullable": false - }, - "description": { - "type": "string", - "minLength": 1, - "nullable": false - } - } - }, - "ProblemDetails": { - "type": "object", - "additionalProperties": { - "nullable": true - }, - "properties": { - "type": { - "type": "string", - "nullable": true - }, - "title": { - "type": "string", - "nullable": true - }, - "status": { - "type": "integer", - "format": "int32", - "nullable": true - }, - "detail": { - "type": "string", - "nullable": true - }, - "instance": { - "type": "string", - "nullable": true - } - } - }, - "UpdateBuildingCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "address": { - "type": "string" - }, - "description": { - "type": "string" - } - } - }, - "WalletViewModel": { - "type": "object", - "additionalProperties": false, - "properties": { - "balance": { - "type": "number", - "format": "double" - } - } - }, - "CreateWalletCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "balance": { - "type": "number", - "format": "double", - "minimum": 0.0, - "exclusiveMinimum": true - } - } - }, - "UpdateWalletCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "balance": { - "type": "number", - "format": "double", - "minimum": 0.0, - "exclusiveMinimum": true - } - } - }, - "PaginatedListOfTodoItemBriefDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoItemBriefDto" - } - }, - "pageNumber": { - "type": "integer", - "format": "int32" - }, - "totalPages": { - "type": "integer", - "format": "int32" - }, - "totalCount": { - "type": "integer", - "format": "int32" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "hasNextPage": { - "type": "boolean" - } - } - }, - "TodoItemBriefDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "listId": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "done": { - "type": "boolean" - } - } - }, - "CreateTodoItemCommand": { - "type": "object", - "additionalProperties": false, - "required": [ - "title" - ], - "properties": { - "listId": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "nullable": false - } - } - }, - "UpdateTodoItemCommand": { - "type": "object", - "additionalProperties": false, - "required": [ - "title" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "nullable": false - }, - "done": { - "type": "boolean" - } - } - }, - "UpdateTodoItemDetailCommand": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "listId": { - "type": "integer", - "format": "int32" - }, - "priority": { - "$ref": "#/components/schemas/PriorityLevel" - }, - "note": { - "type": "string", - "nullable": true - } - } - }, - "PriorityLevel": { - "type": "integer", - "description": "", - "x-enumNames": [ - "None", - "Low", - "Medium", - "High" - ], - "enum": [ - 0, - 1, - 2, - 3 - ] - }, - "TodosVm": { - "type": "object", - "additionalProperties": false, - "properties": { - "priorityLevels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PriorityLevelDto" - } - }, - "lists": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoListDto" - } - } - } - }, - "PriorityLevelDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "value": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string", - "nullable": true - } - } - }, - "TodoListDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "colour": { - "type": "string", - "nullable": true - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TodoItemDto" - } - } - } - }, - "TodoItemDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "listId": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "nullable": true - }, - "done": { - "type": "boolean" - }, - "priority": { - "type": "integer", - "format": "int32" - }, - "note": { - "type": "string", - "nullable": true - } - } - }, - "CreateTodoListCommand": { - "type": "object", - "additionalProperties": false, - "required": [ - "title" - ], - "properties": { - "title": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "nullable": false - } - } - }, - "UpdateTodoListCommand": { - "type": "object", - "additionalProperties": false, - "required": [ - "title" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "title": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "nullable": false - } - } - } - }, - "securitySchemes": { - "JWT": { - "type": "apiKey", - "description": "Type into the textbox: Bearer {your JWT token}.", - "name": "Authorization", - "in": "header" - } - } - }, - "security": [ - { - "JWT": [] - } - ] -} \ No newline at end of file diff --git a/src/WebUI/wwwroot/favicon.ico b/src/WebUI/wwwroot/favicon.ico deleted file mode 100644 index 63e859b476eff5055e0e557aaa151ca8223fbeef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5430 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 Date: Sun, 1 Oct 2023 05:33:04 +0700 Subject: [PATCH 20/53] Create Infrastructure --- .../Class1.cs | 6 - .../Class1.cs | 6 - src/SWD-Laundry-Backend.Core/Class1.cs | 6 - .../Constant/ApplicationConstant.cs | 4 + .../Constant/ErrorCode.cs | 31 +++++ .../Constant/Formattings.cs | 35 ++++++ .../Models/BaseResponseModels.cs | 24 ++++ .../Utils/CoreHelper.cs | 32 +++++ .../Utils/ObjExtensions.cs | 29 +++++ .../Utils/ObjHelper.cs | 114 ++++++++++++++++++ src/SWD-Laundry-Backend.Mapper/Class1.cs | 6 - src/SWD-Laundry-Backend.Repository/Class1.cs | 6 - src/SWD-Laundry-Backend.Service/Class1.cs | 6 - src/SWD-Laundry-Backend/ConfigureService.cs | 5 + .../Controllers/ApiControllerBase.cs | 9 ++ .../Controllers/WeatherForecastController.cs | 6 +- .../Extensions/AutoMapperExtension.cs | 17 +++ src/SWD-Laundry-Backend/Program.cs | 51 ++++++-- .../Properties/launchSettings.json | 4 +- .../SWD-Laundry-Backend.csproj | 8 +- 20 files changed, 350 insertions(+), 55 deletions(-) delete mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Class1.cs delete mode 100644 src/SWD-Laundry-Backend.Contract.Service/Class1.cs delete mode 100644 src/SWD-Laundry-Backend.Core/Class1.cs create mode 100644 src/SWD-Laundry-Backend.Core/Constant/ApplicationConstant.cs create mode 100644 src/SWD-Laundry-Backend.Core/Constant/ErrorCode.cs create mode 100644 src/SWD-Laundry-Backend.Core/Constant/Formattings.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs create mode 100644 src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs create mode 100644 src/SWD-Laundry-Backend.Core/Utils/ObjExtensions.cs create mode 100644 src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs delete mode 100644 src/SWD-Laundry-Backend.Mapper/Class1.cs delete mode 100644 src/SWD-Laundry-Backend.Repository/Class1.cs delete mode 100644 src/SWD-Laundry-Backend.Service/Class1.cs create mode 100644 src/SWD-Laundry-Backend/ConfigureService.cs create mode 100644 src/SWD-Laundry-Backend/Controllers/ApiControllerBase.cs create mode 100644 src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Class1.cs b/src/SWD-Laundry-Backend.Contract.Repository/Class1.cs deleted file mode 100644 index e8f30e5..0000000 --- a/src/SWD-Laundry-Backend.Contract.Repository/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Contract.Repository; - -public class Class1 -{ - -} diff --git a/src/SWD-Laundry-Backend.Contract.Service/Class1.cs b/src/SWD-Laundry-Backend.Contract.Service/Class1.cs deleted file mode 100644 index 522b55a..0000000 --- a/src/SWD-Laundry-Backend.Contract.Service/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Contract.Service; - -public class Class1 -{ - -} diff --git a/src/SWD-Laundry-Backend.Core/Class1.cs b/src/SWD-Laundry-Backend.Core/Class1.cs deleted file mode 100644 index 90950a3..0000000 --- a/src/SWD-Laundry-Backend.Core/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Core; - -public class Class1 -{ - -} diff --git a/src/SWD-Laundry-Backend.Core/Constant/ApplicationConstant.cs b/src/SWD-Laundry-Backend.Core/Constant/ApplicationConstant.cs new file mode 100644 index 0000000..a6efe69 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Constant/ApplicationConstant.cs @@ -0,0 +1,4 @@ +namespace SWD_Laundry_Backend.Core.Constant; +public class ApplicationConstant +{ +} diff --git a/src/SWD-Laundry-Backend.Core/Constant/ErrorCode.cs b/src/SWD-Laundry-Backend.Core/Constant/ErrorCode.cs new file mode 100644 index 0000000..76d3866 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Constant/ErrorCode.cs @@ -0,0 +1,31 @@ +namespace SWD_Laundry_Backend.Core.Constant; +public class ErrorCode +{ + public const string BadRequest = "Bad Request"; + public const string UnAuthenticated = "Un-Authenticate"; + public const string UnAuthorized = "Forbidden"; + public const string NotFound = "Not Found"; + public const string Unknown = "Oops! Something went wrong, please try again later."; + public const string NotUnique = "The resource is already, please try another."; + public const string TokenExpired = "The Token is already expired."; + public const string TokenInvalid = "The Token is invalid."; + + // Client + public const string GrantTypeInValid = "Grant Type is invalid."; + + public const string SecretInValid = "Secret is invalid."; + + // User + public const string UserPasswordWrong = "Password is wrong."; + + public const string UserBanned = "User is banned."; + public const string UserInActive = "User is in-active."; + + // Access Token + public const string AuthCodeInValid = "The Code is invalid."; + + // App + public const string AppBanned = "App is banned."; + // Update callback Balance + public const string UserInvalid = "Username invalid."; +} diff --git a/src/SWD-Laundry-Backend.Core/Constant/Formattings.cs b/src/SWD-Laundry-Backend.Core/Constant/Formattings.cs new file mode 100644 index 0000000..00a1389 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Constant/Formattings.cs @@ -0,0 +1,35 @@ +using System.Globalization; +using System.Xml; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace SWD_Laundry_Backend.Core.Constant; + +public static class Formattings +{ + public const string DateTimeOffSetFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; + + public const string TimeZone = "Asia/Ho_Chi_Minh"; // "UTC" + + public const string DateFormat = "dd/MM/yyyy"; + + public const string TimeFormat = "h:mm:ss tt"; + + public const string DateTimeFormat = "dd/MM/yyyy hh:mm:ss tt"; + + public const string JsDateFormat = "dd/mm/yyyy"; + + public const string JsDateTimeFormat = "dd/mm/yyyy HH:ii:ss P"; + + public static readonly JsonSerializerSettings JsonSerializerSettings = new() + { + Formatting = Newtonsoft.Json.Formatting.None, + NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK", + ContractResolver = new CamelCasePropertyNamesContractResolver(), + Culture = CultureInfo.CurrentCulture + }; +} diff --git a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs new file mode 100644 index 0000000..c2b23ca --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs @@ -0,0 +1,24 @@ +namespace SWD_Laundry_Backend.Core.Models; +public class BaseResponseModel +{ + public T? Data { get; set; } + public object? AdditionalData { get; set; } + public string? Message { get; set; } + public int StatusCode { get; set; } + public string Code { get; set; } + + public BaseResponseModel(int statusCode, string code, T? data, object? additionalData = null) + { + this.StatusCode = statusCode; + this.Code = code; + this.Data = data; + this.AdditionalData = additionalData; + } + + public BaseResponseModel(int statusCode, string code, string? message) + { + this.StatusCode = statusCode; + this.Code = code; + this.Message = message; + } +} diff --git a/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs b/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs new file mode 100644 index 0000000..b60efd4 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Utils/CoreHelper.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Http; +using SWD_Laundry_Backend.Core.Constant; +using TimeZoneConverter; + +namespace SWD_Laundry_Backend.Core.Utils; +public static class CoreHelper +{ + private static IHttpContextAccessor? _contextAccessor; + public static HttpContext CurrentHttpContext => Current; + + public static TimeZoneInfo SystemTimeZoneInfo => GetTimeZoneInfo(Formattings.TimeZone); + + public static DateTimeOffset SystemTimeNow => DateTimeOffset.UtcNow; + + public static DateTime UtcToSystemTime(this DateTimeOffset dateTimeOffsetUtc) + { + return dateTimeOffsetUtc.UtcDateTime.UtcToSystemTime(); + } + + public static DateTime UtcToSystemTime(this DateTime dateTimeUtc) + { + var dateTimeWithTimeZone = TimeZoneInfo.ConvertTimeFromUtc(dateTimeUtc, SystemTimeZoneInfo); + + return dateTimeWithTimeZone; + } + public static TimeZoneInfo GetTimeZoneInfo(string timeZoneId) + { + return TZConvert.GetTimeZoneInfo(timeZoneId); + } + + public static HttpContext? Current => _contextAccessor?.HttpContext; +} diff --git a/src/SWD-Laundry-Backend.Core/Utils/ObjExtensions.cs b/src/SWD-Laundry-Backend.Core/Utils/ObjExtensions.cs new file mode 100644 index 0000000..aa47882 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Utils/ObjExtensions.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Core.Utils; +public static class ObjExtensions +{ + public static string ToJsonString(this object obj) + { + return ObjHelper.ToJsonString(obj); + } + + public static T Clone(this T obj) + { + return ObjHelper.Clone(obj); + } + + public static T ConvertTo(this object obj) + { + return ObjHelper.ConvertTo(obj); + } + + public static T WithoutRefLoop(this T obj) + { + return ObjHelper.WithoutRefLoop(obj); + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs b/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs new file mode 100644 index 0000000..ed7ca72 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Utils/ObjHelper.cs @@ -0,0 +1,114 @@ +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; + +namespace SWD_Laundry_Backend.Core.Utils; +public class ObjHelper +{ + public static string ToJsonString(object obj) + { + JObject? jObject = obj as JObject; + if (jObject != null) + { + return jObject.ToString(Formatting.None); + } + + return JsonConvert.SerializeObject(obj, Formatting.None); + } + + public static T? Clone(T obj) + { + if (obj == null) + { + return default(T); + } + + string value = JsonConvert.SerializeObject(obj); + return JsonConvert.DeserializeObject(value, new JsonSerializerSettings + { + ObjectCreationHandling = ObjectCreationHandling.Replace + }); + } + + public static T? ConvertTo(object obj) + { + if (obj != null) + { + if (obj is T) + { + return (T)obj; + } + + Type typeFromHandle = typeof(T); + Type? underlyingType = Nullable.GetUnderlyingType(typeFromHandle); + if (underlyingType != null) + { + if (underlyingType == typeof(string)) + { + return (T)(object)obj.ToString(); + } + + return (T)Convert.ChangeType(obj, underlyingType); + } + + if (typeFromHandle == typeof(string)) + { + return (T)(object)obj.ToString(); + } + + if (typeFromHandle.IsPrimitive) + { + return (T)Convert.ChangeType(obj.ToString(), typeFromHandle); + } + + return (T)Convert.ChangeType(obj, typeFromHandle); + } + + return default(T); + } + + public static bool TryConvertTo(object obj, T defaultValue, out T value) + { + try + { + value = ConvertTo(obj); + return true; + } + catch + { + value = ((defaultValue == null) ? default(T) : defaultValue); + return false; + } + } + + public static T? WithoutRefLoop(T obj) + { + if (obj == null) + { + return default(T); + } + + string value = JsonConvert.SerializeObject(obj, new JsonSerializerSettings + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore + }); + return JsonConvert.DeserializeObject(value, new JsonSerializerSettings + { + ObjectCreationHandling = ObjectCreationHandling.Replace + }); + } + + public static T ReplaceNullOrDefault(T value, T newValue) + { + if (value == null) + { + value = newValue; + } + else if (value.Equals(default(T))) + { + value = newValue; + } + + return value; + } + +} diff --git a/src/SWD-Laundry-Backend.Mapper/Class1.cs b/src/SWD-Laundry-Backend.Mapper/Class1.cs deleted file mode 100644 index 2d79800..0000000 --- a/src/SWD-Laundry-Backend.Mapper/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Mapper; - -public class Class1 -{ - -} diff --git a/src/SWD-Laundry-Backend.Repository/Class1.cs b/src/SWD-Laundry-Backend.Repository/Class1.cs deleted file mode 100644 index 3d9a4c3..0000000 --- a/src/SWD-Laundry-Backend.Repository/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Repository; - -public class Class1 -{ - -} diff --git a/src/SWD-Laundry-Backend.Service/Class1.cs b/src/SWD-Laundry-Backend.Service/Class1.cs deleted file mode 100644 index f9afaaa..0000000 --- a/src/SWD-Laundry-Backend.Service/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SWD_Laundry_Backend.Service; - -public class Class1 -{ - -} diff --git a/src/SWD-Laundry-Backend/ConfigureService.cs b/src/SWD-Laundry-Backend/ConfigureService.cs new file mode 100644 index 0000000..64784aa --- /dev/null +++ b/src/SWD-Laundry-Backend/ConfigureService.cs @@ -0,0 +1,5 @@ +namespace SWD_Laundry_Backend; + +public class ConfigureService +{ +} diff --git a/src/SWD-Laundry-Backend/Controllers/ApiControllerBase.cs b/src/SWD-Laundry-Backend/Controllers/ApiControllerBase.cs new file mode 100644 index 0000000..794099b --- /dev/null +++ b/src/SWD-Laundry-Backend/Controllers/ApiControllerBase.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Mvc; + +namespace SWD_Laundry_Backend.Controllers; +[Route("api/[controller]")] +[ApiController] +public abstract class ApiControllerBase : ControllerBase +{ + +} diff --git a/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs b/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs index 87bbfeb..a37e97d 100644 --- a/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs +++ b/src/SWD-Laundry-Backend/Controllers/WeatherForecastController.cs @@ -2,8 +2,7 @@ namespace SWD_Laundry_Backend.Controllers; [ApiController] -[Route("[controller]")] -public class WeatherForecastController : ControllerBase +public class WeatherForecastController : ApiControllerBase { private static readonly string[] Summaries = new[] { @@ -17,7 +16,7 @@ public WeatherForecastController(ILogger logger) _logger = logger; } - [HttpGet(Name = "GetWeatherForecast")] + [HttpGet] public IEnumerable Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast @@ -29,3 +28,4 @@ public IEnumerable Get() .ToArray(); } } + diff --git a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs new file mode 100644 index 0000000..3a818c5 --- /dev/null +++ b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs @@ -0,0 +1,17 @@ +namespace SWD_Laundry_Backend.Extensions; + + +public static class AutoMapperExtension +{ + public static IServiceCollection AddAutoMapperServices(this IServiceCollection services) + { + services.AddAutoMapper(cfg => + { + + }); + return services; + } +} + + + diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index 93efa15..38e0634 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -1,4 +1,10 @@ +using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.OpenApi.Models; using Serilog; +using SWD_Laundry_Backend.Extensions; + namespace SWD_Laundry_Backend; public class Program @@ -6,34 +12,63 @@ public class Program public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - + builder.Environment.EnvironmentName = Environments.Development; // Add services to the container. + builder.Configuration.AddJsonFile("appsettings.json", false, true) + .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", false, true) + .AddUserSecrets(true, false) + .Build(); + builder.Host.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration .ReadFrom.Configuration(hostingContext.Configuration) .Enrich.FromLogContext() .WriteTo.Console()); - builder.Services.AddControllers(); + builder.Services.AddControllers(options => + { + options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer())); + }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(); + builder.Services.AddSwaggerGen( options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "SWD-Laundry-Backend", Version = "v1" }); + }); + + builder.Services.AddAutoMapperServices(); + builder.Services.AddRouting(options => + { + options.AppendTrailingSlash = true; + } ); + builder.Services.Configure(opt => opt.TokenLifespan = TimeSpan.FromMinutes(30)); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); - app.UseSwaggerUI(); + app.UseSwaggerUI( + options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "SWD-Laundry-Backend v1"); + options.RoutePrefix = "swagger/api/v1"; + }); } app.UseHttpsRedirection(); - + app.UseSerilogRequestLogging(); app.UseAuthorization(); - - app.MapControllers(); - app.Run(); } } + +public class SlugifyParameterTransformer : IOutboundParameterTransformer +{ + public string? TransformOutbound(object value) + { + // Slugify value + return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); + } +} diff --git a/src/SWD-Laundry-Backend/Properties/launchSettings.json b/src/SWD-Laundry-Backend/Properties/launchSettings.json index 2cb5d0e..a820841 100644 --- a/src/SWD-Laundry-Backend/Properties/launchSettings.json +++ b/src/SWD-Laundry-Backend/Properties/launchSettings.json @@ -23,7 +23,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "launchUrl": "swagger", + "launchUrl": "swagger/api/v1", "applicationUrl": "https://localhost:7220;http://localhost:5130", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -32,7 +32,7 @@ "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "swagger", + "launchUrl": "swagger/api/v1", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj index c657e66..06664f9 100644 --- a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj +++ b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj @@ -8,12 +8,8 @@ - - - - - - + + From 4977c8644a9a5c6f5204a1f65b6c87b116e37eae Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sun, 1 Oct 2023 05:52:43 +0700 Subject: [PATCH 21/53] Core --- .../SWD-Laundry-Backend.Core.csproj | 6 ++++++ src/SWD-Laundry-Backend/.config/dotnet-tools.json | 12 ++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/SWD-Laundry-Backend/.config/dotnet-tools.json diff --git a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj index 6f6cf3a..706d92c 100644 --- a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj +++ b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj @@ -8,7 +8,13 @@ + + + + + + diff --git a/src/SWD-Laundry-Backend/.config/dotnet-tools.json b/src/SWD-Laundry-Backend/.config/dotnet-tools.json new file mode 100644 index 0000000..96be437 --- /dev/null +++ b/src/SWD-Laundry-Backend/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-ef": { + "version": "7.0.11", + "commands": [ + "dotnet-ef" + ] + } + } +} \ No newline at end of file From ed44995f0448d68d5d3d6e946ed11f5966dc5cbc Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sun, 1 Oct 2023 06:46:50 +0700 Subject: [PATCH 22/53] Update --- .../Base Interface/IBaseRepository.cs | 11 ++++++ .../Entity/BaseEntity.cs | 26 ++++++++++++++ .../Infrastructure/IRepository.cs | 7 ++++ ...Laundry-Backend.Contract.Repository.csproj | 18 ++++++++++ .../Config/SystemSettingModel.cs | 13 +++++++ .../Utils/SystemHelper.cs | 10 ++++++ .../Base/BaseRepository.cs | 36 +++++++++++++++++++ .../SWD-Laundry-Backend.Repository.csproj | 4 +++ src/SWD-Laundry-Backend/ConfigureService.cs | 5 --- src/SWD-Laundry-Backend/Program.cs | 18 ++++++++-- .../appsettings.Development.json | 3 ++ 11 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/BaseEntity.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Infrastructure/IRepository.cs create mode 100644 src/SWD-Laundry-Backend.Core/Config/SystemSettingModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Utils/SystemHelper.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs delete mode 100644 src/SWD-Laundry-Backend/ConfigureService.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs new file mode 100644 index 0000000..cb8d408 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs @@ -0,0 +1,11 @@ +using System.Linq.Expressions; + +namespace SWD_Laundry_Backend.Contract.Repository.Base_Interface; +public interface IBaseRepository where T : Entity.BaseEntity, new() +{ + T GetSingle(Expression>? filter = null, params Expression>[]? includes); + IQueryable Get(Expression>? filter = null, params Expression>[]? includes); + int Update(Expression> filter, T entity); + int Delete(Expression> filter); + int Add(T entity); +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/BaseEntity.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/BaseEntity.cs new file mode 100644 index 0000000..5340694 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/BaseEntity.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; +using SWD_Laundry_Backend.Core.Utils; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity +{ + public abstract class BaseEntity + { + protected BaseEntity() + { + Id = Guid.NewGuid().ToString(); + CreatedTime = LastUpdatedTime = CoreHelper.SystemTimeNow; + } + + [Key] + public string Id { get; set; } + public string? CreatedBy { get; set; } + public string? LastUpdatedBy { get; set; } + //public string? DeletedBy { get; set; } + + public DateTimeOffset? CreatedTime { get; set; } + + public DateTimeOffset? LastUpdatedTime { get; set; } + + //public DateTimeOffset? DeletedTime { get; set; } + } +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Infrastructure/IRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Infrastructure/IRepository.cs new file mode 100644 index 0000000..ebac5ab --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Infrastructure/IRepository.cs @@ -0,0 +1,7 @@ +using SWD_Laundry_Backend.Contract.Repository.Base_Interface; + +namespace SWD_Laundry_Backend.Contract.Repository.Infrastructure; +public interface IRepository : IBaseRepository where T : Entity.BaseEntity, new() +{ + +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj index 77dcfe3..ab97129 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj +++ b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj @@ -7,4 +7,22 @@ enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + diff --git a/src/SWD-Laundry-Backend.Core/Config/SystemSettingModel.cs b/src/SWD-Laundry-Backend.Core/Config/SystemSettingModel.cs new file mode 100644 index 0000000..b210a3f --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Config/SystemSettingModel.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.Configuration; +using System.Reflection; + +namespace SWD_Laundry_Backend.Core.Config; +public class SystemSettingModel +{ + public static SystemSettingModel Instance { get; set; } + + public static IConfiguration Configs { get; set; } + public string ApplicationName { get; set; } = Assembly.GetEntryAssembly()?.GetName().Name; + + public string? Domain { get; set; } +} diff --git a/src/SWD-Laundry-Backend.Core/Utils/SystemHelper.cs b/src/SWD-Laundry-Backend.Core/Utils/SystemHelper.cs new file mode 100644 index 0000000..0a134b4 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Utils/SystemHelper.cs @@ -0,0 +1,10 @@ +using Microsoft.Extensions.Configuration; +using SWD_Laundry_Backend.Core.Config; + +namespace SWD_Laundry_Backend.Core.Utils; +public class SystemHelper +{ + public static SystemSettingModel Setting => SystemSettingModel.Instance; + public static IConfiguration Configs => SystemSettingModel.Configs; + public static string? AppDb => SystemSettingModel.Configs.GetConnectionString("DefaultConnection"); +} diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs new file mode 100644 index 0000000..a8d3908 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -0,0 +1,36 @@ +using System.Linq.Expressions; +using SWD_Laundry_Backend.Contract.Repository.Base_Interface; +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Repository.Base +{ + public abstract class BaseRepository : IBaseRepository where T : BaseEntity, new() + { + + + public int Add(T entity) + { + throw new NotImplementedException(); + } + + public int Delete(Expression> filter) + { + throw new NotImplementedException(); + } + + public IQueryable Get(Expression>? filter = null, params Expression>[]? includes) + { + throw new NotImplementedException(); + } + + public T GetSingle(Expression>? filter = null, params Expression>[]? includes) + { + throw new NotImplementedException(); + } + + public int Update(Expression> filter, T entity) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj index 0dbe32a..16f16bd 100644 --- a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj +++ b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/src/SWD-Laundry-Backend/ConfigureService.cs b/src/SWD-Laundry-Backend/ConfigureService.cs deleted file mode 100644 index 64784aa..0000000 --- a/src/SWD-Laundry-Backend/ConfigureService.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace SWD_Laundry_Backend; - -public class ConfigureService -{ -} diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index 38e0634..18a9f5f 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.OpenApi.Models; using Serilog; +using SWD_Laundry_Backend.Core.Config; using SWD_Laundry_Backend.Extensions; namespace SWD_Laundry_Backend; @@ -15,11 +16,14 @@ public static void Main(string[] args) builder.Environment.EnvironmentName = Environments.Development; // Add services to the container. - builder.Configuration.AddJsonFile("appsettings.json", false, true) + SystemSettingModel.Configs = builder.Configuration.AddJsonFile("appsettings.json", false, true) .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", false, true) .AddUserSecrets(true, false) .Build(); + var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); + + builder.Host.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration .ReadFrom.Configuration(hostingContext.Configuration) .Enrich.FromLogContext() @@ -40,7 +44,7 @@ public static void Main(string[] args) { options.AppendTrailingSlash = true; } ); - + _ = builder.Services.AddSystemSetting(builder.Configuration.GetSection("SystemSetting").Get()); builder.Services.Configure(opt => opt.TokenLifespan = TimeSpan.FromMinutes(30)); var app = builder.Build(); @@ -72,3 +76,13 @@ public class SlugifyParameterTransformer : IOutboundParameterTransformer return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); } } + +public static class StartupSystemSetting +{ + public static IServiceCollection AddSystemSetting(this IServiceCollection services, SystemSettingModel? systemSettingModel) + { + SystemSettingModel.Instance = systemSettingModel ?? new SystemSettingModel(); + + return services; + } +} diff --git a/src/SWD-Laundry-Backend/appsettings.Development.json b/src/SWD-Laundry-Backend/appsettings.Development.json index 0c208ae..6653762 100644 --- a/src/SWD-Laundry-Backend/appsettings.Development.json +++ b/src/SWD-Laundry-Backend/appsettings.Development.json @@ -4,5 +4,8 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "ConnectionStrings": { + "DefaultConnection": "Data Source=(localdb)\\ProjectModels;Initial Catalog=Laundry;user=sa;pwd=12345;Trusted_Connection=True;Trust Server Certificate=True" } } From 3a1a017763eeadd124e9d72caf6a324f610f1f91 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sun, 1 Oct 2023 07:30:02 +0700 Subject: [PATCH 23/53] Finished Base --- .../Base Service Interface/ICreateAble.cs | 9 ++++ .../Base Service Interface/IDeleteAble.cs | 7 +++ .../Base Service Interface/IGetAble.cs | 8 +++ .../Base Service Interface/IUpdateAble.cs | 7 +++ ...WD-Laundry-Backend.Contract.Service.csproj | 4 ++ .../Base/BaseDbContext.cs | 10 ++++ .../Base/BaseRepository.cs | 7 ++- .../Infrastructure/AppDbContext.DbSet.cs | 5 ++ .../Infrastructure/AppDbContext.cs | 52 +++++++++++++++++++ .../Infrastructure/Repository.cs | 14 +++++ .../Base Service/Service.cs | 10 ++++ 11 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs create mode 100644 src/SWD-Laundry-Backend.Service/Base Service/Service.cs diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs new file mode 100644 index 0000000..6e32864 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs @@ -0,0 +1,9 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface +{ + public interface ICreateAble where T : BaseEntity, new() + { + Task CreateAsync(T model, CancellationToken cancellationToken = default); + } +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs new file mode 100644 index 0000000..57f2493 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs @@ -0,0 +1,7 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +public interface IDeleteAble where TKey : BaseEntity +{ + Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs new file mode 100644 index 0000000..91b55dc --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs @@ -0,0 +1,8 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +public interface IGetAble where T : BaseEntity +{ + Task> GetAllAsync(CancellationToken cancellationToken = default); + Task GetByIdAsync(TKey id, CancellationToken cancellationToken = default); +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs new file mode 100644 index 0000000..77cfc6b --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs @@ -0,0 +1,7 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +public interface IUpdateAble where T : BaseEntity, new() +{ + Task UpdateAsync(Tkey id, T model, CancellationToken cancellationToken = default); +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj index c7f524b..a93d042 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj +++ b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs new file mode 100644 index 0000000..0299655 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs @@ -0,0 +1,10 @@ +using Microsoft.EntityFrameworkCore; + +namespace SWD_Laundry_Backend.Repository.Base; +public abstract class BaseDbContext : DbContext +{ + protected BaseDbContext(DbContextOptions options) : base(options) + { + + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs index a8d3908..6479f30 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -1,4 +1,5 @@ using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; using SWD_Laundry_Backend.Contract.Repository.Base_Interface; using SWD_Laundry_Backend.Contract.Repository.Entity; @@ -6,7 +7,11 @@ namespace SWD_Laundry_Backend.Repository.Base { public abstract class BaseRepository : IBaseRepository where T : BaseEntity, new() { - + protected readonly DbContext _dbContext; + protected BaseRepository(DbContext dbContext) + { + _dbContext = dbContext; + } public int Add(T entity) { diff --git a/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs new file mode 100644 index 0000000..43a14a9 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs @@ -0,0 +1,5 @@ +namespace SWD_Laundry_Backend.Repository.Infrastructure; +public sealed partial class AppDbContext +{ + +} diff --git a/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs new file mode 100644 index 0000000..889d147 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs @@ -0,0 +1,52 @@ +using System.Reflection; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using SWD_Laundry_Backend.Core.Utils; +using SWD_Laundry_Backend.Repository.Base; + +namespace SWD_Laundry_Backend.Repository.Infrastructure; +public sealed partial class AppDbContext : BaseDbContext +{ + public readonly int CommandTimeoutInSecond = 20 * 60; + + public static readonly ILoggerFactory LoggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create( + builder => builder + .AddFilter((category, level) => + category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information) + .AddConsole()); + + public AppDbContext(DbContextOptions options) : base(options) + { + Database.SetCommandTimeout(CommandTimeoutInSecond); + + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + /* var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.Development.json") + .Build(); + var connectionString = configuration.GetConnectionString("DefaultConnection");*/ + + var connectionString = SystemHelper.AppDb; + //var connectionString = "Data Source=(local);Initial Catalog=WaterCity-Portal;user=sa;pwd=12345;Trusted_Connection=True;Trust Server Certificate=True"; + + optionsBuilder.UseSqlServer(connectionString, sqlServerOptionsAction => + { + sqlServerOptionsAction.MigrationsAssembly( + typeof(AppDbContext).GetTypeInfo().Assembly.GetName().Name); + + sqlServerOptionsAction.MigrationsHistoryTable("Migration"); + }); + optionsBuilder.UseLoggerFactory(LoggerFactory); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs b/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs new file mode 100644 index 0000000..3d39a9d --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Base_Interface; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; +using SWD_Laundry_Backend.Repository.Base; + +namespace SWD_Laundry_Backend.Repository.Infrastructure; +public class Repository : BaseRepository, IRepository, IBaseRepository where T : BaseEntity, new() +{ + public Repository(DbContext dbContext) : base(dbContext) + { + + } +} diff --git a/src/SWD-Laundry-Backend.Service/Base Service/Service.cs b/src/SWD-Laundry-Backend.Service/Base Service/Service.cs new file mode 100644 index 0000000..13301e4 --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Base Service/Service.cs @@ -0,0 +1,10 @@ +namespace SWD_Laundry_Backend.Service.Base_Service +{ + public abstract class Service + { + protected Service() + { + + } + } +} From 5d0afc3394d0b61a99140c0a6d1914d32dcc4c40 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:57:08 +0700 Subject: [PATCH 24/53] Update Repository --- .../Base Interface/IBaseRepository.cs | 11 ++-- .../Base/BaseRepository.cs | 57 +++++++++++++++---- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs index cb8d408..f1d11b6 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs @@ -1,11 +1,12 @@ using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; namespace SWD_Laundry_Backend.Contract.Repository.Base_Interface; public interface IBaseRepository where T : Entity.BaseEntity, new() { - T GetSingle(Expression>? filter = null, params Expression>[]? includes); - IQueryable Get(Expression>? filter = null, params Expression>[]? includes); - int Update(Expression> filter, T entity); - int Delete(Expression> filter); - int Add(T entity); + Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes); + Task> GetAsync(Expression>? filter = null, params Expression>[]? includes); + Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update); + Task DeleteAsync(Expression> filter); + Task AddAsync(T entity); } diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs index 6479f30..bf00519 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -1,5 +1,6 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; using SWD_Laundry_Backend.Contract.Repository.Base_Interface; using SWD_Laundry_Backend.Contract.Repository.Entity; @@ -8,34 +9,68 @@ namespace SWD_Laundry_Backend.Repository.Base public abstract class BaseRepository : IBaseRepository where T : BaseEntity, new() { protected readonly DbContext _dbContext; + + private DbSet _dbSet; + + protected DbSet DbSet + { + get + { + if (_dbSet != null) + { + return _dbSet; + } + + _dbSet = _dbContext.Set(); + return _dbSet; + } + } + protected BaseRepository(DbContext dbContext) { - _dbContext = dbContext; + _dbContext = dbContext; } - public int Add(T entity) + public virtual async Task AddAsync(T entity) { - throw new NotImplementedException(); + var e = await DbSet.AddAsync(entity); + return e.Entity; } - public int Delete(Expression> filter) + public virtual async Task DeleteAsync(Expression> filter) { - throw new NotImplementedException(); + var i = await DbSet.Where(filter).ExecuteDeleteAsync(); + return i; } - public IQueryable Get(Expression>? filter = null, params Expression>[]? includes) + public virtual async Task> GetAsync(Expression>? filter = null, params Expression>[]? includes) { - throw new NotImplementedException(); + + return await Task.Run(() => + { + var query = DbSet.AsNoTracking().Where(filter); + if (includes != null) + { + query = includes.Aggregate(query, (current, include) => current.Include(include)); + } + return query; + }); ; } - public T GetSingle(Expression>? filter = null, params Expression>[]? includes) + public virtual async Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes) { - throw new NotImplementedException(); + var query = DbSet.Where(filter).AsNoTracking(); + if (includes != null) + { + query = includes.Aggregate(query, (current, include) => current.Include(include)); + } + return await query.FirstOrDefaultAsync(); } - public int Update(Expression> filter, T entity) + public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update) { - throw new NotImplementedException(); + int i = await DbSet.Where(filter).ExecuteUpdateAsync(update); + return i; } } } From 18a06691851d666a970dcda7830e02349ca2edfb Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Sun, 1 Oct 2023 12:26:07 +0700 Subject: [PATCH 25/53] UpdateDatabase6 --- .../Base Interface/IBaseRepository.cs | 11 ++-- .../Entity/Building.cs | 16 +++++ .../Entity/Customer.cs | 58 +++++++++++++++++++ .../Entity/IdentityModels/ApplicationUser.cs | 20 +++++++ .../Entity/IdentityModels/IdentityRole.cs | 11 ++++ .../Entity/LaundryStore.cs | 27 +++++++++ .../Entity/Order.cs | 45 ++++++++++++++ .../Entity/OrderHistory.cs | 29 ++++++++++ .../Entity/Payment.cs | 19 ++++++ .../Entity/Staff.cs | 25 ++++++++ .../Entity/Staff_Trip.cs | 33 +++++++++++ .../Entity/TimeSchedule.cs | 20 +++++++ .../Entity/Transaction.cs | 31 ++++++++++ .../Entity/Wallet.cs | 18 ++++++ .../Enum/AllowedTransactionType.cs | 8 +++ .../Enum/DeliveryStatus.cs | 13 +++++ .../Enum/LaundryStatus.cs | 14 +++++ .../Enum/OrderStatus.cs | 8 +++ .../Enum/OrderType.cs | 6 ++ .../Enum/PaymentType.cs | 8 +++ .../Enum/TimeFrame.cs | 13 +++++ .../Enum/TripType.cs | 14 +++++ .../Base/BaseRepository.cs | 57 ++++-------------- src/SWD-Laundry-Backend/appsettings.json | 5 +- 24 files changed, 456 insertions(+), 53 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/AllowedTransactionType.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/DeliveryStatus.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/LaundryStatus.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderType.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/TimeFrame.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Enum/TripType.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs index f1d11b6..cb8d408 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs @@ -1,12 +1,11 @@ using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query; namespace SWD_Laundry_Backend.Contract.Repository.Base_Interface; public interface IBaseRepository where T : Entity.BaseEntity, new() { - Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes); - Task> GetAsync(Expression>? filter = null, params Expression>[]? includes); - Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update); - Task DeleteAsync(Expression> filter); - Task AddAsync(T entity); + T GetSingle(Expression>? filter = null, params Expression>[]? includes); + IQueryable Get(Expression>? filter = null, params Expression>[]? includes); + int Update(Expression> filter, T entity); + int Delete(Expression> filter); + int Add(T entity); } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs new file mode 100644 index 0000000..7193b25 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs @@ -0,0 +1,16 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class Building : BaseEntity +{ + public string Name { get; set; } + public string Address { get; set; } + public string Description { get; set; } + + #region Relationship + public List Customers { get; set; } + public List Staff_Trips { get; set; } + #endregion +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs new file mode 100644 index 0000000..75da97c --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs @@ -0,0 +1,58 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; + +#nullable disable + +public class Customer : BaseEntity +{ + //public string Name { get; set; } + //public string Address { get; set; } + + #region Relationship + + [ForeignKey("Building")] + public int BuildingID { get; set; } + + [ForeignKey("ApplicationUser")] + public string ApplicationUserID { get; set; } + + public Building Building { get; set; } + + public ApplicationUser ApplicationUser { get; set; } + public virtual List Order { get; set; } + + #endregion Relationship + + #region Special Attribute + + //private string _email; + + //private string _phone; + + //public string Email + //{ + // get { return _email; } + // set + // { + // _email = new Validate().IsValidEmail(value) + // ? value + // : throw new ArgumentException("Invalid email."); + // } + //} + + //public string Phone + //{ + // get { return _phone; } + // set + // { + // _phone = new Validate().IsValidPhone(value) + // ? value + // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); + // } + //} + + #endregion Special Attribute +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs new file mode 100644 index 0000000..102034d --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.AspNetCore.Identity; + + +namespace SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; + +public class ApplicationUser : IdentityUser +{ +#nullable disable + public string Name { get; set; } + + #region Relationship + + [ForeignKey("Wallet")] + public int WalletID { get; set; } + + public Wallet Wallet { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs new file mode 100644 index 0000000..1c28792 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; +public class ApplicationRole : IdentityRole +{ +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs new file mode 100644 index 0000000..27fed5b --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/LaundryStore.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class LaundryStore : BaseEntity +{ + public string Name { get; set; } + public string Address { get; set; } + + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public bool Status { get; set; } + + #region Relationship + + [ForeignKey("ApplicationUser")] + public string ApplicationUserID { get; set; } + + public ApplicationUser ApplicationUser { get; set; } + + public List Orders{ get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs new file mode 100644 index 0000000..b0d357f --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs @@ -0,0 +1,45 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Enum; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class Order : BaseEntity +{ + public DateTime OrderDate { get; set; } + public TimeFrame DeliveryTimeFrame { get; set; } + public DateTime ExpectedFinishDate { get; set; } + public string Address { get; set; } // Address = Customer's building location + public short Amount { get; set; } + + public double TotalPrice { get; set; } + + #region Relationship + + [ForeignKey("Customer")] + public int CustomerID { get; set; } + + [ForeignKey(nameof(LaundryStore))] + public int LaundryStoreID { get; set; } + + [ForeignKey(nameof(Staff))] + public int StaffID { get; set; } + + ////=========================== + public Customer Customer { get; set; } + public Staff Staff { get; set; } + public LaundryStore LaundryStore { get; set; } + + public List Payments { get; set; } + public List OrderHistories { get; set; } + + #endregion Relationship + + #region Special Attribute + + public OrderType OrderType { get; set; } + public PaymentType PaymentType { get; set; } + + #endregion Special Attribute +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs new file mode 100644 index 0000000..951d9cc --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Enum; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class OrderHistory : BaseEntity +{ + public string Title { get; set; } + public string Message { get; set; } + + #region Relationship + + [ForeignKey("Order")] + public int OrderID { get; set; } + + public Order Order { get; set; } + + #endregion Relationship + + #region Special attributes + + public OrderStatus OrderStatus { get; set; } + public DeliveryStatus DeliveryStatus { get; set; } + public LaundryStatus LaundryStatus { get; set; } + + #endregion Special attributes +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs new file mode 100644 index 0000000..1aeb4ce --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class Payment : BaseEntity +{ + public double Price { get; set; } + + #region Relationship + + [ForeignKey(nameof(Order))] + public int OrderId { get; set; } + + public Transaction Transaction { get; set; } + public Order Orders { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs new file mode 100644 index 0000000..25d243d --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; + + + +#nullable disable + +public class Staff : BaseEntity +{ + public DateTime Dob { get; set; } + public string Address { get; set; } + public double Salary { get; set; } + + #region Relationship + + [ForeignKey("ApplicationUser")] + public string ApplicationUserID { get; set; } + + public ApplicationUser ApplicationUser { get; set; } + + public List Staff_Trips { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs new file mode 100644 index 0000000..321a354 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +namespace SWD_Laundry_Backend.Contract.Repository.Entity; + +#nullable disable + +public class Staff_Trip : BaseEntity +{ + public int TripCollect { get; set; } = 0; + + #region Relationship + + [ForeignKey("Staff")] + public int StaffID { get; set; } + + [ForeignKey("TimeSchedule")] + public int TimeScheduleID { get; set; } + + [ForeignKey("Building")] + public int BuildingID { get; set; } + + public Building Building { get; set; } + public Staff Staff { get; set; } + public TimeSchedule TimeSchedule { get; set; } + + #endregion Relationship + + #region Special Attribute + + public TripType TripType { get; set; } + + #endregion Special Attribute +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs new file mode 100644 index 0000000..cd86cb2 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/TimeSchedule.cs @@ -0,0 +1,20 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Enum; + + + +#nullable disable + +public class TimeSchedule : BaseEntity +{ + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + + #region Special Attribute + + public DayOfWeek DayOfWeek { get; set; } + public TimeFrame TimeFrame { get; set; } + public List Staff_Trip { get; set; } + + #endregion Special Attribute +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs new file mode 100644 index 0000000..cc492e5 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations.Schema; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Enum; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class Transaction : BaseEntity +{ + public string PaymentMethod { get; set; } + public int Amount { get; set; } + public string Description { get; set; } + + #region Relationship + + [ForeignKey(nameof(Wallet))] + public int WalletID { get; set; } + + public Wallet Wallet { get; set; } + public List Payments { get; set; } + + #endregion Relationship + + #region Special Attribute + + public AllowedTransactionType TransactionType { get; set; } + + //public OrderStatus Status { get; set; } + + #endregion Special Attribute +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs new file mode 100644 index 0000000..09b0e5a --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Wallet.cs @@ -0,0 +1,18 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; + +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +#nullable disable + +public class Wallet : BaseEntity +{ + public double Balance { get; set; } + + #region Relationship + + public List Transactions { get; set; } + + public ApplicationUser ApplicationUser { get; set; } + + #endregion Relationship +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/AllowedTransactionType.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/AllowedTransactionType.cs new file mode 100644 index 0000000..7b69dc4 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/AllowedTransactionType.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Contract.Repository.Enum; +public enum AllowedTransactionType +{ + Deposit = 1, + Withdraw = 2, + Debt = 3, + Paid = 4 +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/DeliveryStatus.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/DeliveryStatus.cs new file mode 100644 index 0000000..37d22d3 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/DeliveryStatus.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Contract.Repository.Enum; +public enum DeliveryStatus +{ + Pending = 0, + Delivering = 1, + Delivered = 2, +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/LaundryStatus.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/LaundryStatus.cs new file mode 100644 index 0000000..32d79da --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/LaundryStatus.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Contract.Repository.Enum; + +public enum LaundryStatus +{ + Pending = 0, + Cleaning = 1, + Finished = 2, +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs new file mode 100644 index 0000000..3a34b5d --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Contract.Repository.Enum; +public enum OrderStatus +{ + Preparing = 1, + Processing = 2, + Completed = 3, + Cancelled = 4 +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderType.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderType.cs new file mode 100644 index 0000000..d610015 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderType.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Contract.Repository.Enum; +public enum OrderType +{ + OneWay = 1, + TwoWay = 2 +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs new file mode 100644 index 0000000..bb9a774 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Contract.Repository.Enum; +public enum PaymentType +{ + Cash = 1, + CreditCard = 2, + DebitCard = 3, + EWallet = 4 +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/TimeFrame.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/TimeFrame.cs new file mode 100644 index 0000000..bc61b54 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/TimeFrame.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Contract.Repository.Enum; +public enum TimeFrame +{ + Morning = 0, // 7h - 12h + Afternoon= 1, // 13h - 18h + Night = 2, // 19h - 24h +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/TripType.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/TripType.cs new file mode 100644 index 0000000..62a9b07 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/TripType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + + + +public enum TripType +{ + Collect_From_Customer = 0, + Delivery_To_Customer = 1, +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs index bf00519..6479f30 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -1,6 +1,5 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; using SWD_Laundry_Backend.Contract.Repository.Base_Interface; using SWD_Laundry_Backend.Contract.Repository.Entity; @@ -9,68 +8,34 @@ namespace SWD_Laundry_Backend.Repository.Base public abstract class BaseRepository : IBaseRepository where T : BaseEntity, new() { protected readonly DbContext _dbContext; - - private DbSet _dbSet; - - protected DbSet DbSet - { - get - { - if (_dbSet != null) - { - return _dbSet; - } - - _dbSet = _dbContext.Set(); - return _dbSet; - } - } - protected BaseRepository(DbContext dbContext) { - _dbContext = dbContext; + _dbContext = dbContext; } - public virtual async Task AddAsync(T entity) + public int Add(T entity) { - var e = await DbSet.AddAsync(entity); - return e.Entity; + throw new NotImplementedException(); } - public virtual async Task DeleteAsync(Expression> filter) + public int Delete(Expression> filter) { - var i = await DbSet.Where(filter).ExecuteDeleteAsync(); - return i; + throw new NotImplementedException(); } - public virtual async Task> GetAsync(Expression>? filter = null, params Expression>[]? includes) + public IQueryable Get(Expression>? filter = null, params Expression>[]? includes) { - - return await Task.Run(() => - { - var query = DbSet.AsNoTracking().Where(filter); - if (includes != null) - { - query = includes.Aggregate(query, (current, include) => current.Include(include)); - } - return query; - }); ; + throw new NotImplementedException(); } - public virtual async Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes) + public T GetSingle(Expression>? filter = null, params Expression>[]? includes) { - var query = DbSet.Where(filter).AsNoTracking(); - if (includes != null) - { - query = includes.Aggregate(query, (current, include) => current.Include(include)); - } - return await query.FirstOrDefaultAsync(); + throw new NotImplementedException(); } - public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update) + public int Update(Expression> filter, T entity) { - int i = await DbSet.Where(filter).ExecuteUpdateAsync(update); - return i; + throw new NotImplementedException(); } } } diff --git a/src/SWD-Laundry-Backend/appsettings.json b/src/SWD-Laundry-Backend/appsettings.json index 10f68b8..64ce3c9 100644 --- a/src/SWD-Laundry-Backend/appsettings.json +++ b/src/SWD-Laundry-Backend/appsettings.json @@ -5,5 +5,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "DefaultConnection": "Server = LEWIS; Database = LaundryStoreDB; User Id = sa; Password = 123456; TrustServerCertificate = true" + } } From 5f2167a519d6125e028a632130b9ec4bb2f94b60 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:31:10 +0700 Subject: [PATCH 26/53] Fix DI --- .../Entity/Test.cs | 16 ++++++++++++++++ ...WD-Laundry-Backend.Contract.Repository.csproj | 4 ++++ .../SWD-Laundry-Backend.Contract.Service.csproj | 4 ++++ .../SWD-Laundry-Backend.Core.csproj | 2 ++ .../Infrastructure/AppDbContext.cs | 2 ++ .../Infrastructure/Repository.cs | 2 +- .../SWD-Laundry-Backend.Repository.csproj | 4 ++++ .../SWD-Laundry-Backend.Service.csproj | 8 ++++++++ src/SWD-Laundry-Backend/Program.cs | 9 +++++++++ .../SWD-Laundry-Backend.csproj | 6 +++++- 10 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs new file mode 100644 index 0000000..b2b46ec --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs @@ -0,0 +1,16 @@ +namespace SWD_Laundry_Backend.Contract.Repository.Entity; +public class Test : BaseEntity +{ + public string? Name { get; set; } + public string? Address { get; set; } + public string? Phone { get; set; } + public string? Email { get; set; } + public string? Password { get; set; } + public string? Role { get; set; } + public string? Status { get; set; } + public string? Token { get; set; } + public string? RefreshToken { get; set; } + public DateTime? RefreshTokenExpiryTime { get; set; } + public DateTime? CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj index ab97129..4db3ce3 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj +++ b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj @@ -25,4 +25,8 @@ + + + + diff --git a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj index a93d042..44335df 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj +++ b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj index 706d92c..059c09d 100644 --- a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj +++ b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj @@ -10,6 +10,8 @@ + + diff --git a/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs index 889d147..24454a1 100644 --- a/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs +++ b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.cs @@ -1,10 +1,12 @@ using System.Reflection; +using Invedia.DI.Attributes; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using SWD_Laundry_Backend.Core.Utils; using SWD_Laundry_Backend.Repository.Base; namespace SWD_Laundry_Backend.Repository.Infrastructure; + public sealed partial class AppDbContext : BaseDbContext { public readonly int CommandTimeoutInSecond = 20 * 60; diff --git a/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs b/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs index 3d39a9d..4b91bb9 100644 --- a/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs +++ b/src/SWD-Laundry-Backend.Repository/Infrastructure/Repository.cs @@ -7,7 +7,7 @@ namespace SWD_Laundry_Backend.Repository.Infrastructure; public class Repository : BaseRepository, IRepository, IBaseRepository where T : BaseEntity, new() { - public Repository(DbContext dbContext) : base(dbContext) + public Repository(AppDbContext dbContext) : base(dbContext) { } diff --git a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj index 16f16bd..57262bb 100644 --- a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj +++ b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj b/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj index 4089cd6..a17de4e 100644 --- a/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj +++ b/src/SWD-Laundry-Backend.Service/SWD-Laundry-Backend.Service.csproj @@ -7,4 +7,12 @@ enable + + + + + + + + diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index 18a9f5f..e7f8d1a 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -1,10 +1,13 @@ using System.Text.RegularExpressions; +using Invedia.DI; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.EntityFrameworkCore; using Microsoft.OpenApi.Models; using Serilog; using SWD_Laundry_Backend.Core.Config; using SWD_Laundry_Backend.Extensions; +using SWD_Laundry_Backend.Repository.Infrastructure; namespace SWD_Laundry_Backend; @@ -39,6 +42,9 @@ public static void Main(string[] args) options.SwaggerDoc("v1", new OpenApiInfo { Title = "SWD-Laundry-Backend", Version = "v1" }); }); + builder.Services.AddDbContext(); + + builder.Services.AddAutoMapperServices(); builder.Services.AddRouting(options => { @@ -46,6 +52,8 @@ public static void Main(string[] args) } ); _ = builder.Services.AddSystemSetting(builder.Configuration.GetSection("SystemSetting").Get()); builder.Services.Configure(opt => opt.TokenLifespan = TimeSpan.FromMinutes(30)); + builder.Services.AddDI(); + builder.Services.PrintServiceAddedToConsole(); var app = builder.Build(); // Configure the HTTP request pipeline. @@ -64,6 +72,7 @@ public static void Main(string[] args) app.UseSerilogRequestLogging(); app.UseAuthorization(); app.MapControllers(); + app.Run(); } } diff --git a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj index 06664f9..6a5b7d9 100644 --- a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj +++ b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -8,8 +8,12 @@ + + + + From 7e4a5b301d8d7cf2cca9a11b901fa18df4ef99be Mon Sep 17 00:00:00 2001 From: Nero Date: Mon, 2 Oct 2023 00:31:08 +0700 Subject: [PATCH 27/53] Update IBaseRepository.cs --- .../Base Interface/IBaseRepository.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs index cb8d408..f4aa1e6 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs @@ -1,11 +1,12 @@ -using System.Linq.Expressions; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; namespace SWD_Laundry_Backend.Contract.Repository.Base_Interface; public interface IBaseRepository where T : Entity.BaseEntity, new() { - T GetSingle(Expression>? filter = null, params Expression>[]? includes); - IQueryable Get(Expression>? filter = null, params Expression>[]? includes); - int Update(Expression> filter, T entity); - int Delete(Expression> filter); - int Add(T entity); + Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes); + Task> GetAsync(Expression>? filter = null, params Expression>[]? includes); + Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update); + Task DeleteAsync(Expression> filter); + Task AddAsync(T entity); } From 0a0c32a0ca2f68bf562f2722162fff9881e7e911 Mon Sep 17 00:00:00 2001 From: Nero Date: Mon, 2 Oct 2023 00:31:54 +0700 Subject: [PATCH 28/53] Update BaseRepository.cs --- .../Base/BaseRepository.cs | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs index 6479f30..6a439b6 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -1,5 +1,6 @@ -using System.Linq.Expressions; +using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; using SWD_Laundry_Backend.Contract.Repository.Base_Interface; using SWD_Laundry_Backend.Contract.Repository.Entity; @@ -8,34 +9,68 @@ namespace SWD_Laundry_Backend.Repository.Base public abstract class BaseRepository : IBaseRepository where T : BaseEntity, new() { protected readonly DbContext _dbContext; + + private DbSet _dbSet; + + protected DbSet DbSet + { + get + { + if (_dbSet != null) + { + return _dbSet; + } + + _dbSet = _dbContext.Set(); + return _dbSet; + } + } + protected BaseRepository(DbContext dbContext) { - _dbContext = dbContext; + _dbContext = dbContext; } - public int Add(T entity) + public virtual async Task AddAsync(T entity) { - throw new NotImplementedException(); + var e = await DbSet.AddAsync(entity); + return e.Entity; } - public int Delete(Expression> filter) + public virtual async Task DeleteAsync(Expression> filter) { - throw new NotImplementedException(); + var i = await DbSet.Where(filter).ExecuteDeleteAsync(); + return i; } - public IQueryable Get(Expression>? filter = null, params Expression>[]? includes) + public virtual async Task> GetAsync(Expression>? filter = null, params Expression>[]? includes) { - throw new NotImplementedException(); + + return await Task.Run(() => + { + var query = DbSet.AsNoTracking().Where(filter); + if (includes != null) + { + query = includes.Aggregate(query, (current, include) => current.Include(include)); + } + return query; + }); ; } - public T GetSingle(Expression>? filter = null, params Expression>[]? includes) + public virtual async Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes) { - throw new NotImplementedException(); + var query = DbSet.Where(filter).AsNoTracking(); + if (includes != null) + { + query = includes.Aggregate(query, (current, include) => current.Include(include)); + } + return await query.FirstOrDefaultAsync(); } - public int Update(Expression> filter, T entity) + public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update) { - throw new NotImplementedException(); + int i = await DbSet.Where(filter).ExecuteUpdateAsync(update); + return i; } } } From 2a3071f2d36d290c151a8f98a117222f1e0d6516 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 2 Oct 2023 01:55:38 +0700 Subject: [PATCH 29/53] Add Migration, Building Repo, Service, Controller --- .../Base Interface/IBaseRepository.cs | 10 +- .../Entity/Building.cs | 4 +- .../Entity/Customer.cs | 2 +- .../Entity/IdentityModels/ApplicationUser.cs | 2 +- .../Entity/IdentityModels/IdentityRole.cs | 7 +- .../Entity/Order.cs | 6 +- .../Entity/OrderHistory.cs | 2 +- .../Entity/Payment.cs | 2 +- .../Entity/Staff_Trip.cs | 6 +- .../Entity/Test.cs | 16 - .../Entity/Transaction.cs | 2 +- .../Interface/IBuildingRepository.cs | 8 + ...Laundry-Backend.Contract.Repository.csproj | 11 +- .../Base Service Interface/ICreateAble.cs | 5 +- .../Base Service Interface/IDeleteAble.cs | 5 +- .../Base Service Interface/IGetAble.cs | 5 +- .../Base Service Interface/IUpdateAble.cs | 6 +- .../Interface/IBuidingService.cs | 9 + ...WD-Laundry-Backend.Contract.Service.csproj | 4 - .../Models/BaseResponseModels.cs | 7 +- .../Models/BuildingModel.cs | 7 + .../SWD-Laundry-Backend.Core.csproj | 1 + .../BuildingMapperProfile.cs | 14 + .../SWD-Laundry-Backend.Mapper.csproj | 7 +- .../Base/BaseRepository.cs | 30 +- .../Infrastructure/AppDbContext.DbSet.cs | 17 +- .../20231001181800_Init-Migration.Designer.cs | 675 ++++++++++++++++++ .../20231001181800_Init-Migration.cs | 449 ++++++++++++ .../Migrations/AppDbContextModelSnapshot.cs | 672 +++++++++++++++++ .../Repository/BuildingRepository.cs | 14 + .../SWD-Laundry-Backend.Repository.csproj | 4 - .../Services/BuildingService.cs | 48 ++ .../Controllers/BuildingController.cs | 27 + .../Extensions/AutoMapperExtension.cs | 6 +- src/SWD-Laundry-Backend/Program.cs | 10 +- .../SWD-Laundry-Backend.csproj | 1 + .../appsettings.Development.json | 2 +- src/SWD-Laundry-Backend/appsettings.json | 5 +- 38 files changed, 2010 insertions(+), 98 deletions(-) delete mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Repository/Interface/IBuildingRepository.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Interface/IBuidingService.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/BuildingModel.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.Designer.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Repository/BuildingRepository.cs create mode 100644 src/SWD-Laundry-Backend.Service/Services/BuildingService.cs create mode 100644 src/SWD-Laundry-Backend/Controllers/BuildingController.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs index f4aa1e6..85f4bfd 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs @@ -4,9 +4,9 @@ namespace SWD_Laundry_Backend.Contract.Repository.Base_Interface; public interface IBaseRepository where T : Entity.BaseEntity, new() { - Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes); - Task> GetAsync(Expression>? filter = null, params Expression>[]? includes); - Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update); - Task DeleteAsync(Expression> filter); - Task AddAsync(T entity); + Task GetSingleAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes); + Task> GetAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes); + Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update, CancellationToken cancellationToken = default); + Task DeleteAsync(Expression> filter, CancellationToken cancellationToken = default); + Task AddAsync(T entity, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs index 7193b25..9b769ef 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Building.cs @@ -1,6 +1,4 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; - -namespace SWD_Laundry_Backend.Contract.Repository.Entity; +namespace SWD_Laundry_Backend.Contract.Repository.Entity; #nullable disable public class Building : BaseEntity diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs index 75da97c..346b92c 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs @@ -14,7 +14,7 @@ public class Customer : BaseEntity #region Relationship [ForeignKey("Building")] - public int BuildingID { get; set; } + public string BuildingID { get; set; } [ForeignKey("ApplicationUser")] public string ApplicationUserID { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs index 102034d..1db7d3f 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/ApplicationUser.cs @@ -12,7 +12,7 @@ public class ApplicationUser : IdentityUser #region Relationship [ForeignKey("Wallet")] - public int WalletID { get; set; } + public string WalletID { get; set; } public Wallet Wallet { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs index 1c28792..4070187 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity; namespace SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; public class ApplicationRole : IdentityRole diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs index b0d357f..c60caf6 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Order.cs @@ -18,13 +18,13 @@ public class Order : BaseEntity #region Relationship [ForeignKey("Customer")] - public int CustomerID { get; set; } + public string CustomerID { get; set; } [ForeignKey(nameof(LaundryStore))] - public int LaundryStoreID { get; set; } + public string LaundryStoreID { get; set; } [ForeignKey(nameof(Staff))] - public int StaffID { get; set; } + public string StaffID { get; set; } ////=========================== public Customer Customer { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs index 951d9cc..47302de 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/OrderHistory.cs @@ -13,7 +13,7 @@ public class OrderHistory : BaseEntity #region Relationship [ForeignKey("Order")] - public int OrderID { get; set; } + public string OrderID { get; set; } public Order Order { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs index 1aeb4ce..cc1ace4 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Payment.cs @@ -10,7 +10,7 @@ public class Payment : BaseEntity #region Relationship [ForeignKey(nameof(Order))] - public int OrderId { get; set; } + public string OrderId { get; set; } public Transaction Transaction { get; set; } public Order Orders { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs index 321a354..cd2bd94 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs @@ -11,13 +11,13 @@ public class Staff_Trip : BaseEntity #region Relationship [ForeignKey("Staff")] - public int StaffID { get; set; } + public string StaffID { get; set; } [ForeignKey("TimeSchedule")] - public int TimeScheduleID { get; set; } + public string TimeScheduleID { get; set; } [ForeignKey("Building")] - public int BuildingID { get; set; } + public string BuildingID { get; set; } public Building Building { get; set; } public Staff Staff { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs deleted file mode 100644 index b2b46ec..0000000 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Test.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace SWD_Laundry_Backend.Contract.Repository.Entity; -public class Test : BaseEntity -{ - public string? Name { get; set; } - public string? Address { get; set; } - public string? Phone { get; set; } - public string? Email { get; set; } - public string? Password { get; set; } - public string? Role { get; set; } - public string? Status { get; set; } - public string? Token { get; set; } - public string? RefreshToken { get; set; } - public DateTime? RefreshTokenExpiryTime { get; set; } - public DateTime? CreatedAt { get; set; } - public DateTime? UpdatedAt { get; set; } -} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs index cc492e5..1afc784 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs @@ -14,7 +14,7 @@ public class Transaction : BaseEntity #region Relationship [ForeignKey(nameof(Wallet))] - public int WalletID { get; set; } + public string WalletID { get; set; } public Wallet Wallet { get; set; } public List Payments { get; set; } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Interface/IBuildingRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Interface/IBuildingRepository.cs new file mode 100644 index 0000000..aa677ac --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Repository/Interface/IBuildingRepository.cs @@ -0,0 +1,8 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Contract.Repository.Interface; +public interface IBuildingRepository : IRepository +{ + +} diff --git a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj index 4db3ce3..63275a1 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj +++ b/src/SWD-Laundry-Backend.Contract.Repository/SWD-Laundry-Backend.Contract.Repository.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -10,10 +10,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + all @@ -25,8 +22,4 @@ - - - - diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs index 6e32864..8a6bb81 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/ICreateAble.cs @@ -1,8 +1,7 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; - + namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface { - public interface ICreateAble where T : BaseEntity, new() + public interface ICreateAble where T : class, new() { Task CreateAsync(T model, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs index 57f2493..e2d417a 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs @@ -1,7 +1,6 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; - + namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; -public interface IDeleteAble where TKey : BaseEntity +public interface IDeleteAble where TKey : class { Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs index 91b55dc..eecd1a2 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs @@ -1,7 +1,6 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; - + namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; -public interface IGetAble where T : BaseEntity +public interface IGetAble where T : class { Task> GetAllAsync(CancellationToken cancellationToken = default); Task GetByIdAsync(TKey id, CancellationToken cancellationToken = default); diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs index 77cfc6b..458325b 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs @@ -1,7 +1,5 @@ -using SWD_Laundry_Backend.Contract.Repository.Entity; - -namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; -public interface IUpdateAble where T : BaseEntity, new() +namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +public interface IUpdateAble where T : class, new() { Task UpdateAsync(Tkey id, T model, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/IBuidingService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/IBuidingService.cs new file mode 100644 index 0000000..bae7327 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/IBuidingService.cs @@ -0,0 +1,9 @@ +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Contract.Service.Interface; +public interface IBuidingService : ICreateAble, IGetAble, IUpdateAble, IDeleteAble +{ + +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj index 44335df..a93d042 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj +++ b/src/SWD-Laundry-Backend.Contract.Service/SWD-Laundry-Backend.Contract.Service.csproj @@ -11,8 +11,4 @@ - - - - diff --git a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs index c2b23ca..2950328 100644 --- a/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs +++ b/src/SWD-Laundry-Backend.Core/Models/BaseResponseModels.cs @@ -5,20 +5,17 @@ public class BaseResponseModel public object? AdditionalData { get; set; } public string? Message { get; set; } public int StatusCode { get; set; } - public string Code { get; set; } - public BaseResponseModel(int statusCode, string code, T? data, object? additionalData = null) + public BaseResponseModel(int statusCode, T? data, object? additionalData = null) { this.StatusCode = statusCode; - this.Code = code; this.Data = data; this.AdditionalData = additionalData; } - public BaseResponseModel(int statusCode, string code, string? message) + public BaseResponseModel(int statusCode, string? message) { this.StatusCode = statusCode; - this.Code = code; this.Message = message; } } diff --git a/src/SWD-Laundry-Backend.Core/Models/BuildingModel.cs b/src/SWD-Laundry-Backend.Core/Models/BuildingModel.cs new file mode 100644 index 0000000..c2dcc35 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/BuildingModel.cs @@ -0,0 +1,7 @@ +namespace SWD_Laundry_Backend.Core.Models; +public class BuildingModel +{ + public string? Name { get; set; } + public string? Address { get; set; } + public string? Description { get; set; } +} diff --git a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj index 059c09d..4280e60 100644 --- a/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj +++ b/src/SWD-Laundry-Backend.Core/SWD-Laundry-Backend.Core.csproj @@ -12,6 +12,7 @@ + diff --git a/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs new file mode 100644 index 0000000..a46dfc9 --- /dev/null +++ b/src/SWD-Laundry-Backend.Mapper/BuildingMapperProfile.cs @@ -0,0 +1,14 @@ +using AutoMapper; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Mapper +{ + public class BuildingMapperProfile : Profile + { + public BuildingMapperProfile() + { + CreateMap().ReverseMap(); + } + } +} diff --git a/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj b/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj index 02abd3d..f598764 100644 --- a/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj +++ b/src/SWD-Laundry-Backend.Mapper/SWD-Laundry-Backend.Mapper.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -7,4 +7,9 @@ enable + + + + + diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs index 6a439b6..b75a3b9 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -31,24 +31,28 @@ protected BaseRepository(DbContext dbContext) _dbContext = dbContext; } - public virtual async Task AddAsync(T entity) + public virtual async Task AddAsync(T entity, CancellationToken cancellationToken = default) { - var e = await DbSet.AddAsync(entity); + var e = await DbSet.AddAsync(entity, cancellationToken); return e.Entity; } - public virtual async Task DeleteAsync(Expression> filter) + public virtual async Task DeleteAsync(Expression> filter, CancellationToken cancellationToken = default) { - var i = await DbSet.Where(filter).ExecuteDeleteAsync(); + var i = await DbSet.Where(filter).ExecuteDeleteAsync(cancellationToken); return i; } - public virtual async Task> GetAsync(Expression>? filter = null, params Expression>[]? includes) + public virtual async Task> GetAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes) { return await Task.Run(() => { - var query = DbSet.AsNoTracking().Where(filter); + var query = DbSet.AsNoTracking(); + if(filter != null) + { + query = query.Where(filter); + } if (includes != null) { query = includes.Aggregate(query, (current, include) => current.Include(include)); @@ -57,19 +61,23 @@ public virtual async Task> GetAsync(Expression>? fil }); ; } - public virtual async Task GetSingleAsync(Expression>? filter = null, params Expression>[]? includes) + public virtual async Task GetSingleAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes) { - var query = DbSet.Where(filter).AsNoTracking(); + var query = DbSet.AsNoTracking(); + if(filter != null) + { + query = query.Where(filter); + } if (includes != null) { query = includes.Aggregate(query, (current, include) => current.Include(include)); } - return await query.FirstOrDefaultAsync(); + return await query.FirstOrDefaultAsync(cancellationToken); } - public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update) + public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update, CancellationToken cancellationToken = default) { - int i = await DbSet.Where(filter).ExecuteUpdateAsync(update); + int i = await DbSet.Where(filter).ExecuteUpdateAsync(update, cancellationToken); return i; } } diff --git a/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs index 43a14a9..b969641 100644 --- a/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs +++ b/src/SWD-Laundry-Backend.Repository/Infrastructure/AppDbContext.DbSet.cs @@ -1,5 +1,18 @@ -namespace SWD_Laundry_Backend.Repository.Infrastructure; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity; + +namespace SWD_Laundry_Backend.Repository.Infrastructure; public sealed partial class AppDbContext { - + public DbSet Buildings { get; set; } + public DbSet Staffs { get; set; } + public DbSet Staff_Trips { get; set; } + public DbSet TimeSchedules { get; set; } + public DbSet Wallets { get; set; } + public DbSet Customers { get; set; } + public DbSet LaundryStores { get; set; } + public DbSet Orders { get; set; } + public DbSet OrderHistories { get; set; } + public DbSet Payments { get; set; } + public DbSet Transaction { get; set; } } diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.Designer.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.Designer.cs new file mode 100644 index 0000000..c3cb383 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.Designer.cs @@ -0,0 +1,675 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SWD_Laundry_Backend.Repository.Infrastructure; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20231001181800_Init-Migration")] + partial class InitMigration + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.HasIndex("BuildingID"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + 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.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("WalletID") + .IsUnique() + .HasFilter("[WalletID] IS NOT NULL"); + + b.ToTable("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("CustomerID") + .HasColumnType("nvarchar(450)"); + + b.Property("DeliveryTimeFrame") + .HasColumnType("int"); + + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStoreID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderDate") + .HasColumnType("datetime2"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("PaymentType") + .HasColumnType("int"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TotalPrice") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreID"); + + b.HasIndex("StaffID"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DeliveryStatus") + .HasColumnType("int"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStatus") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("OrderID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderStatus") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrderID"); + + b.ToTable("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("Price") + .HasColumnType("float"); + + b.Property("TransactionId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("TransactionId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TimeScheduleID") + .HasColumnType("nvarchar(450)"); + + b.Property("TripCollect") + .HasColumnType("int"); + + b.Property("TripType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BuildingID"); + + b.HasIndex("StaffID"); + + b.HasIndex("TimeScheduleID"); + + b.ToTable("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("PaymentMethod") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionType") + .HasColumnType("int"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("WalletID"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Balance") + .HasColumnType("float"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Wallets"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Dob") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Salary") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Customers") + .HasForeignKey("BuildingID"); + + b.Navigation("ApplicationUser"); + + b.Navigation("Building"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", "Customer") + .WithMany("Order") + .HasForeignKey("CustomerID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", "LaundryStore") + .WithMany("Orders") + .HasForeignKey("LaundryStoreID"); + + b.HasOne("Staff", "Staff") + .WithMany() + .HasForeignKey("StaffID"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Order") + .WithMany("OrderHistories") + .HasForeignKey("OrderID"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Orders") + .WithMany("Payments") + .HasForeignKey("OrderId"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", "Transaction") + .WithMany("Payments") + .HasForeignKey("TransactionId"); + + b.Navigation("Orders"); + + b.Navigation("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Staff_Trips") + .HasForeignKey("BuildingID"); + + b.HasOne("Staff", "Staff") + .WithMany("Staff_Trips") + .HasForeignKey("StaffID"); + + b.HasOne("TimeSchedule", "TimeSchedule") + .WithMany("Staff_Trip") + .HasForeignKey("TimeScheduleID"); + + b.Navigation("Building"); + + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithMany("Transactions") + .HasForeignKey("WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("Staff", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Navigation("Customers"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Navigation("OrderHistories"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Navigation("ApplicationUser"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Navigation("Staff_Trip"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.cs new file mode 100644 index 0000000..4e12dec --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231001181800_Init-Migration.cs @@ -0,0 +1,449 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + /// + public partial class InitMigration : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Buildings", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), + Address = table.Column(type: "nvarchar(max)", nullable: true), + Description = table.Column(type: "nvarchar(max)", nullable: true), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Buildings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "TimeSchedules", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false), + DayOfWeek = table.Column(type: "int", nullable: false), + TimeFrame = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TimeSchedules", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Wallets", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Balance = table.Column(type: "float", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Wallets", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ApplicationUser", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), + WalletID = table.Column(type: "nvarchar(450)", nullable: true), + UserName = table.Column(type: "nvarchar(max)", nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(max)", nullable: true), + Email = table.Column(type: "nvarchar(max)", nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(max)", nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicationUser", x => x.Id); + table.ForeignKey( + name: "FK_ApplicationUser_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Transaction", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + PaymentMethod = table.Column(type: "nvarchar(max)", nullable: true), + Amount = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + WalletID = table.Column(type: "nvarchar(450)", nullable: true), + TransactionType = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Transaction", x => x.Id); + table.ForeignKey( + name: "FK_Transaction_Wallets_WalletID", + column: x => x.WalletID, + principalTable: "Wallets", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Customers", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + BuildingID = table.Column(type: "nvarchar(450)", nullable: true), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Customers", x => x.Id); + table.ForeignKey( + name: "FK_Customers_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Customers_Buildings_BuildingID", + column: x => x.BuildingID, + principalTable: "Buildings", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "LaundryStores", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: true), + Address = table.Column(type: "nvarchar(max)", nullable: true), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false), + Status = table.Column(type: "bit", nullable: false), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_LaundryStores", x => x.Id); + table.ForeignKey( + name: "FK_LaundryStores_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Staffs", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Dob = table.Column(type: "datetime2", nullable: false), + Address = table.Column(type: "nvarchar(max)", nullable: true), + Salary = table.Column(type: "float", nullable: false), + ApplicationUserID = table.Column(type: "nvarchar(450)", nullable: true), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Staffs", x => x.Id); + table.ForeignKey( + name: "FK_Staffs_ApplicationUser_ApplicationUserID", + column: x => x.ApplicationUserID, + principalTable: "ApplicationUser", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + OrderDate = table.Column(type: "datetime2", nullable: false), + DeliveryTimeFrame = table.Column(type: "int", nullable: false), + ExpectedFinishDate = table.Column(type: "datetime2", nullable: false), + Address = table.Column(type: "nvarchar(max)", nullable: true), + Amount = table.Column(type: "smallint", nullable: false), + TotalPrice = table.Column(type: "float", nullable: false), + CustomerID = table.Column(type: "nvarchar(450)", nullable: true), + LaundryStoreID = table.Column(type: "nvarchar(450)", nullable: true), + StaffID = table.Column(type: "nvarchar(450)", nullable: true), + OrderType = table.Column(type: "int", nullable: false), + PaymentType = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Customers_CustomerID", + column: x => x.CustomerID, + principalTable: "Customers", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Orders_LaundryStores_LaundryStoreID", + column: x => x.LaundryStoreID, + principalTable: "LaundryStores", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Orders_Staffs_StaffID", + column: x => x.StaffID, + principalTable: "Staffs", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Staff_Trips", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + TripCollect = table.Column(type: "int", nullable: false), + StaffID = table.Column(type: "nvarchar(450)", nullable: true), + TimeScheduleID = table.Column(type: "nvarchar(450)", nullable: true), + BuildingID = table.Column(type: "nvarchar(450)", nullable: true), + TripType = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Staff_Trips", x => x.Id); + table.ForeignKey( + name: "FK_Staff_Trips_Buildings_BuildingID", + column: x => x.BuildingID, + principalTable: "Buildings", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Staff_Trips_Staffs_StaffID", + column: x => x.StaffID, + principalTable: "Staffs", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Staff_Trips_TimeSchedules_TimeScheduleID", + column: x => x.TimeScheduleID, + principalTable: "TimeSchedules", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "OrderHistories", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Title = table.Column(type: "nvarchar(max)", nullable: true), + Message = table.Column(type: "nvarchar(max)", nullable: true), + OrderID = table.Column(type: "nvarchar(450)", nullable: true), + OrderStatus = table.Column(type: "int", nullable: false), + DeliveryStatus = table.Column(type: "int", nullable: false), + LaundryStatus = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OrderHistories", x => x.Id); + table.ForeignKey( + name: "FK_OrderHistories_Orders_OrderID", + column: x => x.OrderID, + principalTable: "Orders", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Payments", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Price = table.Column(type: "float", nullable: false), + OrderId = table.Column(type: "nvarchar(450)", nullable: true), + TransactionId = table.Column(type: "nvarchar(450)", nullable: true), + CreatedBy = table.Column(type: "nvarchar(max)", nullable: true), + LastUpdatedBy = table.Column(type: "nvarchar(max)", nullable: true), + CreatedTime = table.Column(type: "datetimeoffset", nullable: true), + LastUpdatedTime = table.Column(type: "datetimeoffset", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Payments", x => x.Id); + table.ForeignKey( + name: "FK_Payments_Orders_OrderId", + column: x => x.OrderId, + principalTable: "Orders", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Payments_Transaction_TransactionId", + column: x => x.TransactionId, + principalTable: "Transaction", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApplicationUser_WalletID", + table: "ApplicationUser", + column: "WalletID", + unique: true, + filter: "[WalletID] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_Customers_ApplicationUserID", + table: "Customers", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_Customers_BuildingID", + table: "Customers", + column: "BuildingID"); + + migrationBuilder.CreateIndex( + name: "IX_LaundryStores_ApplicationUserID", + table: "LaundryStores", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_OrderHistories_OrderID", + table: "OrderHistories", + column: "OrderID"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_CustomerID", + table: "Orders", + column: "CustomerID"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_LaundryStoreID", + table: "Orders", + column: "LaundryStoreID"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_StaffID", + table: "Orders", + column: "StaffID"); + + migrationBuilder.CreateIndex( + name: "IX_Payments_OrderId", + table: "Payments", + column: "OrderId"); + + migrationBuilder.CreateIndex( + name: "IX_Payments_TransactionId", + table: "Payments", + column: "TransactionId"); + + migrationBuilder.CreateIndex( + name: "IX_Staff_Trips_BuildingID", + table: "Staff_Trips", + column: "BuildingID"); + + migrationBuilder.CreateIndex( + name: "IX_Staff_Trips_StaffID", + table: "Staff_Trips", + column: "StaffID"); + + migrationBuilder.CreateIndex( + name: "IX_Staff_Trips_TimeScheduleID", + table: "Staff_Trips", + column: "TimeScheduleID"); + + migrationBuilder.CreateIndex( + name: "IX_Staffs_ApplicationUserID", + table: "Staffs", + column: "ApplicationUserID"); + + migrationBuilder.CreateIndex( + name: "IX_Transaction_WalletID", + table: "Transaction", + column: "WalletID"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "OrderHistories"); + + migrationBuilder.DropTable( + name: "Payments"); + + migrationBuilder.DropTable( + name: "Staff_Trips"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "Transaction"); + + migrationBuilder.DropTable( + name: "TimeSchedules"); + + migrationBuilder.DropTable( + name: "Customers"); + + migrationBuilder.DropTable( + name: "LaundryStores"); + + migrationBuilder.DropTable( + name: "Staffs"); + + migrationBuilder.DropTable( + name: "Buildings"); + + migrationBuilder.DropTable( + name: "ApplicationUser"); + + migrationBuilder.DropTable( + name: "Wallets"); + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs new file mode 100644 index 0000000..ce95ae4 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs @@ -0,0 +1,672 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SWD_Laundry_Backend.Repository.Infrastructure; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + [DbContext(typeof(AppDbContext))] + partial class AppDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.HasIndex("BuildingID"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + 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.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("WalletID") + .IsUnique() + .HasFilter("[WalletID] IS NOT NULL"); + + b.ToTable("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("CustomerID") + .HasColumnType("nvarchar(450)"); + + b.Property("DeliveryTimeFrame") + .HasColumnType("int"); + + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStoreID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderDate") + .HasColumnType("datetime2"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("PaymentType") + .HasColumnType("int"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TotalPrice") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreID"); + + b.HasIndex("StaffID"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DeliveryStatus") + .HasColumnType("int"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStatus") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("OrderID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderStatus") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrderID"); + + b.ToTable("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("Price") + .HasColumnType("float"); + + b.Property("TransactionId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("TransactionId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TimeScheduleID") + .HasColumnType("nvarchar(450)"); + + b.Property("TripCollect") + .HasColumnType("int"); + + b.Property("TripType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BuildingID"); + + b.HasIndex("StaffID"); + + b.HasIndex("TimeScheduleID"); + + b.ToTable("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("PaymentMethod") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionType") + .HasColumnType("int"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("WalletID"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Balance") + .HasColumnType("float"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Wallets"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Dob") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Salary") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Customers") + .HasForeignKey("BuildingID"); + + b.Navigation("ApplicationUser"); + + b.Navigation("Building"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", "Customer") + .WithMany("Order") + .HasForeignKey("CustomerID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", "LaundryStore") + .WithMany("Orders") + .HasForeignKey("LaundryStoreID"); + + b.HasOne("Staff", "Staff") + .WithMany() + .HasForeignKey("StaffID"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Order") + .WithMany("OrderHistories") + .HasForeignKey("OrderID"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Orders") + .WithMany("Payments") + .HasForeignKey("OrderId"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", "Transaction") + .WithMany("Payments") + .HasForeignKey("TransactionId"); + + b.Navigation("Orders"); + + b.Navigation("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Staff_Trips") + .HasForeignKey("BuildingID"); + + b.HasOne("Staff", "Staff") + .WithMany("Staff_Trips") + .HasForeignKey("StaffID"); + + b.HasOne("TimeSchedule", "TimeSchedule") + .WithMany("Staff_Trip") + .HasForeignKey("TimeScheduleID"); + + b.Navigation("Building"); + + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithMany("Transactions") + .HasForeignKey("WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("Staff", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Navigation("Customers"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Navigation("OrderHistories"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Navigation("ApplicationUser"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Navigation("Staff_Trip"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Repository/BuildingRepository.cs b/src/SWD-Laundry-Backend.Repository/Repository/BuildingRepository.cs new file mode 100644 index 0000000..940c7db --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Repository/BuildingRepository.cs @@ -0,0 +1,14 @@ +using Invedia.DI.Attributes; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Repository.Infrastructure; + +namespace SWD_Laundry_Backend.Repository.Repository; +[ScopedDependency(ServiceType = typeof(IBuildingRepository))] +public class BuildingRepository : Repository, IBuildingRepository +{ + public BuildingRepository(AppDbContext dbContext) : base(dbContext) + { + + } +} diff --git a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj index 57262bb..16f16bd 100644 --- a/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj +++ b/src/SWD-Laundry-Backend.Repository/SWD-Laundry-Backend.Repository.csproj @@ -11,8 +11,4 @@ - - - - diff --git a/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs b/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs new file mode 100644 index 0000000..ae53b51 --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs @@ -0,0 +1,48 @@ +using AutoMapper; +using Invedia.DI.Attributes; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Repository.Interface; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Service.Services; +[ScopedDependency(ServiceType = typeof(IBuidingService))] +public class BuildingService : Base_Service.Service, IBuidingService +{ + + private readonly IBuildingRepository _buildingRepository; + private readonly IMapper _mapper; + + public BuildingService (IBuildingRepository buildingRepository, IMapper mapper) + { + _buildingRepository = buildingRepository; + _mapper = mapper; + } + + public Task CreateAsync(BuildingModel model, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(string id, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public async Task> GetAllAsync(CancellationToken cancellationToken = default) + { + var buildings = await _buildingRepository.GetAsync(cancellationToken: cancellationToken); + return await buildings.ToListAsync(cancellationToken: cancellationToken); + } + + public Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(string id, BuildingModel model, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } +} diff --git a/src/SWD-Laundry-Backend/Controllers/BuildingController.cs b/src/SWD-Laundry-Backend/Controllers/BuildingController.cs new file mode 100644 index 0000000..4abf2f3 --- /dev/null +++ b/src/SWD-Laundry-Backend/Controllers/BuildingController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Controllers; +[ApiController] +public class BuildingController : ApiControllerBase +{ + private readonly IBuidingService _buildingService; + + public BuildingController(IBuidingService buildingService) + { + _buildingService = buildingService; + } + + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesDefaultResponseType] + public async Task GetAll() + { + var result = await _buildingService.GetAllAsync(); + return Ok(new BaseResponseModel?>(StatusCodes.Status200OK, data: result)); + } + +} diff --git a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs index 3a818c5..8f5a041 100644 --- a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs +++ b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs @@ -1,4 +1,6 @@ -namespace SWD_Laundry_Backend.Extensions; +using SWD_Laundry_Backend.Mapper; + +namespace SWD_Laundry_Backend.Extensions; public static class AutoMapperExtension @@ -7,7 +9,7 @@ public static IServiceCollection AddAutoMapperServices(this IServiceCollection s { services.AddAutoMapper(cfg => { - + cfg.AddProfile(); }); return services; } diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index e7f8d1a..fbbae3b 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -42,7 +42,13 @@ public static void Main(string[] args) options.SwaggerDoc("v1", new OpenApiInfo { Title = "SWD-Laundry-Backend", Version = "v1" }); }); - builder.Services.AddDbContext(); + builder.Services.AddDbContext(options => + { + options.UseSqlServer( + connectionString, + x => x.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName) + ); + }); builder.Services.AddAutoMapperServices(); @@ -70,6 +76,8 @@ public static void Main(string[] args) app.UseHttpsRedirection(); app.UseSerilogRequestLogging(); + app.UseAuthentication(); + //app.UseIdentityServer(); app.UseAuthorization(); app.MapControllers(); diff --git a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj index 6a5b7d9..ed0f27c 100644 --- a/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj +++ b/src/SWD-Laundry-Backend/SWD-Laundry-Backend.csproj @@ -5,6 +5,7 @@ enable enable SWD_Laundry_Backend + True diff --git a/src/SWD-Laundry-Backend/appsettings.Development.json b/src/SWD-Laundry-Backend/appsettings.Development.json index 6653762..76b9bb2 100644 --- a/src/SWD-Laundry-Backend/appsettings.Development.json +++ b/src/SWD-Laundry-Backend/appsettings.Development.json @@ -6,6 +6,6 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Data Source=(localdb)\\ProjectModels;Initial Catalog=Laundry;user=sa;pwd=12345;Trusted_Connection=True;Trust Server Certificate=True" + "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Laundry;user=sa;pwd=12345;Trusted_Connection=True;Trust Server Certificate=True" } } diff --git a/src/SWD-Laundry-Backend/appsettings.json b/src/SWD-Laundry-Backend/appsettings.json index 64ce3c9..10f68b8 100644 --- a/src/SWD-Laundry-Backend/appsettings.json +++ b/src/SWD-Laundry-Backend/appsettings.json @@ -5,8 +5,5 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*", - "ConnectionStrings": { - "DefaultConnection": "Server = LEWIS; Database = LaundryStoreDB; User Id = sa; Password = 123456; TrustServerCertificate = true" - } + "AllowedHosts": "*" } From cbd68c3c36078cf78c4772de54644f8f1d065355 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 2 Oct 2023 02:34:59 +0700 Subject: [PATCH 30/53] Identity-Update --- .../Base/BaseDbContext.cs | 6 +- ...20231001193237_Identity-Update.Designer.cs | 872 ++++++++++++++++++ .../20231001193237_Identity-Update.cs | 407 ++++++++ .../Migrations/AppDbContextModelSnapshot.cs | 207 ++++- src/SWD-Laundry-Backend/Program.cs | 13 +- 5 files changed, 1496 insertions(+), 9 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.Designer.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.cs diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs index 0299655..1748442 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseDbContext.cs @@ -1,7 +1,9 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; namespace SWD_Laundry_Backend.Repository.Base; -public abstract class BaseDbContext : DbContext +public abstract class BaseDbContext : IdentityDbContext { protected BaseDbContext(DbContextOptions options) : base(options) { diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.Designer.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.Designer.cs new file mode 100644 index 0000000..b6294ba --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.Designer.cs @@ -0,0 +1,872 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SWD_Laundry_Backend.Repository.Infrastructure; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20231001193237_Identity-Update")] + partial class IdentityUpdate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.HasIndex("BuildingID"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + 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") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.HasIndex("WalletID") + .IsUnique() + .HasFilter("[WalletID] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("CustomerID") + .HasColumnType("nvarchar(450)"); + + b.Property("DeliveryTimeFrame") + .HasColumnType("int"); + + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStoreID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderDate") + .HasColumnType("datetime2"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("PaymentType") + .HasColumnType("int"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TotalPrice") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreID"); + + b.HasIndex("StaffID"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DeliveryStatus") + .HasColumnType("int"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStatus") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("OrderID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderStatus") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrderID"); + + b.ToTable("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("Price") + .HasColumnType("float"); + + b.Property("TransactionId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("TransactionId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TimeScheduleID") + .HasColumnType("nvarchar(450)"); + + b.Property("TripCollect") + .HasColumnType("int"); + + b.Property("TripType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BuildingID"); + + b.HasIndex("StaffID"); + + b.HasIndex("TimeScheduleID"); + + b.ToTable("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("PaymentMethod") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionType") + .HasColumnType("int"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("WalletID"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Balance") + .HasColumnType("float"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Wallets"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Dob") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Salary") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Customers") + .HasForeignKey("BuildingID"); + + b.Navigation("ApplicationUser"); + + b.Navigation("Building"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", "Customer") + .WithMany("Order") + .HasForeignKey("CustomerID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", "LaundryStore") + .WithMany("Orders") + .HasForeignKey("LaundryStoreID"); + + b.HasOne("Staff", "Staff") + .WithMany() + .HasForeignKey("StaffID"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Order") + .WithMany("OrderHistories") + .HasForeignKey("OrderID"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Orders") + .WithMany("Payments") + .HasForeignKey("OrderId"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", "Transaction") + .WithMany("Payments") + .HasForeignKey("TransactionId"); + + b.Navigation("Orders"); + + b.Navigation("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Staff_Trips") + .HasForeignKey("BuildingID"); + + b.HasOne("Staff", "Staff") + .WithMany("Staff_Trips") + .HasForeignKey("StaffID"); + + b.HasOne("TimeSchedule", "TimeSchedule") + .WithMany("Staff_Trip") + .HasForeignKey("TimeScheduleID"); + + b.Navigation("Building"); + + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithMany("Transactions") + .HasForeignKey("WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("Staff", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Navigation("Customers"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Navigation("OrderHistories"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Navigation("ApplicationUser"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Navigation("Staff_Trip"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.cs new file mode 100644 index 0000000..d3594b9 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231001193237_Identity-Update.cs @@ -0,0 +1,407 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + /// + public partial class IdentityUpdate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_ApplicationUser_Wallets_WalletID", + table: "ApplicationUser"); + + migrationBuilder.DropForeignKey( + name: "FK_Customers_ApplicationUser_ApplicationUserID", + table: "Customers"); + + migrationBuilder.DropForeignKey( + name: "FK_LaundryStores_ApplicationUser_ApplicationUserID", + table: "LaundryStores"); + + migrationBuilder.DropForeignKey( + name: "FK_Staffs_ApplicationUser_ApplicationUserID", + table: "Staffs"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ApplicationUser", + table: "ApplicationUser"); + + migrationBuilder.RenameTable( + name: "ApplicationUser", + newName: "AspNetUsers"); + + migrationBuilder.RenameIndex( + name: "IX_ApplicationUser_WalletID", + table: "AspNetUsers", + newName: "IX_AspNetUsers_WalletID"); + + migrationBuilder.AlterColumn( + name: "UserName", + table: "AspNetUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedUserName", + table: "AspNetUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedEmail", + table: "AspNetUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Email", + table: "AspNetUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_AspNetUsers", + table: "AspNetUsers", + column: "Id"); + + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.AddForeignKey( + name: "FK_AspNetUsers_Wallets_WalletID", + table: "AspNetUsers", + column: "WalletID", + principalTable: "Wallets", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Customers_AspNetUsers_ApplicationUserID", + table: "Customers", + column: "ApplicationUserID", + principalTable: "AspNetUsers", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_LaundryStores_AspNetUsers_ApplicationUserID", + table: "LaundryStores", + column: "ApplicationUserID", + principalTable: "AspNetUsers", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Staffs_AspNetUsers_ApplicationUserID", + table: "Staffs", + column: "ApplicationUserID", + principalTable: "AspNetUsers", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AspNetUsers_Wallets_WalletID", + table: "AspNetUsers"); + + migrationBuilder.DropForeignKey( + name: "FK_Customers_AspNetUsers_ApplicationUserID", + table: "Customers"); + + migrationBuilder.DropForeignKey( + name: "FK_LaundryStores_AspNetUsers_ApplicationUserID", + table: "LaundryStores"); + + migrationBuilder.DropForeignKey( + name: "FK_Staffs_AspNetUsers_ApplicationUserID", + table: "Staffs"); + + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropPrimaryKey( + name: "PK_AspNetUsers", + table: "AspNetUsers"); + + migrationBuilder.DropIndex( + name: "EmailIndex", + table: "AspNetUsers"); + + migrationBuilder.DropIndex( + name: "UserNameIndex", + table: "AspNetUsers"); + + migrationBuilder.RenameTable( + name: "AspNetUsers", + newName: "ApplicationUser"); + + migrationBuilder.RenameIndex( + name: "IX_AspNetUsers_WalletID", + table: "ApplicationUser", + newName: "IX_ApplicationUser_WalletID"); + + migrationBuilder.AlterColumn( + name: "UserName", + table: "ApplicationUser", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedUserName", + table: "ApplicationUser", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedEmail", + table: "ApplicationUser", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Email", + table: "ApplicationUser", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_ApplicationUser", + table: "ApplicationUser", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_ApplicationUser_Wallets_WalletID", + table: "ApplicationUser", + column: "WalletID", + principalTable: "Wallets", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Customers_ApplicationUser_ApplicationUserID", + table: "Customers", + column: "ApplicationUserID", + principalTable: "ApplicationUser", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_LaundryStores_ApplicationUser_ApplicationUserID", + table: "LaundryStores", + column: "ApplicationUserID", + principalTable: "ApplicationUser", + principalColumn: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Staffs_ApplicationUser_ApplicationUserID", + table: "Staffs", + column: "ApplicationUserID", + principalTable: "ApplicationUser", + principalColumn: "Id"); + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs index ce95ae4..65579ab 100644 --- a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs +++ b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs @@ -22,6 +22,139 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => { b.Property("Id") @@ -94,10 +227,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasColumnType("nvarchar(max)"); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("EmailConfirmed") .HasColumnType("bit"); @@ -112,10 +247,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("NormalizedEmail") - .HasColumnType("nvarchar(max)"); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedUserName") - .HasColumnType("nvarchar(max)"); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); @@ -133,18 +270,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("bit"); b.Property("UserName") - .HasColumnType("nvarchar(max)"); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("WalletID") .HasColumnType("nvarchar(450)"); b.HasKey("Id"); + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + b.HasIndex("WalletID") .IsUnique() .HasFilter("[WalletID] IS NOT NULL"); - b.ToTable("ApplicationUser"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => @@ -504,6 +650,57 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("TimeSchedules"); }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => { b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index fbbae3b..4a5aa5c 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.OpenApi.Models; using Serilog; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; using SWD_Laundry_Backend.Core.Config; using SWD_Laundry_Backend.Extensions; using SWD_Laundry_Backend.Repository.Infrastructure; @@ -49,8 +50,16 @@ public static void Main(string[] args) x => x.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName) ); }); - - + builder.Services.AddIdentity(options => + { + options.SignIn.RequireConfirmedAccount = false; + options.Password.RequireDigit = true; + options.Password.RequiredLength = 6; + options.Password.RequireNonAlphanumeric = true; + options.Password.RequireUppercase = true; + }) + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); builder.Services.AddAutoMapperServices(); builder.Services.AddRouting(options => { From 102d2b4b90a7762c4483d5f78ae0cb6e828429e7 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 2 Oct 2023 02:47:10 +0700 Subject: [PATCH 31/53] Identity Service --- .../Entity/IdentityModels/IdentityRole.cs | 1 + .../IBaseIdentityService.cs | 15 ++++ .../Interface/IIdentityService.cs | 7 ++ .../Models/IdentityResultExtensions.cs | 12 +++ src/SWD-Laundry-Backend.Core/Models/Result.cs | 23 +++++ .../Services/IdentityService.cs | 83 +++++++++++++++++++ 6 files changed, 141 insertions(+) create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IBaseIdentityService.cs create mode 100644 src/SWD-Laundry-Backend.Contract.Service/Interface/IIdentityService.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/IdentityResultExtensions.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/Result.cs create mode 100644 src/SWD-Laundry-Backend.Service/Services/IdentityService.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs index 4070187..91a5552 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/IdentityModels/IdentityRole.cs @@ -3,4 +3,5 @@ namespace SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; public class ApplicationRole : IdentityRole { + } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IBaseIdentityService.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IBaseIdentityService.cs new file mode 100644 index 0000000..7939455 --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IBaseIdentityService.cs @@ -0,0 +1,15 @@ +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; +public interface IBaseIdentityService +{ + Task GetUserNameAsync(string userId); + + Task IsInRoleAsync(string userId, string role); + + Task AuthorizeAsync(string userId, string policyName); + + Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password); + + Task DeleteUserAsync(string userId); +} diff --git a/src/SWD-Laundry-Backend.Contract.Service/Interface/IIdentityService.cs b/src/SWD-Laundry-Backend.Contract.Service/Interface/IIdentityService.cs new file mode 100644 index 0000000..9888dce --- /dev/null +++ b/src/SWD-Laundry-Backend.Contract.Service/Interface/IIdentityService.cs @@ -0,0 +1,7 @@ +using SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; + +namespace SWD_Laundry_Backend.Contract.Service.Interface; +public interface IIdentityService : IBaseIdentityService +{ + +} diff --git a/src/SWD-Laundry-Backend.Core/Models/IdentityResultExtensions.cs b/src/SWD-Laundry-Backend.Core/Models/IdentityResultExtensions.cs new file mode 100644 index 0000000..c76420d --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/IdentityResultExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Identity; + +namespace SWD_Laundry_Backend.Core.Models; +public static class IdentityResultExtensions +{ + public static Result ToApplicationResult(this IdentityResult result) + { + return result.Succeeded + ? Result.Success() + : Result.Failure(result.Errors.Select(e => e.Description)); + } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/Result.cs b/src/SWD-Laundry-Backend.Core/Models/Result.cs new file mode 100644 index 0000000..e694460 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/Result.cs @@ -0,0 +1,23 @@ +namespace SWD_Laundry_Backend.Core.Models; +public class Result +{ + internal Result(bool succeeded, IEnumerable errors) + { + Succeeded = succeeded; + Errors = errors.ToArray(); + } + + public bool Succeeded { get; set; } + + public string[] Errors { get; set; } + + public static Result Success() + { + return new Result(true, Array.Empty()); + } + + public static Result Failure(IEnumerable errors) + { + return new Result(false, errors); + } +} diff --git a/src/SWD-Laundry-Backend.Service/Services/IdentityService.cs b/src/SWD-Laundry-Backend.Service/Services/IdentityService.cs new file mode 100644 index 0000000..c62f2f8 --- /dev/null +++ b/src/SWD-Laundry-Backend.Service/Services/IdentityService.cs @@ -0,0 +1,83 @@ +using Invedia.DI.Attributes; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels; +using SWD_Laundry_Backend.Contract.Service.Interface; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Service.Services; +[TransientDependency(ServiceType = typeof(IIdentityService))] +public class IdentityService : Base_Service.Service, IIdentityService +{ + private readonly UserManager _userManager; + private readonly IUserClaimsPrincipalFactory _userClaimsPrincipalFactory; + private readonly IAuthorizationService _authorizationService; + + public IdentityService( + UserManager userManager, + IUserClaimsPrincipalFactory userClaimsPrincipalFactory, + IAuthorizationService authorizationService) + { + _userManager = userManager; + _userClaimsPrincipalFactory = userClaimsPrincipalFactory; + _authorizationService = authorizationService; + } + + public async Task GetUserNameAsync(string userId) + { + var user = await _userManager.Users.FirstAsync(u => u.Id == userId); + + return user.UserName; + } + + public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password) + { + var user = new ApplicationUser + { + UserName = userName, + Email = userName, + }; + + var result = await _userManager.CreateAsync(user, password); + + return (result.ToApplicationResult(), user.Id); + } + + public async Task IsInRoleAsync(string userId, string role) + { + var user = _userManager.Users.SingleOrDefault(u => u.Id == userId); + + return user != null && await _userManager.IsInRoleAsync(user, role); + } + + public async Task AuthorizeAsync(string userId, string policyName) + { + var user = _userManager.Users.SingleOrDefault(u => u.Id == userId); + + if (user == null) + { + return false; + } + + var principal = await _userClaimsPrincipalFactory.CreateAsync(user); + + var result = await _authorizationService.AuthorizeAsync(principal, policyName); + + return result.Succeeded; + } + + public async Task DeleteUserAsync(string userId) + { + var user = _userManager.Users.SingleOrDefault(u => u.Id == userId); + + return user != null ? await DeleteUserAsync(user) : Result.Success(); + } + + public async Task DeleteUserAsync(ApplicationUser user) + { + var result = await _userManager.DeleteAsync(user); + + return result.ToApplicationResult(); + } +} From 40c6260e55b5535e7f2e5fc458b6fb98e2f80b20 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:05:43 +0700 Subject: [PATCH 32/53] Update Building Controller --- .../Base Interface/IBaseRepository.cs | 2 + .../Base Service Interface/IDeleteAble.cs | 2 +- .../Base Service Interface/IGetAble.cs | 2 +- .../Base Service Interface/IUpdateAble.cs | 2 +- .../Base/BaseRepository.cs | 51 +++++++++- .../Services/BuildingService.cs | 24 +++-- .../Controllers/BuildingController.cs | 99 ++++++++++++++++++- 7 files changed, 165 insertions(+), 17 deletions(-) diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs index 85f4bfd..a8b7d1f 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Base Interface/IBaseRepository.cs @@ -7,6 +7,8 @@ namespace SWD_Laundry_Backend.Contract.Repository.Base_Interface; Task GetSingleAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes); Task> GetAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes); Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update, CancellationToken cancellationToken = default); + Task UpdateAsync(T t, CancellationToken cancellationToken = default); + Task DeleteAsync(Expression> filter, CancellationToken cancellationToken = default); Task AddAsync(T entity, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs index e2d417a..89764e0 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IDeleteAble.cs @@ -2,5 +2,5 @@ namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; public interface IDeleteAble where TKey : class { - Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); + Task DeleteAsync(TKey id, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs index eecd1a2..fe6870a 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IGetAble.cs @@ -3,5 +3,5 @@ namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; public interface IGetAble where T : class { Task> GetAllAsync(CancellationToken cancellationToken = default); - Task GetByIdAsync(TKey id, CancellationToken cancellationToken = default); + Task GetByIdAsync(TKey id, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs index 458325b..28aa350 100644 --- a/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs +++ b/src/SWD-Laundry-Backend.Contract.Service/Base Service Interface/IUpdateAble.cs @@ -1,5 +1,5 @@ namespace SWD_Laundry_Backend.Contract.Service.Base_Service_Interface; public interface IUpdateAble where T : class, new() { - Task UpdateAsync(Tkey id, T model, CancellationToken cancellationToken = default); + Task UpdateAsync(Tkey id, T model, CancellationToken cancellationToken = default); } diff --git a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs index b75a3b9..9978db0 100644 --- a/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs +++ b/src/SWD-Laundry-Backend.Repository/Base/BaseRepository.cs @@ -1,8 +1,10 @@ using System.Linq.Expressions; +using AngleSharp.Dom; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using SWD_Laundry_Backend.Contract.Repository.Base_Interface; using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Core.Utils; namespace SWD_Laundry_Backend.Repository.Base { @@ -34,6 +36,8 @@ protected BaseRepository(DbContext dbContext) public virtual async Task AddAsync(T entity, CancellationToken cancellationToken = default) { var e = await DbSet.AddAsync(entity, cancellationToken); + DbSet.Entry(e.Entity).State = EntityState.Added; + _dbContext.SaveChanges(); return e.Entity; } @@ -49,7 +53,7 @@ public virtual async Task> GetAsync(Expression>? fil return await Task.Run(() => { var query = DbSet.AsNoTracking(); - if(filter != null) + if (filter != null) { query = query.Where(filter); } @@ -64,7 +68,7 @@ public virtual async Task> GetAsync(Expression>? fil public virtual async Task GetSingleAsync(Expression>? filter = null, CancellationToken cancellationToken = default, params Expression>[]? includes) { var query = DbSet.AsNoTracking(); - if(filter != null) + if (filter != null) { query = query.Where(filter); } @@ -75,10 +79,51 @@ public virtual async Task> GetAsync(Expression>? fil return await query.FirstOrDefaultAsync(cancellationToken); } - public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update, CancellationToken cancellationToken = default) + /// + /// Update entity with specific properties + /// + /// Entity filter + /// Lamda select per properties + /// + /// + + public virtual async Task UpdateAsync(Expression> filter, Expression, SetPropertyCalls>> update, CancellationToken cancellationToken = default) { int i = await DbSet.Where(filter).ExecuteUpdateAsync(update, cancellationToken); return i; } + protected void TryAttach(T entity) + { + try + { + if (_dbContext.Entry(entity).State == EntityState.Detached) + { + DbSet.Attach(entity); + } + + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + /// + /// Update entity with all properties + /// Change entity.Id property to null if you want to ignore that property + /// + /// + /// + /// Affected rows + + public Task UpdateAsync(T t, CancellationToken cancellationToken = default) + { + TryAttach(t); + t.LastUpdatedTime = ObjHelper.ReplaceNullOrDefault(t.LastUpdatedTime, DateTimeOffset.UtcNow); + _dbContext.Entry(t).State = EntityState.Modified; + return _dbContext.SaveChangesAsync(cancellationToken); + } + + } } diff --git a/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs b/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs index ae53b51..31856a6 100644 --- a/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs +++ b/src/SWD-Laundry-Backend.Service/Services/BuildingService.cs @@ -20,14 +20,16 @@ public BuildingService (IBuildingRepository buildingRepository, IMapper mapper) _mapper = mapper; } - public Task CreateAsync(BuildingModel model, CancellationToken cancellationToken = default) + public async Task CreateAsync(BuildingModel model, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + var id = await _buildingRepository.AddAsync(_mapper.Map(model), cancellationToken); + return id.Id; } - public Task DeleteAsync(string id, CancellationToken cancellationToken = default) + public async Task DeleteAsync(string id, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + int i = await _buildingRepository.DeleteAsync(x => x.Id == id, cancellationToken: cancellationToken); + return i; } public async Task> GetAllAsync(CancellationToken cancellationToken = default) @@ -36,13 +38,19 @@ public async Task> GetAllAsync(CancellationToken cancellat return await buildings.ToListAsync(cancellationToken: cancellationToken); } - public Task GetByIdAsync(string id, CancellationToken cancellationToken = default) + public async Task GetByIdAsync(string id, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + var building = await _buildingRepository.GetSingleAsync(x => x.Id == id, cancellationToken: cancellationToken); + return building; } - public Task UpdateAsync(string id, BuildingModel model, CancellationToken cancellationToken = default) + public async Task UpdateAsync(string id, BuildingModel model, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + int i = await _buildingRepository.UpdateAsync(x => x.Id == id, + x => x.SetProperty(x => x.Name, y => model.Name ?? y.Name) + .SetProperty(x => x.Address, y => model.Address ?? y.Address) + .SetProperty(x => x.Description, y => model.Description ?? y.Description), + cancellationToken: cancellationToken); + return i; } } diff --git a/src/SWD-Laundry-Backend/Controllers/BuildingController.cs b/src/SWD-Laundry-Backend/Controllers/BuildingController.cs index 4abf2f3..a1b3184 100644 --- a/src/SWD-Laundry-Backend/Controllers/BuildingController.cs +++ b/src/SWD-Laundry-Backend/Controllers/BuildingController.cs @@ -16,12 +16,105 @@ public BuildingController(IBuidingService buildingService) [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesDefaultResponseType] public async Task GetAll() { - var result = await _buildingService.GetAllAsync(); - return Ok(new BaseResponseModel?>(StatusCodes.Status200OK, data: result)); + try + { + var result = await _buildingService.GetAllAsync(); + return Ok(new BaseResponseModel?>(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + + } + + [HttpGet("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task GetById(string id) + { + try + { + var result = await _buildingService.GetByIdAsync(id); + if (result == null) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Create(BuildingModel model) + { + try + { + var result = await _buildingService.CreateAsync(model); + return Ok(new BaseResponseModel(StatusCodes.Status201Created, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + + } + + [HttpPut("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Update(string id, BuildingModel model) + { + try + { + var result = await _buildingService.UpdateAsync(id, model); + if(result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } + + } + + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesDefaultResponseType] + public async Task Delete(string id) + { + try + { + var result = await _buildingService.DeleteAsync(id); + if (result == 0) + { + return NotFound(new BaseResponseModel(StatusCodes.Status404NotFound, "Not Found")); + } + return Ok(new BaseResponseModel(StatusCodes.Status200OK, data: result)); + } + catch (Exception e) + { + return BadRequest(new BaseResponseModel(StatusCodes.Status500InternalServerError, e.Message)); + } } } From b25833ff313e9a5900d8fdbcb7b5bb09f00d8ea3 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:26:58 +0700 Subject: [PATCH 33/53] Create ViewModel for Core Project --- .../Entity/Customer.cs | 26 +- .../Entity/Staff.cs | 6 +- .../Entity/Staff_Trip.cs | 2 +- .../Entity/Transaction.cs | 3 - .../Enum/AllowedTransactionType.cs | 8 + .../Enum/DeliveryStatus.cs | 13 + .../Enum/LaundryStatus.cs | 14 + .../Enum/OrderStatus.cs | 8 + .../Enum/OrderType.cs | 6 + .../Enum/PaymentType.cs | 8 + .../Enum/TimeFrame.cs | 13 + src/SWD-Laundry-Backend.Core/Enum/TripType.cs | 7 + .../Models/LaundryStoreModel.cs | 16 + .../Models/OrderHistoryModel.cs | 13 + .../Models/OrderModel.cs | 20 + .../Models/StaffTripModel.cs | 13 + .../Models/TimeScheduleModel.cs | 11 + .../Models/TransactionModel.cs | 16 + .../Models/WalletModel.cs | 11 + src/SWD-Laundry-Backend.Core/PaymentModel.cs | 10 + .../20231002072614_UpdateDatbase7.Designer.cs | 863 ++++++++++++++++++ .../20231002072614_UpdateDatbase7.cs | 51 ++ .../Migrations/AppDbContextModelSnapshot.cs | 9 - .../appsettings.Development.json | 2 +- 24 files changed, 1107 insertions(+), 42 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/DeliveryStatus.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/LaundryStatus.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/OrderType.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/TimeFrame.cs create mode 100644 src/SWD-Laundry-Backend.Core/Enum/TripType.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/LaundryStoreModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/OrderHistoryModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/OrderModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/TimeScheduleModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/TransactionModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/Models/WalletModel.cs create mode 100644 src/SWD-Laundry-Backend.Core/PaymentModel.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs create mode 100644 src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs index 346b92c..317f843 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Customer.cs @@ -28,31 +28,7 @@ public class Customer : BaseEntity #region Special Attribute - //private string _email; - - //private string _phone; - - //public string Email - //{ - // get { return _email; } - // set - // { - // _email = new Validate().IsValidEmail(value) - // ? value - // : throw new ArgumentException("Invalid email."); - // } - //} - - //public string Phone - //{ - // get { return _phone; } - // set - // { - // _phone = new Validate().IsValidPhone(value) - // ? value - // : throw new ArgumentException("Invalid phone (must be 9-10 numbers and start with 09 or 01)."); - // } - //} + #endregion Special Attribute } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs index 25d243d..8c7fea3 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff.cs @@ -8,9 +8,9 @@ public class Staff : BaseEntity { - public DateTime Dob { get; set; } - public string Address { get; set; } - public double Salary { get; set; } + //public DateTime Dob { get; set; } + //public string Address { get; set; } + //public double Salary { get; set; } #region Relationship diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs index cd2bd94..d58afc1 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Staff_Trip.cs @@ -1,5 +1,5 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Contract.Repository.Entity; + namespace SWD_Laundry_Backend.Contract.Repository.Entity; #nullable disable diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs index 1afc784..ab13413 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Entity/Transaction.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations.Schema; -using SWD_Laundry_Backend.Contract.Repository.Entity; using SWD_Laundry_Backend.Contract.Repository.Enum; namespace SWD_Laundry_Backend.Contract.Repository.Entity; @@ -25,7 +24,5 @@ public class Transaction : BaseEntity public AllowedTransactionType TransactionType { get; set; } - //public OrderStatus Status { get; set; } - #endregion Special Attribute } \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs b/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs new file mode 100644 index 0000000..4d2e176 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/AllowedTransactionType.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Core.Enum; +public enum AllowedTransactionType +{ + Deposit = 1, + Withdraw = 2, + Debt = 3, + Paid = 4 +} diff --git a/src/SWD-Laundry-Backend.Core/Enum/DeliveryStatus.cs b/src/SWD-Laundry-Backend.Core/Enum/DeliveryStatus.cs new file mode 100644 index 0000000..7c814d9 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/DeliveryStatus.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Core.Enum; +public enum DeliveryStatus +{ + Pending = 0, + Delivering = 1, + Delivered = 2, +} diff --git a/src/SWD-Laundry-Backend.Core/Enum/LaundryStatus.cs b/src/SWD-Laundry-Backend.Core/Enum/LaundryStatus.cs new file mode 100644 index 0000000..8113a81 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/LaundryStatus.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Core.Enum; + +public enum LaundryStatus +{ + Pending = 0, + Cleaning = 1, + Finished = 2, +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs b/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs new file mode 100644 index 0000000..db7cc71 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/OrderStatus.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Core.Enum; +public enum OrderStatus +{ + Preparing = 1, + Processing = 2, + Completed = 3, + Cancelled = 4 +} diff --git a/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs b/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs new file mode 100644 index 0000000..c95ec26 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/OrderType.cs @@ -0,0 +1,6 @@ +namespace SWD_Laundry_Backend.Core.Enum; +public enum OrderType +{ + OneWay = 1, + TwoWay = 2 +} diff --git a/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs b/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs new file mode 100644 index 0000000..478b06d --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/PaymentType.cs @@ -0,0 +1,8 @@ +namespace SWD_Laundry_Backend.Core.Enum; +public enum PaymentType +{ + Cash = 1, + CreditCard = 2, + DebitCard = 3, + EWallet = 4 +} diff --git a/src/SWD-Laundry-Backend.Core/Enum/TimeFrame.cs b/src/SWD-Laundry-Backend.Core/Enum/TimeFrame.cs new file mode 100644 index 0000000..b15a830 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/TimeFrame.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Core.Enum; +public enum TimeFrame +{ + Morning = 0, // 7h - 12h + Afternoon= 1, // 13h - 18h + Night = 2, // 19h - 24h +} diff --git a/src/SWD-Laundry-Backend.Core/Enum/TripType.cs b/src/SWD-Laundry-Backend.Core/Enum/TripType.cs new file mode 100644 index 0000000..b5075df --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Enum/TripType.cs @@ -0,0 +1,7 @@ +namespace SWD_Laundry_Backend.Core.Enum; + +public enum TripType +{ + Collect_From_Customer = 0, + Delivery_To_Customer = 1, +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/LaundryStoreModel.cs b/src/SWD-Laundry-Backend.Core/Models/LaundryStoreModel.cs new file mode 100644 index 0000000..d4e22d7 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/LaundryStoreModel.cs @@ -0,0 +1,16 @@ +#nullable disable + +namespace SWD_Laundry_Backend.Core.Models; + +public class LaundryStoreModel +{ + public string StoreName { get; set; } + public string Address { get; set; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public bool Status { get; set; } + + //public string Password { get; set; } + //public string Email { get; set; } + //public string PhoneNumber { get; set; } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/OrderHistoryModel.cs b/src/SWD-Laundry-Backend.Core/Models/OrderHistoryModel.cs new file mode 100644 index 0000000..7af378e --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/OrderHistoryModel.cs @@ -0,0 +1,13 @@ +using SWD_Laundry_Backend.Core.Enum; + +namespace SWD_Laundry_Backend.Core.Models; + +public class OrderHistoryModel +{ + public string? Title { get; set; } + public string? Message { get; set; } + + public OrderStatus OrderStatus { get; set; } + public DeliveryStatus DeliveryStatus { get; set; } + public LaundryStatus LaundryStatus { get; set; } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/OrderModel.cs b/src/SWD-Laundry-Backend.Core/Models/OrderModel.cs new file mode 100644 index 0000000..871a80d --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/OrderModel.cs @@ -0,0 +1,20 @@ +using SWD_Laundry_Backend.Core.Enum; + +namespace SWD_Laundry_Backend.Core.Models; + +public class OrderModel +{ + public DateTime OrderDate { get; set; } + public TimeFrame DeliveryTimeFrame { get; set; } + public DateTime ExpectedFinishDate { get; set; } + public string? Address { get; set; } + public short Amount { get; set; } + public double TotalPrice { get; set; } + + public string? CustomerName { get; set; } + public string? StaffName { get; set; } + public string? LaundryStoreName { get; set; } + + public int OrderType { get; set; } + public int PaymentType { get; set; } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs b/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs new file mode 100644 index 0000000..4dffb42 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/StaffTripModel.cs @@ -0,0 +1,13 @@ +using SWD_Laundry_Backend.Core.Enum; + +namespace SWD_Laundry_Backend.Core.Models; + +public class StaffTripModel +{ + public int TripCollect { get; set; } = 0; + + public BuildingModel? Building { get; set; } // Name of the associated building + public string? StaffName { get; set; } // Name of the associated staff + public TimeScheduleModel? TimeSchedule { get; set; } // Name of the associated time schedule + public TripType TripType { get; set; } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/TimeScheduleModel.cs b/src/SWD-Laundry-Backend.Core/Models/TimeScheduleModel.cs new file mode 100644 index 0000000..79dea6e --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/TimeScheduleModel.cs @@ -0,0 +1,11 @@ +using SWD_Laundry_Backend.Core.Enum; + +namespace SWD_Laundry_Backend.Core.Models; + +public class TimeScheduleModel +{ + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public DayOfWeek DayOfWeek { get; set; } + public TimeFrame TimeFrame { get; set; } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Core/Models/TransactionModel.cs b/src/SWD-Laundry-Backend.Core/Models/TransactionModel.cs new file mode 100644 index 0000000..e1a310d --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/TransactionModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SWD_Laundry_Backend.Core.Enum; + +namespace SWD_Laundry_Backend.Core.Models; +public class TransactionModel +{ + public string? PaymentMethod { get; set; } + public int Amount { get; set; } + public string? Description { get; set; } + public WalletModel? Wallet { get; set; } // Name or identifier of the associated wallet + public AllowedTransactionType TransactionType { get; set; } +} diff --git a/src/SWD-Laundry-Backend.Core/Models/WalletModel.cs b/src/SWD-Laundry-Backend.Core/Models/WalletModel.cs new file mode 100644 index 0000000..028bcc5 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/Models/WalletModel.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SWD_Laundry_Backend.Core.Models; +public class WalletModel +{ + public double Balance { get; set; } +} diff --git a/src/SWD-Laundry-Backend.Core/PaymentModel.cs b/src/SWD-Laundry-Backend.Core/PaymentModel.cs new file mode 100644 index 0000000..f4e87e8 --- /dev/null +++ b/src/SWD-Laundry-Backend.Core/PaymentModel.cs @@ -0,0 +1,10 @@ +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Core; + +public class PaymentModel +{ + public double Price { get; set; } + + public OrderModel OrderModel { get; set; } +} \ No newline at end of file diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs new file mode 100644 index 0000000..bac6672 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.Designer.cs @@ -0,0 +1,863 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SWD_Laundry_Backend.Repository.Infrastructure; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20231002072614_UpdateDatbase7")] + partial class UpdateDatbase7 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Buildings"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.HasIndex("BuildingID"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + 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") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.HasIndex("WalletID") + .IsUnique() + .HasFilter("[WalletID] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("LaundryStores"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Amount") + .HasColumnType("smallint"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("CustomerID") + .HasColumnType("nvarchar(450)"); + + b.Property("DeliveryTimeFrame") + .HasColumnType("int"); + + b.Property("ExpectedFinishDate") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStoreID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderDate") + .HasColumnType("datetime2"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("PaymentType") + .HasColumnType("int"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TotalPrice") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("CustomerID"); + + b.HasIndex("LaundryStoreID"); + + b.HasIndex("StaffID"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DeliveryStatus") + .HasColumnType("int"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LaundryStatus") + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("OrderID") + .HasColumnType("nvarchar(450)"); + + b.Property("OrderStatus") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("OrderID"); + + b.ToTable("OrderHistories"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("OrderId") + .HasColumnType("nvarchar(450)"); + + b.Property("Price") + .HasColumnType("float"); + + b.Property("TransactionId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("TransactionId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("BuildingID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StaffID") + .HasColumnType("nvarchar(450)"); + + b.Property("TimeScheduleID") + .HasColumnType("nvarchar(450)"); + + b.Property("TripCollect") + .HasColumnType("int"); + + b.Property("TripType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BuildingID"); + + b.HasIndex("StaffID"); + + b.HasIndex("TimeScheduleID"); + + b.ToTable("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("PaymentMethod") + .HasColumnType("nvarchar(max)"); + + b.Property("TransactionType") + .HasColumnType("int"); + + b.Property("WalletID") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("WalletID"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Balance") + .HasColumnType("float"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Wallets"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationUserID") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserID"); + + b.ToTable("Staffs"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("CreatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("DayOfWeek") + .HasColumnType("int"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetimeoffset"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TimeFrame") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TimeSchedules"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Customers") + .HasForeignKey("BuildingID"); + + b.Navigation("ApplicationUser"); + + b.Navigation("Building"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithOne("ApplicationUser") + .HasForeignKey("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", "Customer") + .WithMany("Order") + .HasForeignKey("CustomerID"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", "LaundryStore") + .WithMany("Orders") + .HasForeignKey("LaundryStoreID"); + + b.HasOne("Staff", "Staff") + .WithMany() + .HasForeignKey("StaffID"); + + b.Navigation("Customer"); + + b.Navigation("LaundryStore"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Order") + .WithMany("OrderHistories") + .HasForeignKey("OrderID"); + + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Order", "Orders") + .WithMany("Payments") + .HasForeignKey("OrderId"); + + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", "Transaction") + .WithMany("Payments") + .HasForeignKey("TransactionId"); + + b.Navigation("Orders"); + + b.Navigation("Transaction"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Building", "Building") + .WithMany("Staff_Trips") + .HasForeignKey("BuildingID"); + + b.HasOne("Staff", "Staff") + .WithMany("Staff_Trips") + .HasForeignKey("StaffID"); + + b.HasOne("TimeSchedule", "TimeSchedule") + .WithMany("Staff_Trip") + .HasForeignKey("TimeScheduleID"); + + b.Navigation("Building"); + + b.Navigation("Staff"); + + b.Navigation("TimeSchedule"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", "Wallet") + .WithMany("Transactions") + .HasForeignKey("WalletID"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("Staff", b => + { + b.HasOne("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", "ApplicationUser") + .WithMany() + .HasForeignKey("ApplicationUserID"); + + b.Navigation("ApplicationUser"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Building", b => + { + b.Navigation("Customers"); + + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => + { + b.Navigation("Order"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.LaundryStore", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => + { + b.Navigation("OrderHistories"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => + { + b.Navigation("ApplicationUser"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Staff", b => + { + b.Navigation("Staff_Trips"); + }); + + modelBuilder.Entity("TimeSchedule", b => + { + b.Navigation("Staff_Trip"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs b/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs new file mode 100644 index 0000000..c34a2c0 --- /dev/null +++ b/src/SWD-Laundry-Backend.Repository/Migrations/20231002072614_UpdateDatbase7.cs @@ -0,0 +1,51 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SWD_Laundry_Backend.Repository.Migrations +{ + /// + public partial class UpdateDatbase7 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Address", + table: "Staffs"); + + migrationBuilder.DropColumn( + name: "Dob", + table: "Staffs"); + + migrationBuilder.DropColumn( + name: "Salary", + table: "Staffs"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Address", + table: "Staffs", + type: "nvarchar(max)", + nullable: true); + + migrationBuilder.AddColumn( + name: "Dob", + table: "Staffs", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "Salary", + table: "Staffs", + type: "float", + nullable: false, + defaultValue: 0.0); + } + } +} diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs index 65579ab..04970bc 100644 --- a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs +++ b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs @@ -585,9 +585,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .HasColumnType("nvarchar(450)"); - b.Property("Address") - .HasColumnType("nvarchar(max)"); - b.Property("ApplicationUserID") .HasColumnType("nvarchar(450)"); @@ -597,18 +594,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedTime") .HasColumnType("datetimeoffset"); - b.Property("Dob") - .HasColumnType("datetime2"); - b.Property("LastUpdatedBy") .HasColumnType("nvarchar(max)"); b.Property("LastUpdatedTime") .HasColumnType("datetimeoffset"); - b.Property("Salary") - .HasColumnType("float"); - b.HasKey("Id"); b.HasIndex("ApplicationUserID"); diff --git a/src/SWD-Laundry-Backend/appsettings.Development.json b/src/SWD-Laundry-Backend/appsettings.Development.json index 76b9bb2..2277658 100644 --- a/src/SWD-Laundry-Backend/appsettings.Development.json +++ b/src/SWD-Laundry-Backend/appsettings.Development.json @@ -6,6 +6,6 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Laundry;user=sa;pwd=12345;Trusted_Connection=True;Trust Server Certificate=True" + "DefaultConnection": "Server = LEWIS; Database = LaundryProject; User Id = sa; Password = 123456; TrustServerCertificate = true" } } From b6dc0d6897658ef54321d6d091ecfe2006069069 Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:31:54 +0700 Subject: [PATCH 34/53] Add data for testing --- Script.sql | Bin 0 -> 38410 bytes .../Enum/OrderStatus.cs | 8 +++---- .../Enum/PaymentType.cs | 4 +--- .../Migrations/AppDbContextModelSnapshot.cs | 22 +++++++++--------- 4 files changed, 16 insertions(+), 18 deletions(-) create mode 100644 Script.sql diff --git a/Script.sql b/Script.sql new file mode 100644 index 0000000000000000000000000000000000000000..7b3091985ecd7867bed1c21cdae4c99d7bd27275 GIT binary patch literal 38410 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 literal 0 HcmV?d00001 diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs index 3a34b5d..3757731 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/OrderStatus.cs @@ -1,8 +1,8 @@ namespace SWD_Laundry_Backend.Contract.Repository.Enum; public enum OrderStatus { - Preparing = 1, - Processing = 2, - Completed = 3, - Cancelled = 4 + Preparing = 0, + Processing = 1, + Completed = 2, + Cancelled = 3 } diff --git a/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs b/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs index bb9a774..77d9e46 100644 --- a/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs +++ b/src/SWD-Laundry-Backend.Contract.Repository/Enum/PaymentType.cs @@ -2,7 +2,5 @@ public enum PaymentType { Cash = 1, - CreditCard = 2, - DebitCard = 3, - EWallet = 4 + Paypal = 2 } diff --git a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs index 04970bc..d5d09ce 100644 --- a/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs +++ b/src/SWD-Laundry-Backend.Repository/Migrations/AppDbContextModelSnapshot.cs @@ -183,7 +183,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Buildings"); + b.ToTable("Buildings", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Customer", b => @@ -215,7 +215,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("BuildingID"); - b.ToTable("Customers"); + b.ToTable("Customers", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.IdentityModels.ApplicationUser", b => @@ -332,7 +332,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.ToTable("LaundryStores"); + b.ToTable("LaundryStores", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Order", b => @@ -393,7 +393,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("StaffID"); - b.ToTable("Orders"); + b.ToTable("Orders", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.OrderHistory", b => @@ -435,7 +435,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("OrderID"); - b.ToTable("OrderHistories"); + b.ToTable("OrderHistories", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Payment", b => @@ -470,7 +470,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TransactionId"); - b.ToTable("Payments"); + b.ToTable("Payments", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Staff_Trip", b => @@ -513,7 +513,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TimeScheduleID"); - b.ToTable("Staff_Trips"); + b.ToTable("Staff_Trips", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Transaction", b => @@ -552,7 +552,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("WalletID"); - b.ToTable("Transaction"); + b.ToTable("Transaction", (string)null); }); modelBuilder.Entity("SWD_Laundry_Backend.Contract.Repository.Entity.Wallet", b => @@ -577,7 +577,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Wallets"); + b.ToTable("Wallets", (string)null); }); modelBuilder.Entity("Staff", b => @@ -604,7 +604,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ApplicationUserID"); - b.ToTable("Staffs"); + b.ToTable("Staffs", (string)null); }); modelBuilder.Entity("TimeSchedule", b => @@ -638,7 +638,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("TimeSchedules"); + b.ToTable("TimeSchedules", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => From b7ca32c2bddeef151314ec3a4b48e1357f96994d Mon Sep 17 00:00:00 2001 From: Nero Date: Mon, 2 Oct 2023 22:12:05 +0700 Subject: [PATCH 35/53] Update appsettings.Development.json --- src/SWD-Laundry-Backend/appsettings.Development.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SWD-Laundry-Backend/appsettings.Development.json b/src/SWD-Laundry-Backend/appsettings.Development.json index 2277658..76b9bb2 100644 --- a/src/SWD-Laundry-Backend/appsettings.Development.json +++ b/src/SWD-Laundry-Backend/appsettings.Development.json @@ -6,6 +6,6 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Server = LEWIS; Database = LaundryProject; User Id = sa; Password = 123456; TrustServerCertificate = true" + "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Laundry;user=sa;pwd=12345;Trusted_Connection=True;Trust Server Certificate=True" } } From fff160fe19c0543799f12fc895e45ffda4ea51f5 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:14:11 +0700 Subject: [PATCH 36/53] Update TrailingSlash --- src/SWD-Laundry-Backend/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SWD-Laundry-Backend/Program.cs b/src/SWD-Laundry-Backend/Program.cs index 4a5aa5c..e177f0d 100644 --- a/src/SWD-Laundry-Backend/Program.cs +++ b/src/SWD-Laundry-Backend/Program.cs @@ -63,7 +63,7 @@ public static void Main(string[] args) builder.Services.AddAutoMapperServices(); builder.Services.AddRouting(options => { - options.AppendTrailingSlash = true; + options.AppendTrailingSlash = false; } ); _ = builder.Services.AddSystemSetting(builder.Configuration.GetSection("SystemSetting").Get()); builder.Services.Configure(opt => opt.TokenLifespan = TimeSpan.FromMinutes(30)); From 9fa7ff8b62b1a7ae117d292f110ba70277817886 Mon Sep 17 00:00:00 2001 From: Nero <67089844+thanhplassma@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:17:41 +0700 Subject: [PATCH 37/53] Profile --- .../WalletMapperProfile.cs | 13 +++++++++++++ .../Extensions/AutoMapperExtension.cs | 1 + 2 files changed, 14 insertions(+) create mode 100644 src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs diff --git a/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs b/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs new file mode 100644 index 0000000..7960435 --- /dev/null +++ b/src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; +using SWD_Laundry_Backend.Contract.Repository.Entity; +using SWD_Laundry_Backend.Core.Models; + +namespace SWD_Laundry_Backend.Mapper; +public class WalletMapperProfile : Profile +{ + public WalletMapperProfile() + { + CreateMap().ReverseMap(); + } + +} diff --git a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs index 8f5a041..9d32fe4 100644 --- a/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs +++ b/src/SWD-Laundry-Backend/Extensions/AutoMapperExtension.cs @@ -10,6 +10,7 @@ public static IServiceCollection AddAutoMapperServices(this IServiceCollection s services.AddAutoMapper(cfg => { cfg.AddProfile(); + cfg.AddProfile(); }); return services; } From d324c46d924febb4da22a917c0543fd4a1b5d50d Mon Sep 17 00:00:00 2001 From: pytas0811 <105399564+pytas0811@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:51:14 +0700 Subject: [PATCH 38/53] Add Mapper Profile & Data Script --- Script.sql | Bin 38410 -> 2119048 bytes .../BuildingMapperProfile.cs | 11 +++++------ .../LaundryStoreMapperProfile.cs | 13 +++++++++++++ .../OrderHistoryMapperProfile.cs | 13 +++++++++++++ .../OrderMapperProfile.cs | 13 +++++++++++++ .../StaffTripMapperProfile.cs | 13 +++++++++++++ .../TimeScheduleMapperProfile.cs | 12 ++++++++++++ .../TransactionMapperProfile.cs | 13 +++++++++++++ .../WalletMapperProfile.cs | 13 +++++++++++++ .../Extensions/AutoMapperExtension.cs | 7 +++++++ 10 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 src/SWD-Laundry-Backend.Mapper/LaundryStoreMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/OrderHistoryMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/OrderMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/StaffTripMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/TimeScheduleMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/TransactionMapperProfile.cs create mode 100644 src/SWD-Laundry-Backend.Mapper/WalletMapperProfile.cs diff --git a/Script.sql b/Script.sql index 7b3091985ecd7867bed1c21cdae4c99d7bd27275..34ba8d3e76f438df7f856a8835b8538481e7319b 100644 GIT binary patch literal 2119048 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¶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�v?WIQvk45#iBZ)^y9-w^@cEU-D(`@dY?6q?zb~h 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

dWq8JrR+_Yk1$eF(Fw2pRJ$T$4&B@y8p7* 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%0DeW2 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 z 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

E`q58#fa4)*K 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