diff --git a/Server/Configurations/MapperInitializer.cs b/Server/Configurations/MapperInitializer.cs index 6385eaa..faec9dd 100644 --- a/Server/Configurations/MapperInitializer.cs +++ b/Server/Configurations/MapperInitializer.cs @@ -35,11 +35,12 @@ public class MapperInitializer : Profile CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); - CreateMap().ReverseMap(); + CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); @@ -66,8 +67,8 @@ public class MapperInitializer : Profile CreateMap().ReverseMap(); - // CreateMap().ReverseMap(); - // CreateMap().ReverseMap(); - // CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } \ No newline at end of file diff --git a/Server/Controllers/AddressController.cs b/Server/Controllers/AddressController.cs index 4085edd..b794092 100644 --- a/Server/Controllers/AddressController.cs +++ b/Server/Controllers/AddressController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/CityController.cs b/Server/Controllers/CityController.cs index 1255cad..8049176 100644 --- a/Server/Controllers/CityController.cs +++ b/Server/Controllers/CityController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/CompanyController.cs b/Server/Controllers/CompanyController.cs index 020d916..3cddc1d 100644 --- a/Server/Controllers/CompanyController.cs +++ b/Server/Controllers/CompanyController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/CountryController.cs b/Server/Controllers/CountryController.cs index f8b709a..f985d35 100644 --- a/Server/Controllers/CountryController.cs +++ b/Server/Controllers/CountryController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/ReviewController.cs b/Server/Controllers/ReviewController.cs index 7864c37..24cab2f 100644 --- a/Server/Controllers/ReviewController.cs +++ b/Server/Controllers/ReviewController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/RouteAddressController.cs b/Server/Controllers/RouteAddressController.cs index 004ae0c..75a2afb 100644 --- a/Server/Controllers/RouteAddressController.cs +++ b/Server/Controllers/RouteAddressController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/RouteController.cs b/Server/Controllers/RouteController.cs index b5e0329..93746e0 100644 --- a/Server/Controllers/RouteController.cs +++ b/Server/Controllers/RouteController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/StateController.cs b/Server/Controllers/StateController.cs index 2a5b0a5..bfa0be3 100644 --- a/Server/Controllers/StateController.cs +++ b/Server/Controllers/StateController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/StatisticsController.cs b/Server/Controllers/StatisticsController.cs new file mode 100644 index 0000000..cf7f88a --- /dev/null +++ b/Server/Controllers/StatisticsController.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using Server.Services; +using SharedModels.QueryParameters.Statistics; + +namespace Server.Controllers; + +[Route("api/[controller]")] +[ApiController] +public class StatisticsController : ControllerBase +{ + private readonly IStatisticsService _statisticsService; + + public StatisticsController(IStatisticsService statisticsService) + { + _statisticsService = statisticsService; + } + + [HttpGet("routes")] + public async Task GetPopularRoutes([FromQuery] int amount = 10) + { + return Ok(); + } + + [HttpGet("users")] + public async Task GetEngagedUsers([FromQuery] EngagedUserParameters parameters) + + { + var result = await _statisticsService.GetEngagedUsers(parameters); + + if (!result.IsSucceed) + { + return BadRequest(result.message); + } + + Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata)); + + return Ok(result.users); + } + + [HttpGet("companies")] + public async Task GetPopularCompanies([FromQuery] int amount = 10) + { + return Ok(); + } + + [HttpGet("stations")] + public async Task GetPopularStations([FromQuery] int amount = 10) + { + return Ok(); + } +} + diff --git a/Server/Controllers/TicketController.cs b/Server/Controllers/TicketController.cs index 08159f1..e40a04a 100644 --- a/Server/Controllers/TicketController.cs +++ b/Server/Controllers/TicketController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/VehicleController.cs b/Server/Controllers/VehicleController.cs index 3fa207f..01513bd 100644 --- a/Server/Controllers/VehicleController.cs +++ b/Server/Controllers/VehicleController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Controllers/VehicleEnrollmentController.cs b/Server/Controllers/VehicleEnrollmentController.cs index db05c3f..c622d82 100644 --- a/Server/Controllers/VehicleEnrollmentController.cs +++ b/Server/Controllers/VehicleEnrollmentController.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Server.Services; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Controllers; diff --git a/Server/Migrations/20221115135952_Change_Refresh_Token_Property_Names.Designer.cs b/Server/Migrations/20221115135952_Change_Refresh_Token_Property_Names.Designer.cs new file mode 100644 index 0000000..b759599 --- /dev/null +++ b/Server/Migrations/20221115135952_Change_Refresh_Token_Property_Names.Designer.cs @@ -0,0 +1,793 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Server.Data; + +#nullable disable + +namespace Server.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20221115135952_Change_Refresh_Token_Property_Names")] + partial class Change_Refresh_Token_Property_Names + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CityId") + .HasColumnType("integer"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CityId"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StateId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("StateId"); + + b.ToTable("Cities"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("Server.Models.Country", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Countries"); + }); + + modelBuilder.Entity("Server.Models.Review", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Rating") + .HasColumnType("integer"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("VehicleEnrollmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VehicleEnrollmentId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("Server.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Routes"); + }); + + modelBuilder.Entity("Server.Models.RouteAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddressId") + .HasColumnType("integer"); + + b.Property("CostToNextCity") + .HasColumnType("double precision"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("RouteId") + .HasColumnType("integer"); + + b.Property("TimeSpanToNextCity") + .HasColumnType("interval"); + + b.Property("WaitTimeSpan") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("RouteId"); + + b.ToTable("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CountryId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CountryId"); + + b.ToTable("States"); + }); + + modelBuilder.Entity("Server.Models.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IsReturned") + .HasColumnType("boolean"); + + b.Property("PurchaseDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("VehicleEnrollmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VehicleEnrollmentId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Server.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Capacity") + .HasColumnType("integer"); + + b.Property("CompanyId") + .HasColumnType("integer"); + + b.Property("HasBelts") + .HasColumnType("boolean"); + + b.Property("HasClimateControl") + .HasColumnType("boolean"); + + b.Property("HasOutlet") + .HasColumnType("boolean"); + + b.Property("HasStewardess") + .HasColumnType("boolean"); + + b.Property("HasTV") + .HasColumnType("boolean"); + + b.Property("HasWC") + .HasColumnType("boolean"); + + b.Property("HasWiFi") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Vehicles"); + }); + + modelBuilder.Entity("Server.Models.VehicleEnrollment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CancelationComment") + .HasColumnType("text"); + + b.Property("DelayTimeSpan") + .HasColumnType("interval"); + + b.Property("DepartureDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IsCanceled") + .HasColumnType("boolean"); + + b.Property("RouteId") + .HasColumnType("integer"); + + b.Property("VehicleId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("RouteId"); + + b.HasIndex("VehicleId"); + + b.ToTable("VehicleEnrollments"); + }); + + 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("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Server.Models.User", 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("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.HasOne("Server.Models.City", "City") + .WithMany("Addresses") + .HasForeignKey("CityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("City"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.HasOne("Server.Models.State", "State") + .WithMany("Cities") + .HasForeignKey("StateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("State"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.HasOne("Server.Models.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Server.Models.Review", b => + { + b.HasOne("Server.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment") + .WithMany() + .HasForeignKey("VehicleEnrollmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("VehicleEnrollment"); + }); + + modelBuilder.Entity("Server.Models.RouteAddress", b => + { + b.HasOne("Server.Models.Address", "Address") + .WithMany("RouteAddresses") + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.Route", "Route") + .WithMany("RouteAddresses") + .HasForeignKey("RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Address"); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.HasOne("Server.Models.Country", "Country") + .WithMany("States") + .HasForeignKey("CountryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Country"); + }); + + modelBuilder.Entity("Server.Models.Ticket", b => + { + b.HasOne("Server.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment") + .WithMany() + .HasForeignKey("VehicleEnrollmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("VehicleEnrollment"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 => + { + b1.Property("UserId") + .HasColumnType("text"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("CreationDateTime") + .HasColumnType("timestamp with time zone"); + + b1.Property("ExpiryDateTime") + .HasColumnType("timestamp with time zone"); + + b1.Property("Revoked") + .HasColumnType("timestamp with time zone"); + + b1.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b1.HasKey("UserId", "Id"); + + b1.ToTable("RefreshToken"); + + b1.WithOwner() + .HasForeignKey("UserId"); + }); + + b.Navigation("RefreshTokens"); + }); + + modelBuilder.Entity("Server.Models.Vehicle", b => + { + b.HasOne("Server.Models.Company", "Company") + .WithMany("Vehicles") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("Server.Models.VehicleEnrollment", b => + { + b.HasOne("Server.Models.Route", "Route") + .WithMany() + .HasForeignKey("RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.Navigation("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.Navigation("Addresses"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.Navigation("Vehicles"); + }); + + modelBuilder.Entity("Server.Models.Country", b => + { + b.Navigation("States"); + }); + + modelBuilder.Entity("Server.Models.Route", b => + { + b.Navigation("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.Navigation("Cities"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Migrations/20221115135952_Change_Refresh_Token_Property_Names.cs b/Server/Migrations/20221115135952_Change_Refresh_Token_Property_Names.cs new file mode 100644 index 0000000..52e7c71 --- /dev/null +++ b/Server/Migrations/20221115135952_Change_Refresh_Token_Property_Names.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Server.Migrations +{ + public partial class Change_Refresh_Token_Property_Names : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Expires", + table: "RefreshToken", + newName: "ExpiryDateTime"); + + migrationBuilder.RenameColumn( + name: "Created", + table: "RefreshToken", + newName: "CreationDateTime"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "ExpiryDateTime", + table: "RefreshToken", + newName: "Expires"); + + migrationBuilder.RenameColumn( + name: "CreationDateTime", + table: "RefreshToken", + newName: "Created"); + } + } +} diff --git a/Server/Migrations/20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review.Designer.cs b/Server/Migrations/20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review.Designer.cs new file mode 100644 index 0000000..df0861b --- /dev/null +++ b/Server/Migrations/20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review.Designer.cs @@ -0,0 +1,799 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Server.Data; + +#nullable disable + +namespace Server.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review")] + partial class Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CityId") + .HasColumnType("integer"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CityId"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StateId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("StateId"); + + b.ToTable("Cities"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("Server.Models.Country", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Countries"); + }); + + modelBuilder.Entity("Server.Models.Review", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("PostDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("Rating") + .HasColumnType("integer"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("VehicleEnrollmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VehicleEnrollmentId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("Server.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Routes"); + }); + + modelBuilder.Entity("Server.Models.RouteAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddressId") + .HasColumnType("integer"); + + b.Property("CostToNextCity") + .HasColumnType("double precision"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("RouteId") + .HasColumnType("integer"); + + b.Property("TimeSpanToNextCity") + .HasColumnType("interval"); + + b.Property("WaitTimeSpan") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("RouteId"); + + b.ToTable("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CountryId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CountryId"); + + b.ToTable("States"); + }); + + modelBuilder.Entity("Server.Models.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IsMissed") + .HasColumnType("boolean"); + + b.Property("IsReturned") + .HasColumnType("boolean"); + + b.Property("PurchaseDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("VehicleEnrollmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VehicleEnrollmentId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Server.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Capacity") + .HasColumnType("integer"); + + b.Property("CompanyId") + .HasColumnType("integer"); + + b.Property("HasBelts") + .HasColumnType("boolean"); + + b.Property("HasClimateControl") + .HasColumnType("boolean"); + + b.Property("HasOutlet") + .HasColumnType("boolean"); + + b.Property("HasStewardess") + .HasColumnType("boolean"); + + b.Property("HasTV") + .HasColumnType("boolean"); + + b.Property("HasWC") + .HasColumnType("boolean"); + + b.Property("HasWiFi") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Vehicles"); + }); + + modelBuilder.Entity("Server.Models.VehicleEnrollment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CancelationComment") + .HasColumnType("text"); + + b.Property("DelayTimeSpan") + .HasColumnType("interval"); + + b.Property("DepartureDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IsCanceled") + .HasColumnType("boolean"); + + b.Property("RouteId") + .HasColumnType("integer"); + + b.Property("VehicleId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("RouteId"); + + b.HasIndex("VehicleId"); + + b.ToTable("VehicleEnrollments"); + }); + + 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("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Server.Models.User", 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("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.HasOne("Server.Models.City", "City") + .WithMany("Addresses") + .HasForeignKey("CityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("City"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.HasOne("Server.Models.State", "State") + .WithMany("Cities") + .HasForeignKey("StateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("State"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.HasOne("Server.Models.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Server.Models.Review", b => + { + b.HasOne("Server.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment") + .WithMany() + .HasForeignKey("VehicleEnrollmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("VehicleEnrollment"); + }); + + modelBuilder.Entity("Server.Models.RouteAddress", b => + { + b.HasOne("Server.Models.Address", "Address") + .WithMany("RouteAddresses") + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.Route", "Route") + .WithMany("RouteAddresses") + .HasForeignKey("RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Address"); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.HasOne("Server.Models.Country", "Country") + .WithMany("States") + .HasForeignKey("CountryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Country"); + }); + + modelBuilder.Entity("Server.Models.Ticket", b => + { + b.HasOne("Server.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment") + .WithMany() + .HasForeignKey("VehicleEnrollmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("VehicleEnrollment"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 => + { + b1.Property("UserId") + .HasColumnType("text"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("CreationDateTime") + .HasColumnType("timestamp with time zone"); + + b1.Property("ExpiryDateTime") + .HasColumnType("timestamp with time zone"); + + b1.Property("Revoked") + .HasColumnType("timestamp with time zone"); + + b1.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b1.HasKey("UserId", "Id"); + + b1.ToTable("RefreshToken"); + + b1.WithOwner() + .HasForeignKey("UserId"); + }); + + b.Navigation("RefreshTokens"); + }); + + modelBuilder.Entity("Server.Models.Vehicle", b => + { + b.HasOne("Server.Models.Company", "Company") + .WithMany("Vehicles") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("Server.Models.VehicleEnrollment", b => + { + b.HasOne("Server.Models.Route", "Route") + .WithMany() + .HasForeignKey("RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.Navigation("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.Navigation("Addresses"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.Navigation("Vehicles"); + }); + + modelBuilder.Entity("Server.Models.Country", b => + { + b.Navigation("States"); + }); + + modelBuilder.Entity("Server.Models.Route", b => + { + b.Navigation("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.Navigation("Cities"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Migrations/20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review.cs b/Server/Migrations/20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review.cs new file mode 100644 index 0000000..3d267c9 --- /dev/null +++ b/Server/Migrations/20221122081645_Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Server.Migrations +{ + public partial class Add_IsMissed_to_Ticket_Add_PostDateTimeUtc_to_Review : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsMissed", + table: "Tickets", + type: "boolean", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "PostDateTimeUtc", + table: "Reviews", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsMissed", + table: "Tickets"); + + migrationBuilder.DropColumn( + name: "PostDateTimeUtc", + table: "Reviews"); + } + } +} diff --git a/Server/Migrations/20221122083642_Add_Tickets_and_Reviews_ILists_to_User.Designer.cs b/Server/Migrations/20221122083642_Add_Tickets_and_Reviews_ILists_to_User.Designer.cs new file mode 100644 index 0000000..0e99afd --- /dev/null +++ b/Server/Migrations/20221122083642_Add_Tickets_and_Reviews_ILists_to_User.Designer.cs @@ -0,0 +1,806 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Server.Data; + +#nullable disable + +namespace Server.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20221122083642_Add_Tickets_and_Reviews_ILists_to_User")] + partial class Add_Tickets_and_Reviews_ILists_to_User + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CityId") + .HasColumnType("integer"); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CityId"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StateId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("StateId"); + + b.ToTable("Cities"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("Companies"); + }); + + modelBuilder.Entity("Server.Models.Country", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Countries"); + }); + + modelBuilder.Entity("Server.Models.Review", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("PostDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("Rating") + .HasColumnType("integer"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("VehicleEnrollmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VehicleEnrollmentId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("Server.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Routes"); + }); + + modelBuilder.Entity("Server.Models.RouteAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddressId") + .HasColumnType("integer"); + + b.Property("CostToNextCity") + .HasColumnType("double precision"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("RouteId") + .HasColumnType("integer"); + + b.Property("TimeSpanToNextCity") + .HasColumnType("interval"); + + b.Property("WaitTimeSpan") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("RouteId"); + + b.ToTable("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CountryId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CountryId"); + + b.ToTable("States"); + }); + + modelBuilder.Entity("Server.Models.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IsMissed") + .HasColumnType("boolean"); + + b.Property("IsReturned") + .HasColumnType("boolean"); + + b.Property("PurchaseDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("VehicleEnrollmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("VehicleEnrollmentId"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Server.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Capacity") + .HasColumnType("integer"); + + b.Property("CompanyId") + .HasColumnType("integer"); + + b.Property("HasBelts") + .HasColumnType("boolean"); + + b.Property("HasClimateControl") + .HasColumnType("boolean"); + + b.Property("HasOutlet") + .HasColumnType("boolean"); + + b.Property("HasStewardess") + .HasColumnType("boolean"); + + b.Property("HasTV") + .HasColumnType("boolean"); + + b.Property("HasWC") + .HasColumnType("boolean"); + + b.Property("HasWiFi") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CompanyId"); + + b.ToTable("Vehicles"); + }); + + modelBuilder.Entity("Server.Models.VehicleEnrollment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CancelationComment") + .HasColumnType("text"); + + b.Property("DelayTimeSpan") + .HasColumnType("interval"); + + b.Property("DepartureDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("IsCanceled") + .HasColumnType("boolean"); + + b.Property("RouteId") + .HasColumnType("integer"); + + b.Property("VehicleId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("RouteId"); + + b.HasIndex("VehicleId"); + + b.ToTable("VehicleEnrollments"); + }); + + 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("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Server.Models.User", 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("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Server.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.HasOne("Server.Models.City", "City") + .WithMany("Addresses") + .HasForeignKey("CityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("City"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.HasOne("Server.Models.State", "State") + .WithMany("Cities") + .HasForeignKey("StateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("State"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.HasOne("Server.Models.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Server.Models.Review", b => + { + b.HasOne("Server.Models.User", "User") + .WithMany("Reviews") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment") + .WithMany() + .HasForeignKey("VehicleEnrollmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("VehicleEnrollment"); + }); + + modelBuilder.Entity("Server.Models.RouteAddress", b => + { + b.HasOne("Server.Models.Address", "Address") + .WithMany("RouteAddresses") + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.Route", "Route") + .WithMany("RouteAddresses") + .HasForeignKey("RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Address"); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.HasOne("Server.Models.Country", "Country") + .WithMany("States") + .HasForeignKey("CountryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Country"); + }); + + modelBuilder.Entity("Server.Models.Ticket", b => + { + b.HasOne("Server.Models.User", "User") + .WithMany("Tickets") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment") + .WithMany() + .HasForeignKey("VehicleEnrollmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("VehicleEnrollment"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 => + { + b1.Property("UserId") + .HasColumnType("text"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("CreationDateTime") + .HasColumnType("timestamp with time zone"); + + b1.Property("ExpiryDateTime") + .HasColumnType("timestamp with time zone"); + + b1.Property("Revoked") + .HasColumnType("timestamp with time zone"); + + b1.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b1.HasKey("UserId", "Id"); + + b1.ToTable("RefreshToken"); + + b1.WithOwner() + .HasForeignKey("UserId"); + }); + + b.Navigation("RefreshTokens"); + }); + + modelBuilder.Entity("Server.Models.Vehicle", b => + { + b.HasOne("Server.Models.Company", "Company") + .WithMany("Vehicles") + .HasForeignKey("CompanyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("Server.Models.VehicleEnrollment", b => + { + b.HasOne("Server.Models.Route", "Route") + .WithMany() + .HasForeignKey("RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Server.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Server.Models.Address", b => + { + b.Navigation("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.City", b => + { + b.Navigation("Addresses"); + }); + + modelBuilder.Entity("Server.Models.Company", b => + { + b.Navigation("Vehicles"); + }); + + modelBuilder.Entity("Server.Models.Country", b => + { + b.Navigation("States"); + }); + + modelBuilder.Entity("Server.Models.Route", b => + { + b.Navigation("RouteAddresses"); + }); + + modelBuilder.Entity("Server.Models.State", b => + { + b.Navigation("Cities"); + }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.Navigation("Reviews"); + + b.Navigation("Tickets"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Migrations/20221122083642_Add_Tickets_and_Reviews_ILists_to_User.cs b/Server/Migrations/20221122083642_Add_Tickets_and_Reviews_ILists_to_User.cs new file mode 100644 index 0000000..583ebd5 --- /dev/null +++ b/Server/Migrations/20221122083642_Add_Tickets_and_Reviews_ILists_to_User.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Server.Migrations +{ + public partial class Add_Tickets_and_Reviews_ILists_to_User : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Server/Migrations/ApplicationDbContextModelSnapshot.cs b/Server/Migrations/ApplicationDbContextModelSnapshot.cs index fc2d6fa..878f566 100644 --- a/Server/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Server/Migrations/ApplicationDbContextModelSnapshot.cs @@ -259,6 +259,9 @@ namespace Server.Migrations b.Property("Comment") .HasColumnType("text"); + b.Property("PostDateTimeUtc") + .HasColumnType("timestamp with time zone"); + b.Property("Rating") .HasColumnType("integer"); @@ -360,6 +363,9 @@ namespace Server.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + b.Property("IsMissed") + .HasColumnType("boolean"); + b.Property("IsReturned") .HasColumnType("boolean"); @@ -624,7 +630,7 @@ namespace Server.Migrations modelBuilder.Entity("Server.Models.Review", b => { b.HasOne("Server.Models.User", "User") - .WithMany() + .WithMany("Reviews") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -673,7 +679,7 @@ namespace Server.Migrations modelBuilder.Entity("Server.Models.Ticket", b => { b.HasOne("Server.Models.User", "User") - .WithMany() + .WithMany("Tickets") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -702,10 +708,10 @@ namespace Server.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); - b1.Property("Created") + b1.Property("CreationDateTime") .HasColumnType("timestamp with time zone"); - b1.Property("Expires") + b1.Property("ExpiryDateTime") .HasColumnType("timestamp with time zone"); b1.Property("Revoked") @@ -785,6 +791,13 @@ namespace Server.Migrations { b.Navigation("Cities"); }); + + modelBuilder.Entity("Server.Models.User", b => + { + b.Navigation("Reviews"); + + b.Navigation("Tickets"); + }); #pragma warning restore 612, 618 } } diff --git a/Server/Models/Review.cs b/Server/Models/Review.cs index 9b7490e..578d301 100644 --- a/Server/Models/Review.cs +++ b/Server/Models/Review.cs @@ -15,7 +15,8 @@ public class Review [ForeignKey("VehicleEnrollmentId")] public int VehicleEnrollmentId { get; set; } public VehicleEnrollment VehicleEnrollment { get; set; } = null!; - + + public DateTime PostDateTimeUtc { get; set; } = DateTime.UtcNow; public int Rating { get; set; } public string? Comment { get; set; } } \ No newline at end of file diff --git a/Server/Models/Ticket.cs b/Server/Models/Ticket.cs index e244a42..6c9099d 100644 --- a/Server/Models/Ticket.cs +++ b/Server/Models/Ticket.cs @@ -16,6 +16,7 @@ public class Ticket public int VehicleEnrollmentId { get; set; } public VehicleEnrollment VehicleEnrollment { get; set; } = null!; - public DateTime PurchaseDateTimeUtc { get; set; } + public DateTime PurchaseDateTimeUtc { get; set; } = DateTime.UtcNow; public bool IsReturned { get; set; } = false; + public bool IsMissed { get; set; } = false; } \ No newline at end of file diff --git a/Server/Models/User.cs b/Server/Models/User.cs index 425ed96..384e610 100644 --- a/Server/Models/User.cs +++ b/Server/Models/User.cs @@ -6,5 +6,7 @@ public class User : IdentityUser { public string? FirstName { get; set; } public string? LastName { get; set; } - public List RefreshTokens { get; set; } = null!; + public IList RefreshTokens { get; set; } = null!; + public virtual IList Tickets { get; set; } = null!; + public virtual IList Reviews { get; set; } = null!; } \ No newline at end of file diff --git a/Server/Program.cs b/Server/Program.cs index 48f9fad..9646808 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -11,6 +11,7 @@ using Server.Data; using Server.Helpers; using Server.Models; using Server.Services; +using SharedModels.DataTransferObjects; using Route = Server.Models.Route; var builder = WebApplication.CreateBuilder(args); @@ -103,6 +104,9 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); + + builder.Services.AddScoped, SortHelper>(); builder.Services.AddScoped, SortHelper>(); builder.Services.AddScoped, SortHelper>(); @@ -115,6 +119,8 @@ builder.Services.AddScoped, SortHelper, SortHelper>(); builder.Services.AddScoped, SortHelper>(); +builder.Services.AddScoped, DataShaper>(); +builder.Services.AddScoped, DataShaper>(); builder.Services.AddScoped, DataShaper>(); builder.Services.AddScoped, DataShaper>(); builder.Services.AddScoped, DataShaper>(); diff --git a/Server/Services/AddressManagementService.cs b/Server/Services/AddressManagementService.cs index 3ea8cbf..7974d1d 100644 --- a/Server/Services/AddressManagementService.cs +++ b/Server/Services/AddressManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/CityManagementService.cs b/Server/Services/CityManagementService.cs index ad475ee..6f0a7ea 100644 --- a/Server/Services/CityManagementService.cs +++ b/Server/Services/CityManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/CompanyManagementService.cs b/Server/Services/CompanyManagementService.cs index 7ae4fb7..644ade4 100644 --- a/Server/Services/CompanyManagementService.cs +++ b/Server/Services/CompanyManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/CountryManagementService.cs b/Server/Services/CountryManagementService.cs index d9b9e91..6942300 100644 --- a/Server/Services/CountryManagementService.cs +++ b/Server/Services/CountryManagementService.cs @@ -5,7 +5,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IAddressManagementService.cs b/Server/Services/IAddressManagementService.cs index f909bf5..f833407 100644 --- a/Server/Services/IAddressManagementService.cs +++ b/Server/Services/IAddressManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/ICityManagementService.cs b/Server/Services/ICityManagementService.cs index 4bb203f..db1d3c4 100644 --- a/Server/Services/ICityManagementService.cs +++ b/Server/Services/ICityManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/ICompanyManagementService.cs b/Server/Services/ICompanyManagementService.cs index cfcadcd..5d267a2 100644 --- a/Server/Services/ICompanyManagementService.cs +++ b/Server/Services/ICompanyManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/ICountryManagementService.cs b/Server/Services/ICountryManagementService.cs index 74741a1..90525a0 100644 --- a/Server/Services/ICountryManagementService.cs +++ b/Server/Services/ICountryManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IReviewManagementService.cs b/Server/Services/IReviewManagementService.cs index 7e181bb..ae53c71 100644 --- a/Server/Services/IReviewManagementService.cs +++ b/Server/Services/IReviewManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IRouteAddressManagementService.cs b/Server/Services/IRouteAddressManagementService.cs index 644a52d..b063b8e 100644 --- a/Server/Services/IRouteAddressManagementService.cs +++ b/Server/Services/IRouteAddressManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IRouteManagementService.cs b/Server/Services/IRouteManagementService.cs index 7227bad..6f26e54 100644 --- a/Server/Services/IRouteManagementService.cs +++ b/Server/Services/IRouteManagementService.cs @@ -1,5 +1,6 @@ using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; using Route = Server.Models.Route; namespace Server.Services; diff --git a/Server/Services/IStateManagementService.cs b/Server/Services/IStateManagementService.cs index 7daabbe..066beb5 100644 --- a/Server/Services/IStateManagementService.cs +++ b/Server/Services/IStateManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IStatisticsService.cs b/Server/Services/IStatisticsService.cs new file mode 100644 index 0000000..c3c0e51 --- /dev/null +++ b/Server/Services/IStatisticsService.cs @@ -0,0 +1,21 @@ +using System.Dynamic; +using Server.Models; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Statistics; + +namespace Server.Services; + +public interface IStatisticsService +{ + Task<(bool IsSucceed, string? message, IEnumerable route)> + GetPopularRoutes(int amount); + + Task<(bool IsSucceed, string? message, IEnumerable users, PagingMetadata pagingMetadata)> + GetEngagedUsers(EngagedUserParameters parameters); + + Task<(bool IsSucceed, string? message, IEnumerable companies)> + GetPopularCompanies(int amount); + + Task<(bool IsSucceed, string? message, IEnumerable stations)> + GetPopularStations(int amount); +} \ No newline at end of file diff --git a/Server/Services/ITicketManagementService.cs b/Server/Services/ITicketManagementService.cs index e298bb9..f0afa61 100644 --- a/Server/Services/ITicketManagementService.cs +++ b/Server/Services/ITicketManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IVehicleEnrollmentManagementService.cs b/Server/Services/IVehicleEnrollmentManagementService.cs index 70e014d..8afef39 100644 --- a/Server/Services/IVehicleEnrollmentManagementService.cs +++ b/Server/Services/IVehicleEnrollmentManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/IVehicleManagementService.cs b/Server/Services/IVehicleManagementService.cs index debbf9d..443772b 100644 --- a/Server/Services/IVehicleManagementService.cs +++ b/Server/Services/IVehicleManagementService.cs @@ -1,6 +1,7 @@ using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/ReviewManagementService.cs b/Server/Services/ReviewManagementService.cs index 6fb8d8d..2716390 100644 --- a/Server/Services/ReviewManagementService.cs +++ b/Server/Services/ReviewManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; @@ -41,9 +42,10 @@ public class ReviewManagementService : IReviewManagementService var dbReviews = _dbContext.Reviews .AsQueryable(); - FilterByReviewRating(ref dbReviews, parameters.Rating); + FilterByReviewRating(ref dbReviews, parameters.FromRating, parameters.ToRating); FilterByReviewComment(ref dbReviews, parameters.Comment); - + FilterByReviewUserId(ref dbReviews, parameters.UserId); + try { dbReviews = _reviewSortHelper.ApplySort(dbReviews, parameters.Sort); @@ -66,14 +68,15 @@ public class ReviewManagementService : IReviewManagementService return (true, "", reviewDtos, pagingMetadata); void FilterByReviewRating(ref IQueryable reviews, - int? rating) + int? fromRating, int? toRating) { - if (!reviews.Any() || rating == null) + if (!reviews.Any() || !fromRating.HasValue && !toRating.HasValue) { return; } - reviews = reviews.Where(r => r.Rating == rating); + reviews = reviews.Where(r => + r.Rating >= fromRating && r.Rating <= toRating); } void FilterByReviewComment(ref IQueryable reviews, @@ -88,6 +91,18 @@ public class ReviewManagementService : IReviewManagementService r.Comment != null && r.Comment.ToLower().Contains(comment.ToLower())); } + + void FilterByReviewUserId(ref IQueryable reviews, + string? userId) + { + if (!reviews.Any() || String.IsNullOrWhiteSpace(userId)) + { + return; + } + + reviews = reviews.Where(r => + r.UserId.Contains(userId.ToLower())); + } PagingMetadata ApplyPaging(ref IQueryable reviews, int pageNumber, int pageSize) diff --git a/Server/Services/RouteAddressManagementService.cs b/Server/Services/RouteAddressManagementService.cs index 5f3bd25..ec362f2 100644 --- a/Server/Services/RouteAddressManagementService.cs +++ b/Server/Services/RouteAddressManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/RouteManagementService.cs b/Server/Services/RouteManagementService.cs index 1fb7a71..b6e2f92 100644 --- a/Server/Services/RouteManagementService.cs +++ b/Server/Services/RouteManagementService.cs @@ -3,7 +3,8 @@ using Microsoft.EntityFrameworkCore; using Server.Data; using Server.Helpers; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; using Route = Server.Models.Route; namespace Server.Services; diff --git a/Server/Services/StateManagementService.cs b/Server/Services/StateManagementService.cs index 0409de0..c0bbcfb 100644 --- a/Server/Services/StateManagementService.cs +++ b/Server/Services/StateManagementService.cs @@ -5,7 +5,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/StatisticsService.cs b/Server/Services/StatisticsService.cs new file mode 100644 index 0000000..7765589 --- /dev/null +++ b/Server/Services/StatisticsService.cs @@ -0,0 +1,100 @@ +using System.Dynamic; +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Server.Data; +using Server.Helpers; +using Server.Models; +using SharedModels.DataTransferObjects; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Statistics; + +namespace Server.Services; + +public class StatisticsService : IStatisticsService +{ + private readonly ApplicationDbContext _dbContext; + private readonly IMapper _mapper; + private readonly IDataShaper _userDataShaper; + + public StatisticsService(ApplicationDbContext dbContext, IMapper mapper, + IDataShaper userDataShaper) + { + _dbContext = dbContext; + _mapper = mapper; + _userDataShaper = userDataShaper; + } + + // Popularity is measured in number of purchased tickets + public async Task<(bool IsSucceed, string? message, IEnumerable route)> + GetPopularRoutes(int amount) + { + throw new NotImplementedException(); + } + + // Engagement is measured in number of tickets bought in last 60 days + public async Task<(bool IsSucceed, string? message, IEnumerable users, PagingMetadata pagingMetadata)> + GetEngagedUsers(EngagedUserParameters parameters) + { + var fromDateUtc = DateTime.UtcNow - TimeSpan.FromDays(parameters.Days ?? parameters.DefaultDays); + + var resultObjectList = _dbContext.Users + .Include(u => u.Tickets) + .Select(u => new + { + User = u, + Tickets = u.Tickets.Where(t => t.PurchaseDateTimeUtc >= fromDateUtc) + }) + .OrderByDescending(o => o.User.Tickets.Count) + .Take(parameters.Amount); + + + var dbUsers = resultObjectList.Select(i => i.User); + var pagingMetadata = ApplyPaging(ref dbUsers, parameters.PageNumber, + parameters.PageSize); + + var userDtos = _mapper.ProjectTo(dbUsers).ToList(); + var shapedData = _userDataShaper + .ShapeData(userDtos, parameters.Fields ?? parameters.DefaultFields) + .ToList(); + + if (parameters.Fields != null && + parameters.Fields.ToLower().Contains("ticketCount".ToLower())) + { + var dbUsersList = await dbUsers.ToListAsync(); + for (int i = 0; i < dbUsersList.Count; i++) + { + var ticketCount = dbUsersList[i].Tickets.Count; + shapedData[i].TryAdd("TicketCount", ticketCount); + } + } + + return (true, null, shapedData, pagingMetadata); + } + + // Popularity is measured in number of purchased tickets & rating + public async Task<(bool IsSucceed, string? message, IEnumerable companies)> + GetPopularCompanies(int amount) + { + throw new NotImplementedException(); + } + + // Popularity is measured in number of routes using the station + public async Task<(bool IsSucceed, string? message, IEnumerable stations)> + GetPopularStations(int amount) + { + throw new NotImplementedException(); + } + + PagingMetadata ApplyPaging(ref IQueryable obj, + int pageNumber, int pageSize) + { + var metadata = new PagingMetadata(obj, + pageNumber, pageSize); + + obj = obj + .Skip((pageNumber - 1) * pageSize) + .Take(pageSize); + + return metadata; + } +} \ No newline at end of file diff --git a/Server/Services/TicketManagementService.cs b/Server/Services/TicketManagementService.cs index c48af5a..60c8c9e 100644 --- a/Server/Services/TicketManagementService.cs +++ b/Server/Services/TicketManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; @@ -41,11 +42,11 @@ public class TicketManagementService : ITicketManagementService var dbTickets = _dbContext.Tickets .AsQueryable(); - FilterByTicketPurchaseDateTime(ref dbTickets, - parameters.FromPurchaseDateTimeUtc, + FilterByTicketPurchaseDateTime(ref dbTickets, parameters.FromPurchaseDateTimeUtc, parameters.ToPurchaseDateTimeUtc); FilterByTicketReturnedState(ref dbTickets, parameters.IsReturned); - + FilterByTicketUserId(ref dbTickets, parameters.UserId); + try { dbTickets = _ticketSortHelper.ApplySort(dbTickets, parameters.Sort); @@ -91,6 +92,18 @@ public class TicketManagementService : ITicketManagementService tickets = tickets.Where(t => t.IsReturned == isReturned); } + void FilterByTicketUserId(ref IQueryable tickets, + string? userId) + { + if (!tickets.Any() || String.IsNullOrWhiteSpace(userId)) + { + return; + } + + tickets = tickets.Where(t => + t.UserId.ToLower().Contains(userId.ToLower())); + } + PagingMetadata ApplyPaging(ref IQueryable tickets, int pageNumber, int pageSize) { diff --git a/Server/Services/VehicleEnrollmentManagementService.cs b/Server/Services/VehicleEnrollmentManagementService.cs index 75e82ee..7205769 100644 --- a/Server/Services/VehicleEnrollmentManagementService.cs +++ b/Server/Services/VehicleEnrollmentManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/Services/VehicleManagementService.cs b/Server/Services/VehicleManagementService.cs index 93febb6..fb66b2e 100644 --- a/Server/Services/VehicleManagementService.cs +++ b/Server/Services/VehicleManagementService.cs @@ -4,7 +4,8 @@ using Server.Data; using Server.Helpers; using Server.Models; using SharedModels.DataTransferObjects; -using SharedModels.QueryStringParameters; +using SharedModels.QueryParameters; +using SharedModels.QueryParameters.Objects; namespace Server.Services; diff --git a/Server/appsettings.Development.json b/Server/appsettings.Development.json index cf2d2fa..8900a52 100644 --- a/Server/appsettings.Development.json +++ b/Server/appsettings.Development.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "host=localhost;database=auto.bus;user id=postgres;password=postgres;" + "DefaultConnection": "host=localhost;database=auto.bus;user id=postgres;password=postgres;Include Error Detail = true" }, "Jwt": { "Key": "Secret which will never be exposed", diff --git a/SharedModels/DataTransferObjects/AddressDto.cs b/SharedModels/DataTransferObjects/AddressDto.cs index 11a6faf..67d53f6 100644 --- a/SharedModels/DataTransferObjects/AddressDto.cs +++ b/SharedModels/DataTransferObjects/AddressDto.cs @@ -7,8 +7,6 @@ public class AddressDto : CreateAddressDto public int Id { get; set; } public InAddressCityDto City { get; set; } = null!; - - public virtual IList RouteAddresses { get; set; } = null!; } public class CreateAddressDto diff --git a/SharedModels/DataTransferObjects/ReviewDto.cs b/SharedModels/DataTransferObjects/ReviewDto.cs index f8b9a3e..2a71278 100644 --- a/SharedModels/DataTransferObjects/ReviewDto.cs +++ b/SharedModels/DataTransferObjects/ReviewDto.cs @@ -5,6 +5,9 @@ namespace SharedModels.DataTransferObjects; public class ReviewDto : CreateReviewDto { public int Id { get; set; } + + [DataType(DataType.DateTime)] + public DateTime PostDateTimeUtc { get; set; } } public class CreateReviewDto @@ -26,4 +29,7 @@ public class UpdateReviewDto : CreateReviewDto { [Required] public int Id { get; set; } + + [DataType(DataType.DateTime)] + public DateTime PostDateTimeUtc { get; set; } } \ No newline at end of file diff --git a/SharedModels/DataTransferObjects/RouteAddressDto.cs b/SharedModels/DataTransferObjects/RouteAddressDto.cs index 5a17060..94afdd3 100644 --- a/SharedModels/DataTransferObjects/RouteAddressDto.cs +++ b/SharedModels/DataTransferObjects/RouteAddressDto.cs @@ -37,12 +37,23 @@ public class UpdateRouteAddressDto : CreateRouteAddressDto public int Id { get; set; } } -public class InRouteRouteAddressDto +public class CreateRouteAddressWithAddressDto { - public int Id { get; set; } - public int AddressId { get; set; } + [Required] public int Order { get; set; } + + [Required] + [DataType(DataType.Duration)] public TimeSpan TimeSpanToNextCity { get; set; } + + [Required] + [DataType(DataType.Duration)] public TimeSpan WaitTimeSpan { get; set; } + + [Required] + [DataType(DataType.Currency)] public double CostToNextCity { get; set; } + + [Required] + public CreateAddressDto Address { get; set; } = null!; } \ No newline at end of file diff --git a/SharedModels/DataTransferObjects/RouteDto.cs b/SharedModels/DataTransferObjects/RouteDto.cs index 7663d0f..5d4e34a 100644 --- a/SharedModels/DataTransferObjects/RouteDto.cs +++ b/SharedModels/DataTransferObjects/RouteDto.cs @@ -5,8 +5,6 @@ namespace SharedModels.DataTransferObjects; public class RouteDto : CreateRouteDto { public int Id { get; set; } - - public virtual IList RouteAddresses { get; set; } = null!; } public class CreateRouteDto @@ -19,4 +17,11 @@ public class UpdateRouteDto : CreateRouteDto { [Required] public int Id { get; set; } +} + +public class CreateRouteWithAddressesDto : CreateRouteDto +{ + [Required] + [MinLength(2)] + public IList RouteAddresses { get; set; } = null!; } \ No newline at end of file diff --git a/SharedModels/DataTransferObjects/TicketDto.cs b/SharedModels/DataTransferObjects/TicketDto.cs index bd20620..db5056a 100644 --- a/SharedModels/DataTransferObjects/TicketDto.cs +++ b/SharedModels/DataTransferObjects/TicketDto.cs @@ -9,6 +9,7 @@ public class TicketDto : CreateTicketDto [DataType(DataType.DateTime)] public DateTime PurchaseDateTimeUtc { get; set; } public bool IsReturned { get; set; } = false; + public bool IsMissed { get; set; } = false; } public class CreateTicketDto @@ -31,4 +32,5 @@ public class UpdateTicketDto [DataType(DataType.DateTime)] public DateTime PurchaseDateTimeUtc { get; set; } public bool IsReturned { get; set; } = false; + public bool IsMissed { get; set; } = false; } \ No newline at end of file diff --git a/SharedModels/DataTransferObjects/UserDto.cs b/SharedModels/DataTransferObjects/UserDto.cs new file mode 100644 index 0000000..4e79e14 --- /dev/null +++ b/SharedModels/DataTransferObjects/UserDto.cs @@ -0,0 +1,63 @@ +using System.ComponentModel.DataAnnotations; + +namespace SharedModels.DataTransferObjects; + +public class UserDto : UpdateUserDto +{ + public virtual CompanyDto Company { get; set; } = null!; + + public virtual IList Tickets { get; set; } = null!; + public virtual IList Ratings { get; set; } = null!; +} + +public class CreateUserDto +{ + public string? FirstName { get; set; } + public string? LastName { get; set; } + + [Required(ErrorMessage = "Username is required")] + public string UserName { get; set; } = null!; + + [Required(ErrorMessage = "Email is required")] + [EmailAddress] + public string Email { get; set; } = null!; + public bool EmailConfirmed { get; set; } = false; + + [Required(ErrorMessage = "Password is required")] + [DataType(DataType.Password)] + public string Password { get; set; } = null!; + [DataType(DataType.Password)] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } = null!; + + public string? PhoneNumber { get; set; } + public bool PhoneNumberConfirmed { get; set; } = false; + + public virtual IList RoleIds { get; set; } = new List { "User" }; +} + +public class UpdateUserDto +{ + [Required] + public string Id { get; set; } = null!; + + public string? FirstName { get; set; } + public string? LastName { get; set; } + + public string UserName { get; set; } = null!; + + [EmailAddress] + public string Email { get; set; } = null!; + public bool EmailConfirmed { get; set; } + + [DataType(DataType.Password)] + public string Password { get; set; } = null!; + [DataType(DataType.Password)] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } = null!; + + public string? PhoneNumber { get; set; } + public bool PhoneNumberConfirmed { get; set; } + + public virtual IList RoleIds { get; set; } = new List { "User" }; +} \ No newline at end of file diff --git a/SharedModels/QueryParameters/ISearchable.cs b/SharedModels/QueryParameters/ISearchable.cs new file mode 100644 index 0000000..1db64ac --- /dev/null +++ b/SharedModels/QueryParameters/ISearchable.cs @@ -0,0 +1,6 @@ +namespace SharedModels.QueryParameters; + +public interface ISearchable +{ + public string? Search { get; set; } +} \ No newline at end of file diff --git a/SharedModels/QueryParameters/IShapeable.cs b/SharedModels/QueryParameters/IShapeable.cs new file mode 100644 index 0000000..013616f --- /dev/null +++ b/SharedModels/QueryParameters/IShapeable.cs @@ -0,0 +1,6 @@ +namespace SharedModels.QueryParameters; + +public interface IShapeable +{ + public string? Fields { get; set; } +} \ No newline at end of file diff --git a/SharedModels/QueryParameters/ISortable.cs b/SharedModels/QueryParameters/ISortable.cs new file mode 100644 index 0000000..08b5154 --- /dev/null +++ b/SharedModels/QueryParameters/ISortable.cs @@ -0,0 +1,6 @@ +namespace SharedModels.QueryParameters; + +public interface ISortable +{ + public string? Sort { get; set; } +} \ No newline at end of file diff --git a/SharedModels/QueryStringParameters/AddressParameters.cs b/SharedModels/QueryParameters/Objects/AddressParameters.cs similarity index 70% rename from SharedModels/QueryStringParameters/AddressParameters.cs rename to SharedModels/QueryParameters/Objects/AddressParameters.cs index 9eba78c..5fef293 100644 --- a/SharedModels/QueryStringParameters/AddressParameters.cs +++ b/SharedModels/QueryParameters/Objects/AddressParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class AddressParameters : QueryStringParameters +public class AddressParameters : ParametersBase { public const string DefaultFields = "id,name,cityId"; diff --git a/SharedModels/QueryStringParameters/CityParameters.cs b/SharedModels/QueryParameters/Objects/CityParameters.cs similarity index 71% rename from SharedModels/QueryStringParameters/CityParameters.cs rename to SharedModels/QueryParameters/Objects/CityParameters.cs index 9141345..e78f12f 100644 --- a/SharedModels/QueryStringParameters/CityParameters.cs +++ b/SharedModels/QueryParameters/Objects/CityParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class CityParameters : QueryStringParameters +public class CityParameters : ParametersBase { public const string DefaultFields = "id,name,stateId"; diff --git a/SharedModels/QueryStringParameters/CompanyParameters.cs b/SharedModels/QueryParameters/Objects/CompanyParameters.cs similarity index 70% rename from SharedModels/QueryStringParameters/CompanyParameters.cs rename to SharedModels/QueryParameters/Objects/CompanyParameters.cs index b428c64..43fe683 100644 --- a/SharedModels/QueryStringParameters/CompanyParameters.cs +++ b/SharedModels/QueryParameters/Objects/CompanyParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class CompanyParameters : QueryStringParameters +public class CompanyParameters : ParametersBase { public const string DefaultFields = "id,ownerId,name"; diff --git a/SharedModels/QueryStringParameters/CountryParameters.cs b/SharedModels/QueryParameters/Objects/CountryParameters.cs similarity index 70% rename from SharedModels/QueryStringParameters/CountryParameters.cs rename to SharedModels/QueryParameters/Objects/CountryParameters.cs index d1e64c1..00065ef 100644 --- a/SharedModels/QueryStringParameters/CountryParameters.cs +++ b/SharedModels/QueryParameters/Objects/CountryParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class CountryParameters : QueryStringParameters +public class CountryParameters : ParametersBase { public const string DefaultFields = "id,code,name"; diff --git a/SharedModels/QueryParameters/Objects/ParametersBase.cs b/SharedModels/QueryParameters/Objects/ParametersBase.cs new file mode 100644 index 0000000..56cc436 --- /dev/null +++ b/SharedModels/QueryParameters/Objects/ParametersBase.cs @@ -0,0 +1,8 @@ +namespace SharedModels.QueryParameters.Objects; + +public class ParametersBase : PagingParameters, ISearchable, ISortable, IShapeable +{ + public string? Search { get; set; } + public string? Sort { get; set; } + public string? Fields { get; set; } +} \ No newline at end of file diff --git a/SharedModels/QueryStringParameters/ReviewParameters.cs b/SharedModels/QueryParameters/Objects/ReviewParameters.cs similarity index 52% rename from SharedModels/QueryStringParameters/ReviewParameters.cs rename to SharedModels/QueryParameters/Objects/ReviewParameters.cs index 2cdcc40..9dbaff5 100644 --- a/SharedModels/QueryStringParameters/ReviewParameters.cs +++ b/SharedModels/QueryParameters/Objects/ReviewParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class ReviewParameters : QueryStringParameters +public class ReviewParameters : ParametersBase { public const string DefaultFields = "id,userId,vehicleEnrollmentId,rating,comment"; @@ -10,6 +10,9 @@ public class ReviewParameters : QueryStringParameters Fields = DefaultFields; } - public int? Rating { get; set; } + public int? FromRating { get; set; } + public int? ToRating { get; set; } + public string? Comment { get; set; } + public string? UserId { get; set; } } \ No newline at end of file diff --git a/SharedModels/QueryStringParameters/RouteAddressParameters.cs b/SharedModels/QueryParameters/Objects/RouteAddressParameters.cs similarity index 77% rename from SharedModels/QueryStringParameters/RouteAddressParameters.cs rename to SharedModels/QueryParameters/Objects/RouteAddressParameters.cs index 856f3f8..e8793b0 100644 --- a/SharedModels/QueryStringParameters/RouteAddressParameters.cs +++ b/SharedModels/QueryParameters/Objects/RouteAddressParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class RouteAddressParameters : QueryStringParameters +public class RouteAddressParameters : ParametersBase { public const string DefaultFields = "id,routeId,addressId,order,timeSpanToNextCity," + "waitTimeSpan,costToNextCity"; diff --git a/SharedModels/QueryStringParameters/RouteParameters.cs b/SharedModels/QueryParameters/Objects/RouteParameters.cs similarity index 66% rename from SharedModels/QueryStringParameters/RouteParameters.cs rename to SharedModels/QueryParameters/Objects/RouteParameters.cs index c3275fa..258cd62 100644 --- a/SharedModels/QueryStringParameters/RouteParameters.cs +++ b/SharedModels/QueryParameters/Objects/RouteParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class RouteParameters : QueryStringParameters +public class RouteParameters : ParametersBase { public const string DefaultFields = "id,type"; diff --git a/SharedModels/QueryStringParameters/StateParameters.cs b/SharedModels/QueryParameters/Objects/StateParameters.cs similarity index 71% rename from SharedModels/QueryStringParameters/StateParameters.cs rename to SharedModels/QueryParameters/Objects/StateParameters.cs index 9c44b31..6023808 100644 --- a/SharedModels/QueryStringParameters/StateParameters.cs +++ b/SharedModels/QueryParameters/Objects/StateParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class StateParameters : QueryStringParameters +public class StateParameters : ParametersBase { public const string DefaultFields = "id,name,countryId"; diff --git a/SharedModels/QueryStringParameters/TicketParameters.cs b/SharedModels/QueryParameters/Objects/TicketParameters.cs similarity index 73% rename from SharedModels/QueryStringParameters/TicketParameters.cs rename to SharedModels/QueryParameters/Objects/TicketParameters.cs index 5ac6890..21d57f1 100644 --- a/SharedModels/QueryStringParameters/TicketParameters.cs +++ b/SharedModels/QueryParameters/Objects/TicketParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class TicketParameters : QueryStringParameters +public class TicketParameters : ParametersBase { public const string DefaultFields = "id,userId,vehicleEnrollmentId,purchaseDateTimeUtc,isReturned"; @@ -13,4 +13,5 @@ public class TicketParameters : QueryStringParameters public DateTime? FromPurchaseDateTimeUtc { get; set; } public DateTime? ToPurchaseDateTimeUtc { get; set; } public bool? IsReturned { get; set; } + public string? UserId { get; set; } } \ No newline at end of file diff --git a/SharedModels/QueryParameters/Objects/UserParameters.cs b/SharedModels/QueryParameters/Objects/UserParameters.cs new file mode 100644 index 0000000..77fd0f3 --- /dev/null +++ b/SharedModels/QueryParameters/Objects/UserParameters.cs @@ -0,0 +1,18 @@ +namespace SharedModels.QueryParameters.Objects; + +public class UserParameters : ParametersBase +{ + public const string DefaultFields = ""; + + public UserParameters() + { + Sort = "id"; + Fields = DefaultFields; + } + + public string? FirstName { get; set; } + public string? LastName { get; set; } + public string? Username { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } +} \ No newline at end of file diff --git a/SharedModels/QueryStringParameters/VehicleEnrollmentParameters.cs b/SharedModels/QueryParameters/Objects/VehicleEnrollmentParameters.cs similarity index 83% rename from SharedModels/QueryStringParameters/VehicleEnrollmentParameters.cs rename to SharedModels/QueryParameters/Objects/VehicleEnrollmentParameters.cs index 5f13d33..96c0201 100644 --- a/SharedModels/QueryStringParameters/VehicleEnrollmentParameters.cs +++ b/SharedModels/QueryParameters/Objects/VehicleEnrollmentParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class VehicleEnrollmentParameters : QueryStringParameters +public class VehicleEnrollmentParameters : ParametersBase { public const string DefaultFields = "id,vehicleId,routeId,departureDateTimeUtc," + "delayTimeSpan,isCancelled,cancellationComment"; diff --git a/SharedModels/QueryStringParameters/VehicleParameters.cs b/SharedModels/QueryParameters/Objects/VehicleParameters.cs similarity index 88% rename from SharedModels/QueryStringParameters/VehicleParameters.cs rename to SharedModels/QueryParameters/Objects/VehicleParameters.cs index fd13159..665c655 100644 --- a/SharedModels/QueryStringParameters/VehicleParameters.cs +++ b/SharedModels/QueryParameters/Objects/VehicleParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters.Objects; -public class VehicleParameters : QueryStringParameters +public class VehicleParameters : ParametersBase { public const string DefaultFields = "id,companyId,number,type,capacity,hasClimateControl," + "hasWiFi,hasWC,hasStewardess,hasTV,hasOutlet,hasBelts"; diff --git a/SharedModels/QueryStringParameters/PagingMetadata.cs b/SharedModels/QueryParameters/PagingMetadata.cs similarity index 92% rename from SharedModels/QueryStringParameters/PagingMetadata.cs rename to SharedModels/QueryParameters/PagingMetadata.cs index 57dc292..137202b 100644 --- a/SharedModels/QueryStringParameters/PagingMetadata.cs +++ b/SharedModels/QueryParameters/PagingMetadata.cs @@ -1,4 +1,4 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters; public class PagingMetadata { diff --git a/SharedModels/QueryStringParameters/QueryStringParameters.cs b/SharedModels/QueryParameters/PagingParameters.cs similarity index 55% rename from SharedModels/QueryStringParameters/QueryStringParameters.cs rename to SharedModels/QueryParameters/PagingParameters.cs index ba6f037..dcf6688 100644 --- a/SharedModels/QueryStringParameters/QueryStringParameters.cs +++ b/SharedModels/QueryParameters/PagingParameters.cs @@ -1,6 +1,6 @@ -namespace SharedModels.QueryStringParameters; +namespace SharedModels.QueryParameters; -public class QueryStringParameters +public class PagingParameters { public int PageNumber { get; set; } = 1; @@ -11,8 +11,4 @@ public class QueryStringParameters get => _pageSize; set => _pageSize = value > MaxPageSize ? MaxPageSize : value; } - - public string? Search { get; set; } - public string? Sort { get; set; } - public string? Fields { get; set; } } \ No newline at end of file diff --git a/SharedModels/QueryParameters/Statistics/EngagedUserParameters.cs b/SharedModels/QueryParameters/Statistics/EngagedUserParameters.cs new file mode 100644 index 0000000..55ae1bd --- /dev/null +++ b/SharedModels/QueryParameters/Statistics/EngagedUserParameters.cs @@ -0,0 +1,14 @@ +namespace SharedModels.QueryParameters.Statistics; + +public class EngagedUserParameters : ParametersBase +{ + public readonly string DefaultFields = "id,firstName,lastName,username,email,phoneNumber,ticketCount"; + public readonly int DefaultDays = 60; + + public EngagedUserParameters() + { + Fields = DefaultFields; + } + + public int? Days { get; set; } +} \ No newline at end of file diff --git a/SharedModels/QueryParameters/Statistics/ParametersBase.cs b/SharedModels/QueryParameters/Statistics/ParametersBase.cs new file mode 100644 index 0000000..ed8bf7e --- /dev/null +++ b/SharedModels/QueryParameters/Statistics/ParametersBase.cs @@ -0,0 +1,7 @@ +namespace SharedModels.QueryParameters.Statistics; + +public class ParametersBase : PagingParameters, IShapeable +{ + public int Amount { get; set; } = 10; + public string? Fields { get; set; } +} \ No newline at end of file