add "Engaged users" statistics

This commit is contained in:
cuqmbr 2022-11-23 19:45:15 +02:00
parent 9b076610ca
commit 606bb93825
75 changed files with 2976 additions and 90 deletions

View File

@ -35,11 +35,12 @@ public class MapperInitializer : Profile
CreateMap<RouteAddress, RouteAddressDto>().ReverseMap();
CreateMap<RouteAddress, CreateRouteAddressDto>().ReverseMap();
CreateMap<RouteAddress, UpdateRouteAddressDto>().ReverseMap();
CreateMap<RouteAddress, InRouteRouteAddressDto>().ReverseMap();
CreateMap<RouteAddress, CreateRouteAddressWithAddressDto>().ReverseMap();
CreateMap<Route, RouteDto>().ReverseMap();
CreateMap<Route, CreateRouteDto>().ReverseMap();
CreateMap<Route, UpdateRouteDto>().ReverseMap();
CreateMap<Route, CreateRouteWithAddressesDto>().ReverseMap();
@ -66,8 +67,8 @@ public class MapperInitializer : Profile
CreateMap<VehicleEnrollment, UpdateVehicleEnrollmentDto>().ReverseMap();
// CreateMap<User, UserDto>().ReverseMap();
// CreateMap<User, CreateUserDto>().ReverseMap();
// CreateMap<User, UpdateUserDto>().ReverseMap();
CreateMap<User, UserDto>().ReverseMap();
CreateMap<User, CreateUserDto>().ReverseMap();
CreateMap<User, UpdateUserDto>().ReverseMap();
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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<IActionResult> GetPopularRoutes([FromQuery] int amount = 10)
{
return Ok();
}
[HttpGet("users")]
public async Task<IActionResult> 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<IActionResult> GetPopularCompanies([FromQuery] int amount = 10)
{
return Ok();
}
[HttpGet("stations")]
public async Task<IActionResult> GetPopularStations([FromQuery] int amount = 10)
{
return Ok();
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,793 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("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<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CityId")
.HasColumnType("integer");
b.Property<double>("Latitude")
.HasColumnType("double precision");
b.Property<double>("Longitude")
.HasColumnType("double precision");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CityId");
b.ToTable("Addresses");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("StateId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("StateId");
b.ToTable("Cities");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.ToTable("Companies");
});
modelBuilder.Entity("Server.Models.Country", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Code")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Countries");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<int>("Rating")
.HasColumnType("integer");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Reviews");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Routes");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AddressId")
.HasColumnType("integer");
b.Property<double>("CostToNextCity")
.HasColumnType("double precision");
b.Property<int>("Order")
.HasColumnType("integer");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<TimeSpan>("TimeSpanToNextCity")
.HasColumnType("interval");
b.Property<TimeSpan>("WaitTimeSpan")
.HasColumnType("interval");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CountryId")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CountryId");
b.ToTable("States");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsReturned")
.HasColumnType("boolean");
b.Property<DateTime>("PurchaseDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("Capacity")
.HasColumnType("integer");
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<bool>("HasBelts")
.HasColumnType("boolean");
b.Property<bool>("HasClimateControl")
.HasColumnType("boolean");
b.Property<bool>("HasOutlet")
.HasColumnType("boolean");
b.Property<bool>("HasStewardess")
.HasColumnType("boolean");
b.Property<bool>("HasTV")
.HasColumnType("boolean");
b.Property<bool>("HasWC")
.HasColumnType("boolean");
b.Property<bool>("HasWiFi")
.HasColumnType("boolean");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CompanyId");
b.ToTable("Vehicles");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("CancelationComment")
.HasColumnType("text");
b.Property<TimeSpan?>("DelayTimeSpan")
.HasColumnType("interval");
b.Property<DateTime>("DepartureDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsCanceled")
.HasColumnType("boolean");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<int>("VehicleId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", 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<string>", 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<string>("UserId")
.HasColumnType("text");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("CreationDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("ExpiryDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime?>("Revoked")
.HasColumnType("timestamp with time zone");
b1.Property<string>("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
}
}
}

View File

@ -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");
}
}
}

View File

@ -0,0 +1,799 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("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<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CityId")
.HasColumnType("integer");
b.Property<double>("Latitude")
.HasColumnType("double precision");
b.Property<double>("Longitude")
.HasColumnType("double precision");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CityId");
b.ToTable("Addresses");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("StateId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("StateId");
b.ToTable("Cities");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.ToTable("Companies");
});
modelBuilder.Entity("Server.Models.Country", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Code")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Countries");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("PostDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<int>("Rating")
.HasColumnType("integer");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Reviews");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Routes");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AddressId")
.HasColumnType("integer");
b.Property<double>("CostToNextCity")
.HasColumnType("double precision");
b.Property<int>("Order")
.HasColumnType("integer");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<TimeSpan>("TimeSpanToNextCity")
.HasColumnType("interval");
b.Property<TimeSpan>("WaitTimeSpan")
.HasColumnType("interval");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CountryId")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CountryId");
b.ToTable("States");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsMissed")
.HasColumnType("boolean");
b.Property<bool>("IsReturned")
.HasColumnType("boolean");
b.Property<DateTime>("PurchaseDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("Capacity")
.HasColumnType("integer");
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<bool>("HasBelts")
.HasColumnType("boolean");
b.Property<bool>("HasClimateControl")
.HasColumnType("boolean");
b.Property<bool>("HasOutlet")
.HasColumnType("boolean");
b.Property<bool>("HasStewardess")
.HasColumnType("boolean");
b.Property<bool>("HasTV")
.HasColumnType("boolean");
b.Property<bool>("HasWC")
.HasColumnType("boolean");
b.Property<bool>("HasWiFi")
.HasColumnType("boolean");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CompanyId");
b.ToTable("Vehicles");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("CancelationComment")
.HasColumnType("text");
b.Property<TimeSpan?>("DelayTimeSpan")
.HasColumnType("interval");
b.Property<DateTime>("DepartureDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsCanceled")
.HasColumnType("boolean");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<int>("VehicleId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", 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<string>", 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<string>("UserId")
.HasColumnType("text");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("CreationDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("ExpiryDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime?>("Revoked")
.HasColumnType("timestamp with time zone");
b1.Property<string>("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
}
}
}

View File

@ -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<bool>(
name: "IsMissed",
table: "Tickets",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<DateTime>(
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");
}
}
}

View File

@ -0,0 +1,806 @@
// <auto-generated />
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<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("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<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CityId")
.HasColumnType("integer");
b.Property<double>("Latitude")
.HasColumnType("double precision");
b.Property<double>("Longitude")
.HasColumnType("double precision");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CityId");
b.ToTable("Addresses");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("StateId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("StateId");
b.ToTable("Cities");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.ToTable("Companies");
});
modelBuilder.Entity("Server.Models.Country", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Code")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Countries");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("PostDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<int>("Rating")
.HasColumnType("integer");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Reviews");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Routes");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AddressId")
.HasColumnType("integer");
b.Property<double>("CostToNextCity")
.HasColumnType("double precision");
b.Property<int>("Order")
.HasColumnType("integer");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<TimeSpan>("TimeSpanToNextCity")
.HasColumnType("interval");
b.Property<TimeSpan>("WaitTimeSpan")
.HasColumnType("interval");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CountryId")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CountryId");
b.ToTable("States");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsMissed")
.HasColumnType("boolean");
b.Property<bool>("IsReturned")
.HasColumnType("boolean");
b.Property<DateTime>("PurchaseDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("Capacity")
.HasColumnType("integer");
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<bool>("HasBelts")
.HasColumnType("boolean");
b.Property<bool>("HasClimateControl")
.HasColumnType("boolean");
b.Property<bool>("HasOutlet")
.HasColumnType("boolean");
b.Property<bool>("HasStewardess")
.HasColumnType("boolean");
b.Property<bool>("HasTV")
.HasColumnType("boolean");
b.Property<bool>("HasWC")
.HasColumnType("boolean");
b.Property<bool>("HasWiFi")
.HasColumnType("boolean");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CompanyId");
b.ToTable("Vehicles");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("CancelationComment")
.HasColumnType("text");
b.Property<TimeSpan?>("DelayTimeSpan")
.HasColumnType("interval");
b.Property<DateTime>("DepartureDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsCanceled")
.HasColumnType("boolean");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<int>("VehicleId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", 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<string>", 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<string>("UserId")
.HasColumnType("text");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("CreationDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("ExpiryDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime?>("Revoked")
.HasColumnType("timestamp with time zone");
b1.Property<string>("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
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -259,6 +259,9 @@ namespace Server.Migrations
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<DateTime>("PostDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<int>("Rating")
.HasColumnType("integer");
@ -360,6 +363,9 @@ namespace Server.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsMissed")
.HasColumnType("boolean");
b.Property<bool>("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<int>("Id"));
b1.Property<DateTime>("Created")
b1.Property<DateTime>("CreationDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("Expires")
b1.Property<DateTime>("ExpiryDateTime")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime?>("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
}
}

View File

@ -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; }
}

View File

@ -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;
}

View File

@ -6,5 +6,7 @@ public class User : IdentityUser
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public List<RefreshToken> RefreshTokens { get; set; } = null!;
public IList<RefreshToken> RefreshTokens { get; set; } = null!;
public virtual IList<Ticket> Tickets { get; set; } = null!;
public virtual IList<Review> Reviews { get; set; } = null!;
}

View File

@ -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<IVehicleEnrollmentManagementService, VehicleEnrollmen
builder.Services.AddScoped<IRouteManagementService, RouteManagementService>();
builder.Services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
builder.Services.AddScoped<IStatisticsService, StatisticsService>();
builder.Services.AddScoped<ISortHelper<Country>, SortHelper<Country>>();
builder.Services.AddScoped<ISortHelper<State>, SortHelper<State>>();
builder.Services.AddScoped<ISortHelper<City>, SortHelper<City>>();
@ -115,6 +119,8 @@ builder.Services.AddScoped<ISortHelper<VehicleEnrollment>, SortHelper<VehicleEnr
builder.Services.AddScoped<ISortHelper<Route>, SortHelper<Route>>();
builder.Services.AddScoped<ISortHelper<RouteAddress>, SortHelper<RouteAddress>>();
builder.Services.AddScoped<IDataShaper<User>, DataShaper<User>>();
builder.Services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
builder.Services.AddScoped<IDataShaper<Country>, DataShaper<Country>>();
builder.Services.AddScoped<IDataShaper<State>, DataShaper<State>>();
builder.Services.AddScoped<IDataShaper<City>, DataShaper<City>>();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -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;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -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<ExpandoObject> route)>
GetPopularRoutes(int amount);
Task<(bool IsSucceed, string? message, IEnumerable<ExpandoObject> users, PagingMetadata<User> pagingMetadata)>
GetEngagedUsers(EngagedUserParameters parameters);
Task<(bool IsSucceed, string? message, IEnumerable<ExpandoObject> companies)>
GetPopularCompanies(int amount);
Task<(bool IsSucceed, string? message, IEnumerable<ExpandoObject> stations)>
GetPopularStations(int amount);
}

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -1,6 +1,7 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;

View File

@ -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<Review> 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<Review> reviews,
@ -88,6 +91,18 @@ public class ReviewManagementService : IReviewManagementService
r.Comment != null &&
r.Comment.ToLower().Contains(comment.ToLower()));
}
void FilterByReviewUserId(ref IQueryable<Review> reviews,
string? userId)
{
if (!reviews.Any() || String.IsNullOrWhiteSpace(userId))
{
return;
}
reviews = reviews.Where(r =>
r.UserId.Contains(userId.ToLower()));
}
PagingMetadata<Review> ApplyPaging(ref IQueryable<Review> reviews,
int pageNumber, int pageSize)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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<UserDto> _userDataShaper;
public StatisticsService(ApplicationDbContext dbContext, IMapper mapper,
IDataShaper<UserDto> userDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_userDataShaper = userDataShaper;
}
// Popularity is measured in number of purchased tickets
public async Task<(bool IsSucceed, string? message, IEnumerable<ExpandoObject> 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<ExpandoObject> users, PagingMetadata<User> 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<UserDto>(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<ExpandoObject> 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<ExpandoObject> stations)>
GetPopularStations(int amount)
{
throw new NotImplementedException();
}
PagingMetadata<T> ApplyPaging<T>(ref IQueryable<T> obj,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<T>(obj,
pageNumber, pageSize);
obj = obj
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}

View File

@ -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<Ticket> tickets,
string? userId)
{
if (!tickets.Any() || String.IsNullOrWhiteSpace(userId))
{
return;
}
tickets = tickets.Where(t =>
t.UserId.ToLower().Contains(userId.ToLower()));
}
PagingMetadata<Ticket> ApplyPaging(ref IQueryable<Ticket> tickets,
int pageNumber, int pageSize)
{

View File

@ -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;

View File

@ -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;

View File

@ -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",

View File

@ -7,8 +7,6 @@ public class AddressDto : CreateAddressDto
public int Id { get; set; }
public InAddressCityDto City { get; set; } = null!;
public virtual IList<RouteAddressDto> RouteAddresses { get; set; } = null!;
}
public class CreateAddressDto

View File

@ -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; }
}

View File

@ -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!;
}

View File

@ -5,8 +5,6 @@ namespace SharedModels.DataTransferObjects;
public class RouteDto : CreateRouteDto
{
public int Id { get; set; }
public virtual IList<InRouteRouteAddressDto> 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<CreateRouteAddressWithAddressDto> RouteAddresses { get; set; } = null!;
}

View File

@ -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;
}

View File

@ -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<TicketDto> Tickets { get; set; } = null!;
public virtual IList<ReviewDto> 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<string> RoleIds { get; set; } = new List<string> { "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<string> RoleIds { get; set; } = new List<string> { "User" };
}

View File

@ -0,0 +1,6 @@
namespace SharedModels.QueryParameters;
public interface ISearchable
{
public string? Search { get; set; }
}

View File

@ -0,0 +1,6 @@
namespace SharedModels.QueryParameters;
public interface IShapeable
{
public string? Fields { get; set; }
}

View File

@ -0,0 +1,6 @@
namespace SharedModels.QueryParameters;
public interface ISortable
{
public string? Sort { get; set; }
}

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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";

View File

@ -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";

View File

@ -1,4 +1,4 @@
namespace SharedModels.QueryStringParameters;
namespace SharedModels.QueryParameters;
public class PagingMetadata<T>
{

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -0,0 +1,7 @@
namespace SharedModels.QueryParameters.Statistics;
public class ParametersBase : PagingParameters, IShapeable
{
public int Amount { get; set; } = 10;
public string? Fields { get; set; }
}