feat: add complex route addition and retrieval
This commit is contained in:
parent
a91af2f42a
commit
280d883213
@ -31,16 +31,20 @@ public class MapperInitializer : Profile
|
|||||||
CreateMap<Address, CreateAddressDto>().ReverseMap();
|
CreateMap<Address, CreateAddressDto>().ReverseMap();
|
||||||
CreateMap<Address, UpdateAddressDto>().ReverseMap();
|
CreateMap<Address, UpdateAddressDto>().ReverseMap();
|
||||||
CreateMap<Address, InCityAddressDto>().ReverseMap();
|
CreateMap<Address, InCityAddressDto>().ReverseMap();
|
||||||
|
CreateMap<Address, CreateAddressInRouteAddress>().ReverseMap();
|
||||||
|
CreateMap<Address, AddressInRouteAddress>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<RouteAddress, RouteAddressDto>().ReverseMap();
|
CreateMap<RouteAddress, RouteAddressDto>().ReverseMap();
|
||||||
CreateMap<RouteAddress, CreateRouteAddressDto>().ReverseMap();
|
CreateMap<RouteAddress, CreateRouteAddressDto>().ReverseMap();
|
||||||
CreateMap<RouteAddress, UpdateRouteAddressDto>().ReverseMap();
|
CreateMap<RouteAddress, UpdateRouteAddressDto>().ReverseMap();
|
||||||
CreateMap<RouteAddress, CreateRouteAddressWithAddressDto>().ReverseMap();
|
CreateMap<RouteAddress, CreateRouteAddressWithAddressDto>().ReverseMap();
|
||||||
|
CreateMap<RouteAddress, RouteAddressWithAddressDto>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<Route, RouteDto>().ReverseMap();
|
CreateMap<Route, RouteDto>().ReverseMap();
|
||||||
CreateMap<Route, CreateRouteDto>().ReverseMap();
|
CreateMap<Route, CreateRouteDto>().ReverseMap();
|
||||||
CreateMap<Route, UpdateRouteDto>().ReverseMap();
|
CreateMap<Route, UpdateRouteDto>().ReverseMap();
|
||||||
CreateMap<Route, CreateRouteWithAddressesDto>().ReverseMap();
|
CreateMap<Route, CreateRouteWithAddressesDto>().ReverseMap();
|
||||||
|
CreateMap<Route, RouteWithAddressesDto>().ReverseMap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,19 @@ public class RouteController : ControllerBase
|
|||||||
return CreatedAtAction(nameof(GetRoute), new {id = result.route.Id}, result.route);
|
return CreatedAtAction(nameof(GetRoute), new {id = result.route.Id}, result.route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("withAddresses")]
|
||||||
|
public async Task<IActionResult> AddRouteWithAddresses(CreateRouteWithAddressesDto route)
|
||||||
|
{
|
||||||
|
var result = await _routeManagementService.AddRouteWithAddresses(route);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreatedAtAction(nameof(GetRoute), new {id = result.route.Id}, result.route);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetRoutes([FromQuery] RouteParameters parameters)
|
public async Task<IActionResult> GetRoutes([FromQuery] RouteParameters parameters)
|
||||||
{
|
{
|
||||||
@ -45,6 +58,21 @@ public class RouteController : ControllerBase
|
|||||||
return Ok(result.routes);
|
return Ok(result.routes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("withAddresses")]
|
||||||
|
public async Task<IActionResult> GetRouteWithAddresses([FromQuery] RouteWithAddressesParameters parameters)
|
||||||
|
{
|
||||||
|
var result = await _routeManagementService.GetRoutesWithAddresses(parameters);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
|
||||||
|
|
||||||
|
return Ok(result.routes);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<IActionResult> GetRoute(int id, [FromQuery] string? fields)
|
public async Task<IActionResult> GetRoute(int id, [FromQuery] string? fields)
|
||||||
{
|
{
|
||||||
@ -62,6 +90,24 @@ public class RouteController : ControllerBase
|
|||||||
|
|
||||||
return Ok(result.route);
|
return Ok(result.route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("withAddresses/{id}")]
|
||||||
|
public async Task<IActionResult> GetRouteWithAddresses(int id, [FromQuery] string? fields)
|
||||||
|
{
|
||||||
|
if (!await _routeManagementService.IsRouteExists(id))
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _routeManagementService.GetRouteWithAddresses(id, fields);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return BadRequest(result.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(result.route);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
public async Task<IActionResult> UpdateRoute(int id, UpdateRouteDto route)
|
public async Task<IActionResult> UpdateRoute(int id, UpdateRouteDto route)
|
||||||
|
@ -18,6 +18,8 @@ public class ApplicationDbContext : IdentityDbContext<User>
|
|||||||
public DbSet<Route> Routes { get; set; } = null!;
|
public DbSet<Route> Routes { get; set; } = null!;
|
||||||
public DbSet<RouteAddress> RouteAddresses { get; set; } = null!;
|
public DbSet<RouteAddress> RouteAddresses { get; set; } = null!;
|
||||||
public DbSet<Address> Addresses { get; set; } = null!;
|
public DbSet<Address> Addresses { get; set; } = null!;
|
||||||
|
|
||||||
|
public DbSet<RouteAddressDetails> RouteAddressDetails { get; set; } = null!;
|
||||||
public DbSet<City> Cities { get; set; } = null!;
|
public DbSet<City> Cities { get; set; } = null!;
|
||||||
public DbSet<State> States { get; set; } = null!;
|
public DbSet<State> States { get; set; } = null!;
|
||||||
public DbSet<Country> Countries { get; set; } = null!;
|
public DbSet<Country> Countries { get; set; } = null!;
|
||||||
|
8
Server/Helpers/IPager.cs
Normal file
8
Server/Helpers/IPager.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using SharedModels.QueryParameters;
|
||||||
|
|
||||||
|
namespace Server.Helpers;
|
||||||
|
|
||||||
|
public interface IPager<T>
|
||||||
|
{
|
||||||
|
PagingMetadata<T> ApplyPaging(ref IQueryable<T> obj, int pageNumber, int pageSize);
|
||||||
|
}
|
19
Server/Helpers/Pager.cs
Normal file
19
Server/Helpers/Pager.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using SharedModels.QueryParameters;
|
||||||
|
|
||||||
|
namespace Server.Helpers;
|
||||||
|
|
||||||
|
public class Pager<T> : IPager<T>
|
||||||
|
{
|
||||||
|
public PagingMetadata<T> ApplyPaging(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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Dynamic;
|
||||||
using System.Linq.Dynamic.Core;
|
using System.Linq.Dynamic.Core;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -14,8 +15,9 @@ public class SortHelper<T> : ISortHelper<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var orderParams = orderByQueryString.Trim().Split(",");
|
var orderParams = orderByQueryString.Trim().Split(",");
|
||||||
var propertyInfos =
|
var propertyStrings = typeof(T) == typeof(ExpandoObject) ?
|
||||||
typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
(entities.First() as ExpandoObject).ToDictionary(o => o.Key, o => o.Value).Keys.ToList() :
|
||||||
|
typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList().ConvertAll(o => o.GetType().ToString());
|
||||||
var orderQueryBuilder = new StringBuilder();
|
var orderQueryBuilder = new StringBuilder();
|
||||||
|
|
||||||
foreach (var param in orderParams)
|
foreach (var param in orderParams)
|
||||||
@ -26,8 +28,8 @@ public class SortHelper<T> : ISortHelper<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
var propertyFromQueryName = param[0] == '-' || param[0] == '+' ? param.Substring(1) : param;
|
var propertyFromQueryName = param[0] == '-' || param[0] == '+' ? param.Substring(1) : param;
|
||||||
var objectProperty = propertyInfos.FirstOrDefault(pi =>
|
var objectProperty = propertyStrings.FirstOrDefault(ps =>
|
||||||
pi.Name.Equals(propertyFromQueryName, StringComparison.InvariantCultureIgnoreCase));
|
ps.Equals(propertyFromQueryName, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
if (objectProperty == null)
|
if (objectProperty == null)
|
||||||
{
|
{
|
||||||
@ -36,11 +38,13 @@ public class SortHelper<T> : ISortHelper<T>
|
|||||||
|
|
||||||
var sortingOrder = param[0] == '-' ? "descending" : "ascending";
|
var sortingOrder = param[0] == '-' ? "descending" : "ascending";
|
||||||
|
|
||||||
orderQueryBuilder.Append($"{objectProperty.Name} {sortingOrder}, ");
|
orderQueryBuilder.Append($"{objectProperty} {sortingOrder}, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
var orderQuery = orderQueryBuilder.ToString().TrimEnd(',', ' ');
|
var orderQuery = orderQueryBuilder.ToString().TrimEnd(',', ' ');
|
||||||
|
|
||||||
return entities.OrderBy(orderQuery);
|
return typeof(T) == typeof(ExpandoObject) ?
|
||||||
|
entities.Cast<dynamic>().OrderBy(orderQuery).Cast<T>() :
|
||||||
|
entities.OrderBy(orderQuery);
|
||||||
}
|
}
|
||||||
}
|
}
|
915
Server/Migrations/20221129160345_Decouple_RouteAddress_and_RouteAddressDetails.Designer.cs
generated
Normal file
915
Server/Migrations/20221129160345_Decouple_RouteAddress_and_RouteAddressDetails.Designer.cs
generated
Normal file
@ -0,0 +1,915 @@
|
|||||||
|
// <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("20221129160345_Decouple_RouteAddress_and_RouteAddressDetails")]
|
||||||
|
partial class Decouple_RouteAddress_and_RouteAddressDetails
|
||||||
|
{
|
||||||
|
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<int>("Order")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("RouteAddressDetailsId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("RouteId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AddressId");
|
||||||
|
|
||||||
|
b.HasIndex("RouteId");
|
||||||
|
|
||||||
|
b.ToTable("RouteAddresses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.RouteAddressDetails", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<double>("CostToNextCity")
|
||||||
|
.HasColumnType("double precision");
|
||||||
|
|
||||||
|
b.Property<int>("RouteAddressId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("TimeSpanToNextCity")
|
||||||
|
.HasColumnType("interval");
|
||||||
|
|
||||||
|
b.Property<int>("VehicleEnrollmentId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("WaitTimeSpan")
|
||||||
|
.HasColumnType("interval");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RouteAddressId");
|
||||||
|
|
||||||
|
b.HasIndex("VehicleEnrollmentId");
|
||||||
|
|
||||||
|
b.ToTable("RouteAddressDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
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<int>("FirstRouteAddressId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("IsMissed")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("IsReturned")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("LastRouteAddressId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("PurchaseDateTimeUtc")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("TicketGroupId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("VehicleEnrollmentId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TicketGroupId");
|
||||||
|
|
||||||
|
b.HasIndex("VehicleEnrollmentId");
|
||||||
|
|
||||||
|
b.ToTable("Tickets");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.TicketGroup", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("TicketGroups");
|
||||||
|
});
|
||||||
|
|
||||||
|
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>("RouteAddressDetailsId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
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("Reviews")
|
||||||
|
.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.RouteAddressDetails", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Server.Models.RouteAddress", "RouteAddress")
|
||||||
|
.WithMany("RouteAddressDetails")
|
||||||
|
.HasForeignKey("RouteAddressId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
|
||||||
|
.WithMany("RouteAddressDetails")
|
||||||
|
.HasForeignKey("VehicleEnrollmentId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("RouteAddress");
|
||||||
|
|
||||||
|
b.Navigation("VehicleEnrollment");
|
||||||
|
});
|
||||||
|
|
||||||
|
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.TicketGroup", "TicketGroup")
|
||||||
|
.WithMany("Tickets")
|
||||||
|
.HasForeignKey("TicketGroupId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
|
||||||
|
.WithMany("Tickets")
|
||||||
|
.HasForeignKey("VehicleEnrollmentId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("TicketGroup");
|
||||||
|
|
||||||
|
b.Navigation("VehicleEnrollment");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.TicketGroup", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Server.Models.User", "User")
|
||||||
|
.WithMany("TicketGroups")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
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("VehicleEnrollments")
|
||||||
|
.HasForeignKey("RouteId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Server.Models.Vehicle", "Vehicle")
|
||||||
|
.WithMany("VehicleEnrollments")
|
||||||
|
.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");
|
||||||
|
|
||||||
|
b.Navigation("VehicleEnrollments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.RouteAddress", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("RouteAddressDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.State", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Cities");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.TicketGroup", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Tickets");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Reviews");
|
||||||
|
|
||||||
|
b.Navigation("TicketGroups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.Vehicle", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("VehicleEnrollments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Reviews");
|
||||||
|
|
||||||
|
b.Navigation("RouteAddressDetails");
|
||||||
|
|
||||||
|
b.Navigation("Tickets");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Server.Migrations
|
||||||
|
{
|
||||||
|
public partial class Decouple_RouteAddress_and_RouteAddressDetails : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CostToNextCity",
|
||||||
|
table: "RouteAddresses");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "TimeSpanToNextCity",
|
||||||
|
table: "RouteAddresses");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "WaitTimeSpan",
|
||||||
|
table: "RouteAddresses");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "RouteAddressDetailsId",
|
||||||
|
table: "VehicleEnrollments",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "RouteAddressDetailsId",
|
||||||
|
table: "RouteAddresses",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "RouteAddressDetails",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
VehicleEnrollmentId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
RouteAddressId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
TimeSpanToNextCity = table.Column<TimeSpan>(type: "interval", nullable: false),
|
||||||
|
WaitTimeSpan = table.Column<TimeSpan>(type: "interval", nullable: false),
|
||||||
|
CostToNextCity = table.Column<double>(type: "double precision", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_RouteAddressDetails", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_RouteAddressDetails_RouteAddresses_RouteAddressId",
|
||||||
|
column: x => x.RouteAddressId,
|
||||||
|
principalTable: "RouteAddresses",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_RouteAddressDetails_VehicleEnrollments_VehicleEnrollmentId",
|
||||||
|
column: x => x.VehicleEnrollmentId,
|
||||||
|
principalTable: "VehicleEnrollments",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_RouteAddressDetails_RouteAddressId",
|
||||||
|
table: "RouteAddressDetails",
|
||||||
|
column: "RouteAddressId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_RouteAddressDetails_VehicleEnrollmentId",
|
||||||
|
table: "RouteAddressDetails",
|
||||||
|
column: "VehicleEnrollmentId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "RouteAddressDetails");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "RouteAddressDetailsId",
|
||||||
|
table: "VehicleEnrollments");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "RouteAddressDetailsId",
|
||||||
|
table: "RouteAddresses");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<double>(
|
||||||
|
name: "CostToNextCity",
|
||||||
|
table: "RouteAddresses",
|
||||||
|
type: "double precision",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0.0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<TimeSpan>(
|
||||||
|
name: "TimeSpanToNextCity",
|
||||||
|
table: "RouteAddresses",
|
||||||
|
type: "interval",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new TimeSpan(0, 0, 0, 0, 0));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<TimeSpan>(
|
||||||
|
name: "WaitTimeSpan",
|
||||||
|
table: "RouteAddresses",
|
||||||
|
type: "interval",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new TimeSpan(0, 0, 0, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -309,21 +309,15 @@ namespace Server.Migrations
|
|||||||
b.Property<int>("AddressId")
|
b.Property<int>("AddressId")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<double>("CostToNextCity")
|
|
||||||
.HasColumnType("double precision");
|
|
||||||
|
|
||||||
b.Property<int>("Order")
|
b.Property<int>("Order")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("RouteAddressDetailsId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<int>("RouteId")
|
b.Property<int>("RouteId")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<TimeSpan>("TimeSpanToNextCity")
|
|
||||||
.HasColumnType("interval");
|
|
||||||
|
|
||||||
b.Property<TimeSpan>("WaitTimeSpan")
|
|
||||||
.HasColumnType("interval");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("AddressId");
|
b.HasIndex("AddressId");
|
||||||
@ -333,6 +327,38 @@ namespace Server.Migrations
|
|||||||
b.ToTable("RouteAddresses");
|
b.ToTable("RouteAddresses");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.RouteAddressDetails", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<double>("CostToNextCity")
|
||||||
|
.HasColumnType("double precision");
|
||||||
|
|
||||||
|
b.Property<int>("RouteAddressId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("TimeSpanToNextCity")
|
||||||
|
.HasColumnType("interval");
|
||||||
|
|
||||||
|
b.Property<int>("VehicleEnrollmentId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<TimeSpan>("WaitTimeSpan")
|
||||||
|
.HasColumnType("interval");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RouteAddressId");
|
||||||
|
|
||||||
|
b.HasIndex("VehicleEnrollmentId");
|
||||||
|
|
||||||
|
b.ToTable("RouteAddressDetails");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Server.Models.State", b =>
|
modelBuilder.Entity("Server.Models.State", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -552,6 +578,9 @@ namespace Server.Migrations
|
|||||||
b.Property<bool>("IsCanceled")
|
b.Property<bool>("IsCanceled")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("RouteAddressDetailsId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<int>("RouteId")
|
b.Property<int>("RouteId")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
@ -689,6 +718,25 @@ namespace Server.Migrations
|
|||||||
b.Navigation("Route");
|
b.Navigation("Route");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.RouteAddressDetails", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Server.Models.RouteAddress", "RouteAddress")
|
||||||
|
.WithMany("RouteAddressDetails")
|
||||||
|
.HasForeignKey("RouteAddressId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
|
||||||
|
.WithMany("RouteAddressDetails")
|
||||||
|
.HasForeignKey("VehicleEnrollmentId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("RouteAddress");
|
||||||
|
|
||||||
|
b.Navigation("VehicleEnrollment");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Server.Models.State", b =>
|
modelBuilder.Entity("Server.Models.State", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Server.Models.Country", "Country")
|
b.HasOne("Server.Models.Country", "Country")
|
||||||
@ -824,6 +872,11 @@ namespace Server.Migrations
|
|||||||
b.Navigation("VehicleEnrollments");
|
b.Navigation("VehicleEnrollments");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Server.Models.RouteAddress", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("RouteAddressDetails");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Server.Models.State", b =>
|
modelBuilder.Entity("Server.Models.State", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Cities");
|
b.Navigation("Cities");
|
||||||
@ -850,6 +903,8 @@ namespace Server.Migrations
|
|||||||
{
|
{
|
||||||
b.Navigation("Reviews");
|
b.Navigation("Reviews");
|
||||||
|
|
||||||
|
b.Navigation("RouteAddressDetails");
|
||||||
|
|
||||||
b.Navigation("Tickets");
|
b.Navigation("Tickets");
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
|
@ -10,18 +10,25 @@ public class Address
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
public double Latitude { get; set; }
|
public double Latitude { get; set; }
|
||||||
public double Longitude { get; set; }
|
public double Longitude { get; set; }
|
||||||
|
|
||||||
[ForeignKey("CityId")]
|
[ForeignKey("CityId")]
|
||||||
public int CityId { get; set; }
|
public int CityId { get; set; }
|
||||||
public City? City { get; set; }
|
public City City { get; set; } = null!;
|
||||||
|
|
||||||
public virtual IList<RouteAddress> RouteAddresses { get; set; } = null!;
|
public virtual IList<RouteAddress> RouteAddresses { get; set; } = null!;
|
||||||
|
|
||||||
public override string ToString()
|
public string GetFullName()
|
||||||
{
|
{
|
||||||
return $"{City.State.Country.Name}, {City.State.Name}, " +
|
if (City == null || City.State == null || City.State.Country == null)
|
||||||
$"{City.Name}, {this.Name}";
|
{
|
||||||
|
throw new NullReferenceException(
|
||||||
|
$"Properties {nameof(City)}, {nameof(City.State)}, " +
|
||||||
|
$"{nameof(City.State.Country)} must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{City.GetFullName()}, {Name}";
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,10 +10,23 @@ public class City
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
public virtual IList<Address>? Addresses { get; set; }
|
public virtual IList<Address>? Addresses { get; set; }
|
||||||
|
|
||||||
[ForeignKey("StateId")]
|
[ForeignKey("StateId")]
|
||||||
public int StateId { get; set; }
|
public int StateId { get; set; }
|
||||||
public State? State { get; set; }
|
|
||||||
|
public State State { get; set; } = null!;
|
||||||
|
|
||||||
|
public string GetFullName()
|
||||||
|
{
|
||||||
|
if (State == null || State.Country == null)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException(
|
||||||
|
$"Properties {nameof(State)}, " +
|
||||||
|
$"{nameof(State.Country)} must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{State.GetFullName()}, {Name}";
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using SharedModels.DataTransferObjects;
|
using SharedModels.DataTransferObjects;
|
||||||
|
|
||||||
namespace Server.Models;
|
namespace Server.Models;
|
||||||
@ -12,4 +13,9 @@ public class Country
|
|||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
public virtual IList<State> States { get; set; } = null!;
|
public virtual IList<State> States { get; set; } = null!;
|
||||||
|
|
||||||
|
public string GetFullName()
|
||||||
|
{
|
||||||
|
return $"{Name}";
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,8 +16,9 @@ public class RouteAddress
|
|||||||
public int AddressId { get; set; }
|
public int AddressId { get; set; }
|
||||||
public Address Address { get; set; } = null!;
|
public Address Address { get; set; } = null!;
|
||||||
|
|
||||||
|
[ForeignKey("RouteAddressDetailsId")]
|
||||||
|
public int RouteAddressDetailsId { get; set; }
|
||||||
|
public virtual IList<RouteAddressDetails> RouteAddressDetails { get; set; } = null!;
|
||||||
|
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
public TimeSpan TimeSpanToNextCity { get; set; }
|
|
||||||
public TimeSpan WaitTimeSpan { get; set; }
|
|
||||||
public double CostToNextCity { get; set; }
|
|
||||||
}
|
}
|
22
Server/Models/RouteAddressDetails.cs
Normal file
22
Server/Models/RouteAddressDetails.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Server.Models;
|
||||||
|
|
||||||
|
public class RouteAddressDetails
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("VehicleEnrollmentId")]
|
||||||
|
public int VehicleEnrollmentId { get; set; }
|
||||||
|
public VehicleEnrollment VehicleEnrollment { get; set; } = null!;
|
||||||
|
|
||||||
|
[ForeignKey("RouteAddressId")]
|
||||||
|
public int RouteAddressId { get; set; }
|
||||||
|
public RouteAddress RouteAddress { get; set; } = null!;
|
||||||
|
|
||||||
|
public TimeSpan TimeSpanToNextCity { get; set; }
|
||||||
|
public TimeSpan WaitTimeSpan { get; set; }
|
||||||
|
public double CostToNextCity { get; set; }
|
||||||
|
}
|
@ -10,10 +10,20 @@ public class State
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
public virtual IList<City> Cities { get; set; } = null!;
|
public virtual IList<City> Cities { get; set; } = null!;
|
||||||
|
|
||||||
[ForeignKey("CountryId")]
|
[ForeignKey("CountryId")]
|
||||||
public int CountryId { get; set; }
|
public int CountryId { get; set; }
|
||||||
public Country? Country { get; set; } = null!;
|
public Country Country { get; set; } = null!;
|
||||||
|
|
||||||
|
public string GetFullName()
|
||||||
|
{
|
||||||
|
if (Country == null)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException($"Property {nameof(Country)} must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{Country.GetFullName()}, {Name}";
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,6 +16,10 @@ public class VehicleEnrollment
|
|||||||
public int RouteId { get; set; }
|
public int RouteId { get; set; }
|
||||||
public Route Route { get; set; } = null!;
|
public Route Route { get; set; } = null!;
|
||||||
|
|
||||||
|
[ForeignKey("RouteAddressDetailsId")]
|
||||||
|
public int RouteAddressDetailsId { get; set; }
|
||||||
|
public virtual IList<RouteAddressDetails> RouteAddressDetails { get; set; } = null!;
|
||||||
|
|
||||||
public DateTime DepartureDateTimeUtc { get; set; }
|
public DateTime DepartureDateTimeUtc { get; set; }
|
||||||
|
|
||||||
public TimeSpan? DelayTimeSpan { get; set; }
|
public TimeSpan? DelayTimeSpan { get; set; }
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Dynamic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@ -105,7 +106,7 @@ builder.Services.AddScoped<IRouteManagementService, RouteManagementService>();
|
|||||||
builder.Services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
|
builder.Services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
|
||||||
|
|
||||||
builder.Services.AddScoped<IStatisticsService, StatisticsService>();
|
builder.Services.AddScoped<IStatisticsService, StatisticsService>();
|
||||||
|
builder.Services.AddScoped<IReportService, ReportService>();
|
||||||
|
|
||||||
builder.Services.AddScoped<ISortHelper<Country>, SortHelper<Country>>();
|
builder.Services.AddScoped<ISortHelper<Country>, SortHelper<Country>>();
|
||||||
builder.Services.AddScoped<ISortHelper<State>, SortHelper<State>>();
|
builder.Services.AddScoped<ISortHelper<State>, SortHelper<State>>();
|
||||||
@ -132,9 +133,15 @@ builder.Services.AddScoped<IDataShaper<VehicleEnrollment>, DataShaper<VehicleEnr
|
|||||||
builder.Services.AddScoped<IDataShaper<Route>, DataShaper<Route>>();
|
builder.Services.AddScoped<IDataShaper<Route>, DataShaper<Route>>();
|
||||||
builder.Services.AddScoped<IDataShaper<RouteAddress>, DataShaper<RouteAddress>>();
|
builder.Services.AddScoped<IDataShaper<RouteAddress>, DataShaper<RouteAddress>>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<ISortHelper<ExpandoObject>, SortHelper<ExpandoObject>>();
|
||||||
|
|
||||||
builder.Services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
|
builder.Services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
|
||||||
builder.Services.AddScoped<IDataShaper<CompanyDto>, DataShaper<CompanyDto>>();
|
builder.Services.AddScoped<IDataShaper<CompanyDto>, DataShaper<CompanyDto>>();
|
||||||
builder.Services.AddScoped<IDataShaper<AddressDto>, DataShaper<AddressDto>>();
|
builder.Services.AddScoped<IDataShaper<AddressDto>, DataShaper<AddressDto>>();
|
||||||
|
builder.Services.AddScoped<IDataShaper<RouteDto>, DataShaper<RouteDto>>();
|
||||||
|
builder.Services.AddScoped<IDataShaper<RouteWithAddressesDto>, DataShaper<RouteWithAddressesDto>>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IPager<ExpandoObject>, Pager<ExpandoObject>>();
|
||||||
|
|
||||||
// Adding DB Context with PostgreSQL
|
// Adding DB Context with PostgreSQL
|
||||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||||
|
@ -22,8 +22,12 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.10" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.10" />
|
||||||
|
<PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.41" />
|
||||||
|
<PackageReference Include="MigraDocCore.Rendering" Version="1.3.41" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.7" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.7" />
|
||||||
|
<PackageReference Include="PdfSharpCore" Version="1.3.41" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
|
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.1" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.1" />
|
||||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.20" />
|
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.20" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using System.Dynamic;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SharedModels.DataTransferObjects;
|
using SharedModels.DataTransferObjects;
|
||||||
using SharedModels.QueryParameters;
|
using SharedModels.QueryParameters;
|
||||||
using SharedModels.QueryParameters.Objects;
|
using SharedModels.QueryParameters.Objects;
|
||||||
@ -8,9 +10,13 @@ namespace Server.Services;
|
|||||||
public interface IRouteManagementService
|
public interface IRouteManagementService
|
||||||
{
|
{
|
||||||
Task<(bool isSucceed, string message, RouteDto route)> AddRoute(CreateRouteDto createRouteDto);
|
Task<(bool isSucceed, string message, RouteDto route)> AddRoute(CreateRouteDto createRouteDto);
|
||||||
Task<(bool isSucceed, string message, IEnumerable<RouteDto> routes,
|
Task<(bool isSucceed, IActionResult? actionResult, RouteWithAddressesDto route)> AddRouteWithAddresses(CreateRouteWithAddressesDto createRouteWithAddressesDto);
|
||||||
PagingMetadata<Route> pagingMetadata)> GetRoutes(RouteParameters parameters);
|
Task<(bool isSucceed, string message, IEnumerable<ExpandoObject> routes,
|
||||||
Task<(bool isSucceed, string message, RouteDto route)> GetRoute(int id, string? fields);
|
PagingMetadata<ExpandoObject> pagingMetadata)> GetRoutes(RouteParameters parameters);
|
||||||
|
Task<(bool isSucceed, IActionResult? actionResult, IEnumerable<ExpandoObject> routes,
|
||||||
|
PagingMetadata<ExpandoObject> pagingMetadata)> GetRoutesWithAddresses(RouteWithAddressesParameters parameters);
|
||||||
|
Task<(bool isSucceed, string message, ExpandoObject route)> GetRoute(int id, string? fields);
|
||||||
|
Task<(bool isSucceed, string message, ExpandoObject route)> GetRouteWithAddresses(int id, string? fields);
|
||||||
Task<(bool isSucceed, string message, UpdateRouteDto route)> UpdateRoute(UpdateRouteDto updateRouteDto);
|
Task<(bool isSucceed, string message, UpdateRouteDto route)> UpdateRoute(UpdateRouteDto updateRouteDto);
|
||||||
Task<(bool isSucceed, string message)> DeleteRoute(int id);
|
Task<(bool isSucceed, string message)> DeleteRoute(int id);
|
||||||
Task<bool> IsRouteExists(int id);
|
Task<bool> IsRouteExists(int id);
|
||||||
|
@ -26,6 +26,7 @@ public class ReportService : IReportService
|
|||||||
.ThenInclude(t => t.VehicleEnrollment)
|
.ThenInclude(t => t.VehicleEnrollment)
|
||||||
.ThenInclude(ve => ve.Vehicle)
|
.ThenInclude(ve => ve.Vehicle)
|
||||||
.ThenInclude(v => v.Company)
|
.ThenInclude(v => v.Company)
|
||||||
|
|
||||||
.Include(tg => tg.User)
|
.Include(tg => tg.User)
|
||||||
.Include(tg => tg.Tickets)
|
.Include(tg => tg.Tickets)
|
||||||
.ThenInclude(t => t.VehicleEnrollment)
|
.ThenInclude(t => t.VehicleEnrollment)
|
||||||
@ -35,6 +36,12 @@ public class ReportService : IReportService
|
|||||||
.ThenInclude(a => a.City)
|
.ThenInclude(a => a.City)
|
||||||
.ThenInclude(c => c.State)
|
.ThenInclude(c => c.State)
|
||||||
.ThenInclude(s => s.Country)
|
.ThenInclude(s => s.Country)
|
||||||
|
|
||||||
|
.Include(tg => tg.User)
|
||||||
|
.Include(tg => tg.Tickets)
|
||||||
|
.ThenInclude(t => t.VehicleEnrollment)
|
||||||
|
.ThenInclude(ve => ve.RouteAddressDetails)
|
||||||
|
|
||||||
.FirstOrDefaultAsync(tg => tg.Id == ticketGroupId);
|
.FirstOrDefaultAsync(tg => tg.Id == ticketGroupId);
|
||||||
|
|
||||||
// Define document
|
// Define document
|
||||||
@ -374,13 +381,16 @@ public class ReportService : IReportService
|
|||||||
|
|
||||||
foreach (var routeAddress in routeAddresses)
|
foreach (var routeAddress in routeAddresses)
|
||||||
{
|
{
|
||||||
|
var details = routeAddress.RouteAddressDetails
|
||||||
|
.First(rad => rad.RouteAddressId == routeAddress.Id);
|
||||||
|
|
||||||
if (routeAddress.AddressId == ticket.FirstRouteAddressId)
|
if (routeAddress.AddressId == ticket.FirstRouteAddressId)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
departureDateTimeUtc += routeAddress.TimeSpanToNextCity;
|
departureDateTimeUtc += details.TimeSpanToNextCity;
|
||||||
departureDateTimeUtc += routeAddress.WaitTimeSpan;
|
departureDateTimeUtc += details.WaitTimeSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
return departureDateTimeUtc;
|
return departureDateTimeUtc;
|
||||||
@ -395,12 +405,15 @@ public class ReportService : IReportService
|
|||||||
|
|
||||||
foreach (var routeAddress in routeAddresses)
|
foreach (var routeAddress in routeAddresses)
|
||||||
{
|
{
|
||||||
|
var details = routeAddress.RouteAddressDetails
|
||||||
|
.First(rad => rad.RouteAddressId == routeAddress.Id);
|
||||||
|
|
||||||
if (routeAddress.AddressId == ticket.LastRouteAddressId)
|
if (routeAddress.AddressId == ticket.LastRouteAddressId)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
arrivalDateTimeUtc += routeAddress.TimeSpanToNextCity;
|
arrivalDateTimeUtc += details.TimeSpanToNextCity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return arrivalDateTimeUtc;
|
return arrivalDateTimeUtc;
|
||||||
@ -432,7 +445,10 @@ public class ReportService : IReportService
|
|||||||
|
|
||||||
foreach (var routeAddress in routeAddresses)
|
foreach (var routeAddress in routeAddresses)
|
||||||
{
|
{
|
||||||
cost += routeAddress.CostToNextCity;
|
var details = routeAddress.RouteAddressDetails
|
||||||
|
.First(rad => rad.RouteAddressId == routeAddress.Id);
|
||||||
|
|
||||||
|
cost += details.CostToNextCity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
using System.Dynamic;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using AutoMapper.QueryableExtensions;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Server.Data;
|
using Server.Data;
|
||||||
using Server.Helpers;
|
using Server.Helpers;
|
||||||
@ -13,17 +16,23 @@ public class RouteManagementService : IRouteManagementService
|
|||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _dbContext;
|
private readonly ApplicationDbContext _dbContext;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private readonly ISortHelper<Route> _routeSortHelper;
|
private readonly ISortHelper<ExpandoObject> _routeSortHelper;
|
||||||
private readonly IDataShaper<Route> _routeDataShaper;
|
private readonly IDataShaper<RouteDto> _routeDataShaper;
|
||||||
|
private readonly IDataShaper<RouteWithAddressesDto> _routeWithAddressesDataShaper;
|
||||||
|
private readonly IPager<ExpandoObject> _pager;
|
||||||
|
|
||||||
public RouteManagementService(ApplicationDbContext dbContext,
|
public RouteManagementService(ApplicationDbContext dbContext,
|
||||||
IMapper mapper, ISortHelper<Route> routeSortHelper,
|
IMapper mapper, ISortHelper<ExpandoObject> routeSortHelper,
|
||||||
IDataShaper<Route> routeDataShaper)
|
IDataShaper<RouteDto> routeDataShaper,
|
||||||
|
IDataShaper<RouteWithAddressesDto> routeWithAddressesDataShaper,
|
||||||
|
IPager<ExpandoObject> pager)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
_dbContext = dbContext;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_routeSortHelper = routeSortHelper;
|
_routeSortHelper = routeSortHelper;
|
||||||
_routeDataShaper = routeDataShaper;
|
_routeDataShaper = routeDataShaper;
|
||||||
|
_routeWithAddressesDataShaper = routeWithAddressesDataShaper;
|
||||||
|
_pager = pager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, string message, RouteDto route)> AddRoute(CreateRouteDto createRouteDto)
|
public async Task<(bool isSucceed, string message, RouteDto route)> AddRoute(CreateRouteDto createRouteDto)
|
||||||
@ -36,8 +45,31 @@ public class RouteManagementService : IRouteManagementService
|
|||||||
return (true, String.Empty, _mapper.Map<RouteDto>(route));
|
return (true, String.Empty, _mapper.Map<RouteDto>(route));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, string message, IEnumerable<RouteDto> routes,
|
public async Task<(bool isSucceed, IActionResult? actionResult, RouteWithAddressesDto route)> AddRouteWithAddresses(CreateRouteWithAddressesDto createRouteWithAddressesDto)
|
||||||
PagingMetadata<Route> pagingMetadata)> GetRoutes(RouteParameters parameters)
|
{
|
||||||
|
var route = _mapper.Map<Route>(createRouteWithAddressesDto);
|
||||||
|
|
||||||
|
foreach (var routeAddress in route.RouteAddresses)
|
||||||
|
{
|
||||||
|
var dbAddress = await _dbContext.Addresses
|
||||||
|
.FirstOrDefaultAsync(a => a.Id == routeAddress.AddressId);
|
||||||
|
|
||||||
|
if (dbAddress == null)
|
||||||
|
{
|
||||||
|
return (false, new BadRequestObjectResult($"Address with Id = {routeAddress.AddressId} doesn't exist"), null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
routeAddress.Address = dbAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _dbContext.Routes.AddAsync(route);
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
|
||||||
|
return (true, null, _mapper.Map<RouteWithAddressesDto>(route));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, string message, IEnumerable<ExpandoObject> routes,
|
||||||
|
PagingMetadata<ExpandoObject> pagingMetadata)> GetRoutes(RouteParameters parameters)
|
||||||
{
|
{
|
||||||
var dbRoutes = _dbContext.Routes
|
var dbRoutes = _dbContext.Routes
|
||||||
.AsQueryable();
|
.AsQueryable();
|
||||||
@ -45,9 +77,12 @@ public class RouteManagementService : IRouteManagementService
|
|||||||
SearchByAllRouteFields(ref dbRoutes, parameters.Search);
|
SearchByAllRouteFields(ref dbRoutes, parameters.Search);
|
||||||
FilterByRouteType(ref dbRoutes, parameters.Type);
|
FilterByRouteType(ref dbRoutes, parameters.Type);
|
||||||
|
|
||||||
|
var routeDtos = _mapper.ProjectTo<RouteDto>(dbRoutes);
|
||||||
|
var shapedData = _routeDataShaper.ShapeData(routeDtos, parameters.Fields).AsQueryable();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dbRoutes = _routeSortHelper.ApplySort(dbRoutes, parameters.Sort);
|
shapedData = _routeSortHelper.ApplySort(shapedData, parameters.Sort);
|
||||||
|
|
||||||
// By calling Any() we will check if LINQ to Entities Query will be
|
// By calling Any() we will check if LINQ to Entities Query will be
|
||||||
// executed. If not it will throw an InvalidOperationException exception
|
// executed. If not it will throw an InvalidOperationException exception
|
||||||
@ -57,14 +92,11 @@ public class RouteManagementService : IRouteManagementService
|
|||||||
{
|
{
|
||||||
return (false, "Invalid sorting string", null, null)!;
|
return (false, "Invalid sorting string", null, null)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pagingMetadata = ApplyPaging(ref dbRoutes, parameters.PageNumber,
|
|
||||||
parameters.PageSize);
|
|
||||||
|
|
||||||
var shapedRoutesData = _routeDataShaper.ShapeData(dbRoutes, parameters.Fields);
|
|
||||||
var routeDtos = shapedRoutesData.ToList().ConvertAll(r => _mapper.Map<RouteDto>(r));
|
|
||||||
|
|
||||||
return (true, "", routeDtos, pagingMetadata);
|
var pagingMetadata = _pager.ApplyPaging(ref shapedData, parameters.PageNumber,
|
||||||
|
parameters.PageSize);
|
||||||
|
|
||||||
|
return (true, "", shapedData, pagingMetadata);
|
||||||
|
|
||||||
void SearchByAllRouteFields(ref IQueryable<Route> route,
|
void SearchByAllRouteFields(ref IQueryable<Route> route,
|
||||||
string? search)
|
string? search)
|
||||||
@ -88,23 +120,100 @@ public class RouteManagementService : IRouteManagementService
|
|||||||
|
|
||||||
routes = routes.Where(r => r.Type == type);
|
routes = routes.Where(r => r.Type == type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult? actionResult, IEnumerable<ExpandoObject> routes,
|
||||||
|
PagingMetadata<ExpandoObject> pagingMetadata)> GetRoutesWithAddresses(RouteWithAddressesParameters parameters)
|
||||||
|
{
|
||||||
|
var dbRoutes = _dbContext.Routes
|
||||||
|
.Include(r => r.RouteAddresses.OrderBy(ra => ra.Order))
|
||||||
|
.ThenInclude(ra => ra.Address).ThenInclude(a => a.City)
|
||||||
|
.ThenInclude(c => c.State).ThenInclude(s => s.Country)
|
||||||
|
.AsQueryable();
|
||||||
|
|
||||||
|
SearchByAllRouteFields(ref dbRoutes, parameters.Search);
|
||||||
|
FilterByRouteType(ref dbRoutes, parameters.Type);
|
||||||
|
FilterByFromAddressName(ref dbRoutes, parameters.FromAddressName);
|
||||||
|
FilterByToAddressName(ref dbRoutes, parameters.ToAddressName);
|
||||||
|
|
||||||
|
var routeDtos = _mapper.ProjectTo<RouteWithAddressesDto>(dbRoutes);
|
||||||
|
var shapedData = _routeWithAddressesDataShaper.ShapeData(routeDtos, parameters.Fields).AsQueryable();
|
||||||
|
|
||||||
|
try
|
||||||
PagingMetadata<Route> ApplyPaging(ref IQueryable<Route> routes,
|
|
||||||
int pageNumber, int pageSize)
|
|
||||||
{
|
{
|
||||||
var metadata = new PagingMetadata<Route>(routes,
|
shapedData = _routeSortHelper.ApplySort(shapedData, parameters.Sort);
|
||||||
pageNumber, pageSize);
|
}
|
||||||
|
catch (Exception e)
|
||||||
routes = routes
|
{
|
||||||
.Skip((pageNumber - 1) * pageSize)
|
return (false, new BadRequestObjectResult("Invalid sorting string"), null, null)!;
|
||||||
.Take(pageSize);
|
}
|
||||||
|
|
||||||
|
var pagingMetadata = _pager.ApplyPaging(ref shapedData, parameters.PageNumber,
|
||||||
|
parameters.PageSize);
|
||||||
|
|
||||||
return metadata;
|
return (true, null, shapedData, pagingMetadata);
|
||||||
|
|
||||||
|
void SearchByAllRouteFields(ref IQueryable<Route> route,
|
||||||
|
string? search)
|
||||||
|
{
|
||||||
|
if (!route.Any() || String.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Optimize (remove client evaluation)
|
||||||
|
route = route.ToArray().Where(r =>
|
||||||
|
r.Type.ToLower().Contains(search.ToLower()) ||
|
||||||
|
r.RouteAddresses.OrderBy(ra => ra.Order).First().Address
|
||||||
|
.GetFullName().ToLower().Contains(search.ToLower()) ||
|
||||||
|
r.RouteAddresses.OrderBy(ra => ra.Order).Last().Address
|
||||||
|
.GetFullName().ToLower().Contains(search.ToLower()))
|
||||||
|
.AsQueryable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterByRouteType(ref IQueryable<Route> routes,
|
||||||
|
string? type)
|
||||||
|
{
|
||||||
|
if (!routes.Any() || String.IsNullOrWhiteSpace(type))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
routes = routes.Where(r => r.Type.ToLower().Contains(type.ToLower()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterByFromAddressName(ref IQueryable<Route> routes,
|
||||||
|
string? addressName)
|
||||||
|
{
|
||||||
|
if (!routes.Any() || String.IsNullOrWhiteSpace(addressName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Optimize (remove client evaluation)
|
||||||
|
routes = routes.ToArray().Where(r =>
|
||||||
|
r.RouteAddresses.First().Address
|
||||||
|
.GetFullName().ToLower().Contains(addressName.ToLower()))
|
||||||
|
.AsQueryable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterByToAddressName(ref IQueryable<Route> routes,
|
||||||
|
string? addressName)
|
||||||
|
{
|
||||||
|
if (!routes.Any() || String.IsNullOrWhiteSpace(addressName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Optimize (remove client evaluation)
|
||||||
|
routes = routes.ToArray().Where(r =>
|
||||||
|
r.RouteAddresses.Last().Address.
|
||||||
|
GetFullName().ToLower().Contains(addressName.ToLower()))
|
||||||
|
.AsQueryable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, string message, RouteDto route)> GetRoute(int id, string? fields)
|
public async Task<(bool isSucceed, string message, ExpandoObject route)> GetRoute(int id, string? fields)
|
||||||
{
|
{
|
||||||
var dbRoute = await _dbContext.Routes.Where(r => r.Id == id)
|
var dbRoute = await _dbContext.Routes.Where(r => r.Id == id)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
@ -119,10 +228,33 @@ public class RouteManagementService : IRouteManagementService
|
|||||||
fields = RouteParameters.DefaultFields;
|
fields = RouteParameters.DefaultFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
var shapedRouteData = _routeDataShaper.ShapeData(dbRoute, fields);
|
var routeDto = _mapper.Map<RouteDto>(dbRoute);
|
||||||
var routeDto = _mapper.Map<RouteDto>(shapedRouteData);
|
var shapedRouteData = _routeDataShaper.ShapeData(routeDto, fields);
|
||||||
|
|
||||||
return (true, "", routeDto);
|
return (true, "", shapedRouteData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, string message, ExpandoObject route)> GetRouteWithAddresses(int id, string? fields)
|
||||||
|
{
|
||||||
|
var dbRoute = await _dbContext.Routes.Where(r => r.Id == id)
|
||||||
|
.Include(r => r.RouteAddresses).ThenInclude(ra => ra.Address)
|
||||||
|
.ThenInclude(a => a.City).ThenInclude(c => c.State)
|
||||||
|
.ThenInclude(s => s.Country).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (dbRoute == null)
|
||||||
|
{
|
||||||
|
return (false, $"Route doesn't exist", null)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrWhiteSpace(fields))
|
||||||
|
{
|
||||||
|
fields = RouteWithAddressesParameters.DefaultFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
var routeDto = _mapper.Map<RouteWithAddressesDto>(dbRoute);
|
||||||
|
var shapedRouteData = _routeDataShaper.ShapeData(routeDto, fields);
|
||||||
|
|
||||||
|
return (true, "", shapedRouteData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, string message, UpdateRouteDto route)> UpdateRoute(UpdateRouteDto updateRouteDto)
|
public async Task<(bool isSucceed, string message, UpdateRouteDto route)> UpdateRoute(UpdateRouteDto updateRouteDto)
|
||||||
|
@ -44,6 +44,8 @@ public class StateManagementService : IStateManagementService
|
|||||||
.Include(s => s.Cities)
|
.Include(s => s.Cities)
|
||||||
.ThenInclude(c => c.Addresses).AsQueryable();
|
.ThenInclude(c => c.Addresses).AsQueryable();
|
||||||
|
|
||||||
|
var s = dbStates.ToList().ConvertAll(s => _mapper.Map<StateDto>(s));
|
||||||
|
|
||||||
SearchByAllStateFields(ref dbStates, parameters.Search);
|
SearchByAllStateFields(ref dbStates, parameters.Search);
|
||||||
FilterByStateName(ref dbStates, parameters.Name);
|
FilterByStateName(ref dbStates, parameters.Name);
|
||||||
FilterByCountryId(ref dbStates, parameters.CountryId);
|
FilterByCountryId(ref dbStates, parameters.CountryId);
|
||||||
|
@ -17,16 +17,18 @@ public class StatisticsService : IStatisticsService
|
|||||||
private readonly IDataShaper<UserDto> _userDataShaper;
|
private readonly IDataShaper<UserDto> _userDataShaper;
|
||||||
private readonly IDataShaper<CompanyDto> _companyDataShaper;
|
private readonly IDataShaper<CompanyDto> _companyDataShaper;
|
||||||
private readonly IDataShaper<AddressDto> _addressDataShaper;
|
private readonly IDataShaper<AddressDto> _addressDataShaper;
|
||||||
|
private readonly IPager<ExpandoObject> _pager;
|
||||||
|
|
||||||
public StatisticsService(ApplicationDbContext dbContext, IMapper mapper,
|
public StatisticsService(ApplicationDbContext dbContext, IMapper mapper,
|
||||||
IDataShaper<UserDto> userDataShaper, IDataShaper<CompanyDto> companyDataShaper,
|
IDataShaper<UserDto> userDataShaper, IDataShaper<CompanyDto> companyDataShaper,
|
||||||
IDataShaper<AddressDto> addressDataShaper)
|
IDataShaper<AddressDto> addressDataShaper, IPager<ExpandoObject> pager)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
_dbContext = dbContext;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_userDataShaper = userDataShaper;
|
_userDataShaper = userDataShaper;
|
||||||
_companyDataShaper = companyDataShaper;
|
_companyDataShaper = companyDataShaper;
|
||||||
_addressDataShaper = addressDataShaper;
|
_addressDataShaper = addressDataShaper;
|
||||||
|
_pager = pager;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Popularity is measured in number of purchased tickets
|
// Popularity is measured in number of purchased tickets
|
||||||
@ -76,8 +78,8 @@ public class StatisticsService : IStatisticsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var shapedData = shapedDataArray.AsQueryable();
|
var shapedData = shapedDataArray.AsQueryable();
|
||||||
var pagingMetadata = ApplyPaging(ref shapedData, parameters.PageNumber,
|
var pagingMetadata = _pager.ApplyPaging(ref shapedData,
|
||||||
parameters.PageSize);
|
parameters.PageNumber, parameters.PageSize);
|
||||||
shapedDataArray = shapedData.ToArray();
|
shapedDataArray = shapedData.ToArray();
|
||||||
|
|
||||||
return (true, null, shapedDataArray, pagingMetadata);
|
return (true, null, shapedDataArray, pagingMetadata);
|
||||||
@ -166,8 +168,8 @@ public class StatisticsService : IStatisticsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var shapedData = shapedDataArray.AsQueryable();
|
var shapedData = shapedDataArray.AsQueryable();
|
||||||
var pagingMetadata = ApplyPaging(ref shapedData, parameters.PageNumber,
|
var pagingMetadata = _pager.ApplyPaging(ref shapedData,
|
||||||
parameters.PageSize);
|
parameters.PageNumber, parameters.PageSize);
|
||||||
shapedDataArray = shapedData.ToArray();
|
shapedDataArray = shapedData.ToArray();
|
||||||
|
|
||||||
return (true, null, shapedDataArray, pagingMetadata);
|
return (true, null, shapedDataArray, pagingMetadata);
|
||||||
@ -265,23 +267,10 @@ public class StatisticsService : IStatisticsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var shapedData = shapedDataArray.AsQueryable();
|
var shapedData = shapedDataArray.AsQueryable();
|
||||||
var pagingMetadata = ApplyPaging(ref shapedData, parameters.PageNumber,
|
var pagingMetadata = _pager.ApplyPaging(ref shapedData,
|
||||||
parameters.PageSize);
|
parameters.PageNumber, parameters.PageSize);
|
||||||
shapedDataArray = shapedData.ToArray();
|
shapedDataArray = shapedData.ToArray();
|
||||||
|
|
||||||
return (true, null, shapedDataArray, pagingMetadata);
|
return (true, null, shapedDataArray, pagingMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -5,8 +5,7 @@ namespace SharedModels.DataTransferObjects;
|
|||||||
public class AddressDto : CreateAddressDto
|
public class AddressDto : CreateAddressDto
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
public string FullName = null!;
|
||||||
public InAddressCityDto City { get; set; } = null!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CreateAddressDto
|
public class CreateAddressDto
|
||||||
@ -37,4 +36,25 @@ public class InCityAddressDto
|
|||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
public double Latitude { get; set; }
|
public double Latitude { get; set; }
|
||||||
public double Longitude { get; set; }
|
public double Longitude { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateAddressInRouteAddress
|
||||||
|
{
|
||||||
|
public int? Id { get; set; }
|
||||||
|
|
||||||
|
[StringLength(maximumLength: 250, ErrorMessage = "Address name is too long")]
|
||||||
|
public string? Name { get; set; } = null!;
|
||||||
|
|
||||||
|
[Range(-90, 90, ErrorMessage = "Latitude must be in range(-90, 90)")]
|
||||||
|
public double? Latitude { get; set; }
|
||||||
|
|
||||||
|
[Range(-180, 180, ErrorMessage = "Longitude must be in range(-180, 180)")]
|
||||||
|
public double? Longitude { get; set; }
|
||||||
|
|
||||||
|
public int? CityId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddressInRouteAddress : CreateAddressInRouteAddress
|
||||||
|
{
|
||||||
|
public string FullName = null!;
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ public class CityDto : CreateCityDto
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public InCityStateDto State { get; set; } = null!;
|
public string FullName = null!;
|
||||||
|
|
||||||
public virtual IList<InCityAddressDto>? Addresses { get; set; }
|
public virtual IList<InCityAddressDto>? Addresses { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -16,19 +16,8 @@ public class CreateRouteAddressDto
|
|||||||
public int AddressId { get; set; }
|
public int AddressId { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
|
[Range(0, Int32.MaxValue)]
|
||||||
public int Order { get; set; }
|
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; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateRouteAddressDto : CreateRouteAddressDto
|
public class UpdateRouteAddressDto : CreateRouteAddressDto
|
||||||
@ -39,21 +28,16 @@ public class UpdateRouteAddressDto : CreateRouteAddressDto
|
|||||||
|
|
||||||
public class CreateRouteAddressWithAddressDto
|
public class CreateRouteAddressWithAddressDto
|
||||||
{
|
{
|
||||||
|
[Range(0, Int32.MaxValue)]
|
||||||
|
public int Order { get; set; }
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
|
public CreateAddressInRouteAddress Address { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RouteAddressWithAddressDto
|
||||||
|
{
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
|
|
||||||
[Required]
|
public AddressInRouteAddress Address { get; set; } = null!;
|
||||||
[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!;
|
|
||||||
}
|
}
|
@ -24,4 +24,9 @@ public class CreateRouteWithAddressesDto : CreateRouteDto
|
|||||||
[Required]
|
[Required]
|
||||||
[MinLength(2)]
|
[MinLength(2)]
|
||||||
public IList<CreateRouteAddressWithAddressDto> RouteAddresses { get; set; } = null!;
|
public IList<CreateRouteAddressWithAddressDto> RouteAddresses { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RouteWithAddressesDto : RouteDto
|
||||||
|
{
|
||||||
|
public IList<RouteAddressWithAddressDto> RouteAddresses { get; set; } = null!;
|
||||||
}
|
}
|
@ -5,7 +5,8 @@ namespace SharedModels.DataTransferObjects;
|
|||||||
public class StateDto : CreateStateDto
|
public class StateDto : CreateStateDto
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public InStateCountryDto Country { get; set; } = null!;
|
|
||||||
|
public string FullName = null!;
|
||||||
|
|
||||||
public virtual IList<InStateCityDto> Cities { get; set; } = null!;
|
public virtual IList<InStateCityDto> Cities { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
namespace SharedModels.QueryParameters.Objects;
|
||||||
|
|
||||||
|
public class RouteWithAddressesParameters : ParametersBase
|
||||||
|
{
|
||||||
|
public const string DefaultFields = "id,type,routeAddresses";
|
||||||
|
|
||||||
|
public RouteWithAddressesParameters()
|
||||||
|
{
|
||||||
|
Fields = DefaultFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? Type { get; set; }
|
||||||
|
public string? FromAddressName { get; set; }
|
||||||
|
public string? ToAddressName { get; set; }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user