nonatomic commit. check description for the list of changes

feat: add UserManagementService

feat: add CopmanyDriver relation and DriverManagementService

chore: pupulate database seeding class

fix: add review filtering by CompanyId
This commit is contained in:
cuqmbr 2023-05-02 14:57:46 +03:00
parent ceaba3eb2d
commit a75ea56f69
35 changed files with 3220 additions and 93 deletions

View File

@ -1,3 +1,4 @@
using System.Dynamic;
using AutoMapper;
using Server.Models;
using SharedModels.DataTransferObjects;
@ -86,6 +87,12 @@ public class MapperInitializer : Profile
CreateMap<User, UserDto>().ReverseMap();
CreateMap<User, CreateUserDto>().ReverseMap();
CreateMap<User, UpdateUserDto>().ReverseMap();
CreateMap<User, StrippedUserDto>().ReverseMap();
CreateMap<User, DriverDto>().ForMember(d => d.CompanyId, o => o.MapFrom(s => s.Employer.CompanyId));
CreateMap<UserDto, DriverDto>().ReverseMap();
CreateMap<CreateUserDto, CreateDriverDto>().ReverseMap();
CreateMap<CreateDriverDto, UpdateDriverDto>().ReverseMap();
CreateMap<RouteAddressDetails, RouteAddressDetailsDto>().ReverseMap();
CreateMap<RouteAddressDetails, CreateRouteAddressDetailsDto>().ReverseMap();

View File

@ -3,7 +3,7 @@ namespace Server.Configurations;
public class SmtpCredentials
{
public string Host { get; set; } = null!;
public string Port { get; set; }
public int Port { get; set; }
public string User { get; set; } = null!;
public string Password { get; set; } = null!;
}

View File

@ -0,0 +1,86 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryParameters.Objects;
namespace Server.Controllers;
[Route("api/drivers")]
[ApiController]
public class DriverController : ControllerBase
{
private readonly IDriverManagementService _driverManagementService;
public DriverController(IDriverManagementService driverManagementService)
{
_driverManagementService = driverManagementService;
}
[HttpPost]
public async Task<IActionResult> AddDriver(CreateDriverDto Driver)
{
var result = await _driverManagementService.AddDriver(Driver);
if (!result.isSucceeded)
{
return result.actionResult;
}
return CreatedAtAction(nameof(GetDriver), new {id = result.driver.Id}, result.driver);
}
[HttpGet]
public async Task<IActionResult> GetDrivers([FromQuery] CompanyDriverParameters parameters)
{
var result = await _driverManagementService.GetDrivers(parameters);
if (!result.isSucceeded)
{
return result.actionResult;
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.drivers);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetDriver(string id, [FromQuery] string? fields)
{
var result = await _driverManagementService.GetDriver(id, fields);
if (!result.isSucceeded)
{
return result.actionResult;
}
return Ok(result.driver);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateDriver(string id, UpdateDriverDto driver)
{
var result = await _driverManagementService.UpdateDriver(id, driver);
if (!result.isSucceeded)
{
return result.actionResult;
}
return Ok(result.driver);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteDriver(string id)
{
var result = await _driverManagementService.DeleteDriver(id);
if (!result.isSucceed)
{
return result.actionResult;
}
return NoContent();
}
}

View File

@ -0,0 +1,86 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryParameters.Objects;
namespace Server.Controllers;
[Route("api/users")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserManagementService _userManagementService;
public UserController(IUserManagementService userManagementService)
{
_userManagementService = userManagementService;
}
[HttpPost]
public async Task<IActionResult> AddUser(CreateUserDto User)
{
var result = await _userManagementService.AddUser(User);
if (!result.isSucceeded)
{
return result.actionResult;
}
return CreatedAtAction(nameof(GetUser), new {id = result.user.Id}, result.user);
}
[HttpGet]
public async Task<IActionResult> GetUsers([FromQuery] UserParameters parameters)
{
var result = await _userManagementService.GetUsers(parameters);
if (!result.isSucceeded)
{
return result.actionResult;
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.users);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(string id, [FromQuery] string? fields)
{
var result = await _userManagementService.GetUser(id, fields);
if (!result.isSucceeded)
{
return result.actionResult;
}
return Ok(result.user);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(string id, UpdateUserDto user)
{
var result = await _userManagementService.UpdateUser(id, user);
if (!result.isSucceeded)
{
return result.actionResult;
}
return Ok(result.user);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(string id)
{
var result = await _userManagementService.DeleteUser(id);
if (!result.isSucceed)
{
return result.actionResult;
}
return NoContent();
}
}

View File

@ -12,12 +12,16 @@ public class ApplicationDbContext : IdentityDbContext<User>
{
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Ignore(u => u.UserName).Ignore(u => u.NormalizedUserName);
modelBuilder.Entity<CompanyDriver>().HasKey(cd => new { cd.CompanyId, cd.DriverId });
}
public DbSet<Company> Companies { get; set; } = null!;
public DbSet<CompanyDriver> CompanyDrivers { get; set; } = null!;
public DbSet<Vehicle> Vehicles { get; set; } = null!;
public DbSet<VehicleEnrollment> VehicleEnrollments { get; set; } = null!;
public DbSet<Route> Routes { get; set; } = null!;

View File

@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Identity;
using Server.Models;
using Utils;
using Route = Server.Models.Route;
namespace Server.Data;
@ -8,25 +10,314 @@ public class SeedData
public static async Task Initialize(IServiceProvider serviceProvider)
{
var userManager = (UserManager<User>)serviceProvider.GetService(typeof(UserManager<User>))!;
var roleManager = (RoleManager<IdentityRole>)serviceProvider.GetService(typeof(RoleManager<IdentityRole>))!;
userManager.UserValidators.Clear();
//Seed Roles
foreach (var role in Enum.GetValues(typeof(Constants.Identity.Roles)))
var roleManager = (RoleManager<IdentityRole>)serviceProvider.GetService(typeof(RoleManager<IdentityRole>))!;
var dbContext = (ApplicationDbContext)serviceProvider.GetService(typeof(ApplicationDbContext))!;
// Seed Roles
foreach (var role in Enum.GetValues(typeof(Identity.Roles)))
{
await roleManager.CreateAsync(new IdentityRole(role.ToString()));
}
//Seed Default User
var defaultUser = new User
User? companyUser;
User driverUser;
if (!dbContext.Users.Any())
{
Email = Constants.Identity.DefaultEmail,
// Seed Administrator user
var adminUser = new User
{
FirstName = "user", LastName = "user", Patronymic = "user",
Email = "admin@autobus.com",
EmailConfirmed = true,
};
await userManager.CreateAsync(adminUser, Identity.DefaultPassword);
await userManager.AddToRoleAsync(adminUser, Identity.Roles.Administrator.ToString());
// Seed Company user
companyUser = new User
{
FirstName = "user", LastName = "user", Patronymic = "user",
Email = "company@autobus.com",
EmailConfirmed = true
};
if (userManager.Users.All(u => u.Id != defaultUser.Id))
await userManager.CreateAsync(companyUser, Identity.DefaultPassword);
await userManager.AddToRoleAsync(companyUser, Identity.Roles.Company.ToString());
// Seed Driver user
driverUser = new User
{
await userManager.CreateAsync(defaultUser, Constants.Identity.DefaultPassword);
await userManager.AddToRoleAsync(defaultUser, Constants.Identity.DefaultRole.ToString());
FirstName = "user", LastName = "user", Patronymic = "user",
Email = "driver@autobus.com",
EmailConfirmed = true
};
await userManager.CreateAsync(driverUser, Identity.DefaultPassword);
await userManager.AddToRoleAsync(driverUser, Identity.Roles.Driver.ToString());
// Seed Default user
var defaultUser = new User
{
FirstName = "user", LastName = "user", Patronymic = "user",
Email = "user@autobus.com",
EmailConfirmed = true
};
await userManager.CreateAsync(defaultUser, Identity.DefaultPassword);
await userManager.AddToRoleAsync(defaultUser, Identity.Roles.User.ToString());
}
companyUser = await userManager.FindByEmailAsync("company@autobus.com");
driverUser = await userManager.FindByEmailAsync("driver@autobus.com");
if (!dbContext.Companies.Any())
{
// Seed County - State - City - Address relations
await dbContext.Countries.AddRangeAsync(new Country { Name = "Ukraine", Code = "UA" });
await dbContext.SaveChangesAsync();
await dbContext.States.AddRangeAsync(new State { CountryId = 1, Name = "Kharkiv Oblast" });
await dbContext.SaveChangesAsync();
await dbContext.Cities.AddRangeAsync(new City { StateId = 1, Name = "Osykovyi Hai" },
new City { StateId = 1, Name = "Malynivka" },
new City { StateId = 1, Name = "Chuhuiv" },
new City { StateId = 1, Name = "Kam'yana Yaruha" },
new City { StateId = 1, Name = "Rohan'" },
new City { StateId = 1, Name = "Kharkiv" },
new City { StateId = 1, Name = "Korobochkyne" },
new City { StateId = 1, Name = "Kochetok" },
new City { StateId = 1, Name = "Kytsivka" });
await dbContext.SaveChangesAsync();
await dbContext.Addresses.AddRangeAsync(new Address { CityId = 1, Name = "station near E40 road", Latitude = 36.778044, Longitude = 49.777235 },
new Address { CityId = 2, Name = "v. Malynivka", Latitude = 36.732271, Longitude = 49.813638 },
new Address { CityId = 3, Name = "Chuhuyivsʹka Avtostantsiya, Vulytsya Kharkivsʹka, 133", Latitude = 36.687534, Longitude = 49.838337 },
new Address { CityId = 4, Name = "Kulynychi", Latitude = 36.595877, Longitude = 49.880585 },
new Address { CityId = 5, Name = "v. Rohan", Latitude = 36.495910, Longitude = 49.907080 },
new Address { CityId = 6, Name = "Kharkiv Parking Near Mcdonalds", Latitude = 36.207202, Longitude = 49.987560 },
new Address { CityId = 7, Name = "Ukrposhta 63540, Chuhuivs'ka St, 2Б", Latitude = 36.812743, Longitude = 49.776519 },
new Address { CityId = 8, Name = "Pivnyk", Latitude = 36.712386, Longitude = 49.867814 },
new Address { CityId = 9, Name = "v. Kytsivka", Latitude = 36.819010, Longitude = 49.869401 });
await dbContext.SaveChangesAsync();
// Seed Route - RouteAddresses relations
await dbContext.Routes.AddRangeAsync(
new Route
{
Type = "default",
RouteAddresses = new List<RouteAddress>
{
new RouteAddress { Order = 1, AddressId = 1},
new RouteAddress { Order = 2, AddressId = 2},
new RouteAddress { Order = 3, AddressId = 3},
new RouteAddress { Order = 4, AddressId = 4},
new RouteAddress { Order = 5, AddressId = 5},
new RouteAddress { Order = 6, AddressId = 6},
}
},
new Route
{
Type = "default",
RouteAddresses = new List<RouteAddress>
{
new RouteAddress { Order = 1, AddressId = 7},
new RouteAddress { Order = 2, AddressId = 2},
new RouteAddress { Order = 3, AddressId = 3},
new RouteAddress { Order = 4, AddressId = 8},
new RouteAddress { Order = 5, AddressId = 9},
}
});
await dbContext.SaveChangesAsync();
await dbContext.Companies.AddAsync(
new Company
{
OwnerId = companyUser.Id,
Name = "Default Company",
CompanyDrivers = new []
{
new CompanyDriver
{
DriverId = driverUser.Id
}
}
});
await dbContext.SaveChangesAsync();
await dbContext.Vehicles.AddRangeAsync(
new Vehicle
{
Number = "AC8376BH",
Type = "Cruiser",
Capacity = 50,
CompanyId = 1,
HasClimateControl = true,
HasWiFi = true,
HasWC = true,
HasStewardess = true,
HasTV = false,
HasOutlet = true,
HasBelts = true,
},
new Vehicle
{
Number = "HA8934MK",
Type = "Lon Rider",
Capacity = 25,
CompanyId = 1,
HasClimateControl = false,
HasWiFi = false,
HasWC = false,
HasStewardess = false,
HasTV = false,
HasOutlet = false,
HasBelts = false,
});
await dbContext.SaveChangesAsync();
await dbContext.VehicleEnrollments.AddRangeAsync(
new VehicleEnrollment
{
RouteId = 1,
VehicleId = 1,
DepartureDateTimeUtc = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, 07, 45, 00, DateTimeKind.Utc),
RouteAddressDetails = new List<RouteAddressDetails>
{
new RouteAddressDetails
{
RouteAddressId = 1,
TimeSpanToNextCity = TimeSpan.FromMinutes(20),
CostToNextCity = 25
},
new RouteAddressDetails
{
RouteAddressId = 2,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(15),
CostToNextCity = 20
},
new RouteAddressDetails
{
RouteAddressId = 3,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(25),
CostToNextCity = 30
},
new RouteAddressDetails
{
RouteAddressId = 4,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(20),
CostToNextCity = 35
},
new RouteAddressDetails
{
RouteAddressId = 5,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(30),
CostToNextCity = 40
},
new RouteAddressDetails
{
RouteAddressId = 6,
}
}
},
new VehicleEnrollment
{
RouteId = 2,
VehicleId = 2,
DepartureDateTimeUtc = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, 08, 00, 00, DateTimeKind.Utc),
RouteAddressDetails = new List<RouteAddressDetails>
{
new RouteAddressDetails
{
RouteAddressId = 7,
TimeSpanToNextCity = TimeSpan.FromMinutes(20),
CostToNextCity = 25
},
new RouteAddressDetails
{
RouteAddressId = 8,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(15),
CostToNextCity = 20
},
new RouteAddressDetails
{
RouteAddressId = 9,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(25),
CostToNextCity = 30
},
new RouteAddressDetails
{
RouteAddressId = 10,
TimeSpanToNextCity = TimeSpan.FromMinutes(5),
WaitTimeSpan = TimeSpan.FromMinutes(20),
CostToNextCity = 35
},
new RouteAddressDetails
{
RouteAddressId = 11,
}
}
});
await dbContext.SaveChangesAsync();
await dbContext.TicketGroups.AddAsync(
new TicketGroup
{
UserId = companyUser.Id,
Tickets = new List<Ticket>
{
new Ticket
{
VehicleEnrollmentId = 1,
PurchaseDateTimeUtc = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, 08, 00, 00, DateTimeKind.Utc).AddDays(-1),
FirstRouteAddressId = 1,
LastRouteAddressId = 2
},
new Ticket
{
VehicleEnrollmentId = 2,
PurchaseDateTimeUtc = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, 08, 00, 00, DateTimeKind.Utc).AddDays(-1),
FirstRouteAddressId = 2,
LastRouteAddressId = 9
}
}
});
dbContext.Reviews.AddRangeAsync(
new Review
{
UserId = companyUser.Id,
VehicleEnrollmentId = 1,
Rating = 85,
Comment = "Good overall",
PostDateTimeUtc = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, 08, 00, 00, DateTimeKind.Utc).AddDays(1),
}, new Review
{
UserId = companyUser.Id,
VehicleEnrollmentId = 2,
Rating = 100,
Comment = "Amazing",
PostDateTimeUtc = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day, 08, 00, 00, DateTimeKind.Utc).AddDays(1),
});
await dbContext.SaveChangesAsync();
}
}
}

View File

@ -0,0 +1,922 @@
// <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("20230430115750_Add_Gender_BirthDate_Document_DocumentDetail_fields_to_User_table")]
partial class Add_Gender_BirthDate_Document_DocumentDetail_fields_to_User_table
{
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")
.IsUnique();
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<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<int?>("Document")
.HasColumnType("integer");
b.Property<string>("DocumentDetails")
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.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>("PasswordHash")
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.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.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
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")
.WithOne("Company")
.HasForeignKey("Server.Models.Company", "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("Company")
.IsRequired();
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
}
}
}

View File

@ -0,0 +1,75 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Server.Migrations
{
public partial class Add_Gender_BirthDate_Document_DocumentDetail_fields_to_User_table : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Companies_OwnerId",
table: "Companies");
migrationBuilder.AddColumn<DateTime>(
name: "BirthDate",
table: "AspNetUsers",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "Document",
table: "AspNetUsers",
type: "integer",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "DocumentDetails",
table: "AspNetUsers",
type: "text",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "Gender",
table: "AspNetUsers",
type: "integer",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_Companies_OwnerId",
table: "Companies",
column: "OwnerId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Companies_OwnerId",
table: "Companies");
migrationBuilder.DropColumn(
name: "BirthDate",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Document",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "DocumentDetails",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Gender",
table: "AspNetUsers");
migrationBuilder.CreateIndex(
name: "IX_Companies_OwnerId",
table: "Companies",
column: "OwnerId");
}
}
}

View File

@ -0,0 +1,962 @@
// <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("20230501105408_Add_CompanyDriver_relation")]
partial class Add_CompanyDriver_relation
{
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")
.IsUnique();
b.ToTable("Companies");
});
modelBuilder.Entity("Server.Models.CompanyDriver", b =>
{
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<string>("DriverId")
.HasColumnType("text");
b.HasKey("CompanyId", "DriverId");
b.HasIndex("DriverId")
.IsUnique();
b.ToTable("CompanyDrivers");
});
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<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<int?>("Document")
.HasColumnType("integer");
b.Property<string>("DocumentDetails")
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.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>("PasswordHash")
.HasColumnType("text");
b.Property<string>("Patronymic")
.IsRequired()
.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.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
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")
.WithOne("Company")
.HasForeignKey("Server.Models.Company", "OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
});
modelBuilder.Entity("Server.Models.CompanyDriver", b =>
{
b.HasOne("Server.Models.Company", "Company")
.WithMany("CompanyDrivers")
.HasForeignKey("CompanyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.User", "Driver")
.WithOne("Employer")
.HasForeignKey("Server.Models.CompanyDriver", "DriverId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Company");
b.Navigation("Driver");
});
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("CompanyDrivers");
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("Company")
.IsRequired();
b.Navigation("Employer")
.IsRequired();
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
}
}
}

View File

@ -0,0 +1,48 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Server.Migrations
{
public partial class Add_CompanyDriver_relation : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CompanyDrivers",
columns: table => new
{
DriverId = table.Column<string>(type: "text", nullable: false),
CompanyId = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CompanyDrivers", x => new { x.CompanyId, x.DriverId });
table.ForeignKey(
name: "FK_CompanyDrivers_AspNetUsers_DriverId",
column: x => x.DriverId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CompanyDrivers_Companies_CompanyId",
column: x => x.CompanyId,
principalTable: "Companies",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_CompanyDrivers_DriverId",
table: "CompanyDrivers",
column: "DriverId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CompanyDrivers");
}
}
}

View File

@ -179,7 +179,7 @@ namespace Server.Migrations
b.HasIndex("CityId");
b.ToTable("Addresses");
b.ToTable("Addresses", (string)null);
});
modelBuilder.Entity("Server.Models.City", b =>
@ -201,7 +201,7 @@ namespace Server.Migrations
b.HasIndex("StateId");
b.ToTable("Cities");
b.ToTable("Cities", (string)null);
});
modelBuilder.Entity("Server.Models.Company", b =>
@ -222,9 +222,26 @@ namespace Server.Migrations
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("OwnerId")
.IsUnique();
b.ToTable("Companies");
b.ToTable("Companies", (string)null);
});
modelBuilder.Entity("Server.Models.CompanyDriver", b =>
{
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<string>("DriverId")
.HasColumnType("text");
b.HasKey("CompanyId", "DriverId");
b.HasIndex("DriverId")
.IsUnique();
b.ToTable("CompanyDrivers", (string)null);
});
modelBuilder.Entity("Server.Models.Country", b =>
@ -245,7 +262,7 @@ namespace Server.Migrations
b.HasKey("Id");
b.ToTable("Countries");
b.ToTable("Countries", (string)null);
});
modelBuilder.Entity("Server.Models.Review", b =>
@ -278,7 +295,7 @@ namespace Server.Migrations
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Reviews");
b.ToTable("Reviews", (string)null);
});
modelBuilder.Entity("Server.Models.Route", b =>
@ -295,7 +312,7 @@ namespace Server.Migrations
b.HasKey("Id");
b.ToTable("Routes");
b.ToTable("Routes", (string)null);
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
@ -324,7 +341,7 @@ namespace Server.Migrations
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
b.ToTable("RouteAddresses", (string)null);
});
modelBuilder.Entity("Server.Models.RouteAddressDetails", b =>
@ -356,7 +373,7 @@ namespace Server.Migrations
b.HasIndex("VehicleEnrollmentId");
b.ToTable("RouteAddressDetails");
b.ToTable("RouteAddressDetails", (string)null);
});
modelBuilder.Entity("Server.Models.State", b =>
@ -378,7 +395,7 @@ namespace Server.Migrations
b.HasIndex("CountryId");
b.ToTable("States");
b.ToTable("States", (string)null);
});
modelBuilder.Entity("Server.Models.Ticket", b =>
@ -416,7 +433,7 @@ namespace Server.Migrations
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets");
b.ToTable("Tickets", (string)null);
});
modelBuilder.Entity("Server.Models.TicketGroup", b =>
@ -435,7 +452,7 @@ namespace Server.Migrations
b.HasIndex("UserId");
b.ToTable("TicketGroups");
b.ToTable("TicketGroups", (string)null);
});
modelBuilder.Entity("Server.Models.User", b =>
@ -446,10 +463,19 @@ namespace Server.Migrations
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<int?>("Document")
.HasColumnType("integer");
b.Property<string>("DocumentDetails")
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
@ -461,6 +487,9 @@ namespace Server.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<int?>("Gender")
.HasColumnType("integer");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
@ -549,7 +578,7 @@ namespace Server.Migrations
b.HasIndex("CompanyId");
b.ToTable("Vehicles");
b.ToTable("Vehicles", (string)null);
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
@ -584,7 +613,7 @@ namespace Server.Migrations
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments");
b.ToTable("VehicleEnrollments", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
@ -663,14 +692,33 @@ namespace Server.Migrations
modelBuilder.Entity("Server.Models.Company", b =>
{
b.HasOne("Server.Models.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.WithOne("Company")
.HasForeignKey("Server.Models.Company", "OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
});
modelBuilder.Entity("Server.Models.CompanyDriver", b =>
{
b.HasOne("Server.Models.Company", "Company")
.WithMany("CompanyDrivers")
.HasForeignKey("CompanyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.User", "Driver")
.WithOne("Employer")
.HasForeignKey("Server.Models.CompanyDriver", "DriverId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Company");
b.Navigation("Driver");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.HasOne("Server.Models.User", "User")
@ -771,7 +819,7 @@ namespace Server.Migrations
modelBuilder.Entity("Server.Models.User", b =>
{
b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 =>
b.OwnsMany("Server.Models.User.RefreshTokens#Server.Models.RefreshToken", "RefreshTokens", b1 =>
{
b1.Property<string>("UserId")
.HasColumnType("text");
@ -797,7 +845,7 @@ namespace Server.Migrations
b1.HasKey("UserId", "Id");
b1.ToTable("RefreshToken");
b1.ToTable("RefreshToken", (string)null);
b1.WithOwner()
.HasForeignKey("UserId");
@ -848,6 +896,8 @@ namespace Server.Migrations
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Navigation("CompanyDrivers");
b.Navigation("Vehicles");
});
@ -880,6 +930,12 @@ namespace Server.Migrations
modelBuilder.Entity("Server.Models.User", b =>
{
b.Navigation("Company")
.IsRequired();
b.Navigation("Employer")
.IsRequired();
b.Navigation("Reviews");
b.Navigation("TicketGroups");

View File

@ -14,5 +14,6 @@ public class Company
public string OwnerId { get; set; } = null!;
public User Owner { get; set; } = null!;
public virtual List<Vehicle> Vehicles { get; set; } = null!;
public virtual IList<Vehicle> Vehicles { get; set; } = null!;
public virtual IList<CompanyDriver> CompanyDrivers { get; set; } = null!;
}

View File

@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Server.Models;
public class CompanyDriver
{
[ForeignKey("UserId")]
public string DriverId { get; set; } = null!;
public User Driver { get; set; } = null!;
[ForeignKey("CompanyId")]
public int CompanyId { get; set; }
public Company Company { get; set; } = null!;
}

View File

@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Identity;
using Utils;
namespace Server.Models;
@ -14,8 +15,21 @@ public class User : IdentityUser
[Required(ErrorMessage = "Patronymic is required")]
public string Patronymic { get; set; } = null!;
public DateTime? BirthDate { get; set; }
public Identity.Gender? Gender { get; set; }
public Identity.Document? Document { get; set; }
public string? DocumentDetails { get; set; }
public IList<RefreshToken> RefreshTokens { get; set; } = null!;
public Company Company { get; set; } = null!;
public virtual IList<TicketGroup> TicketGroups { get; set; } = null!;
public virtual IList<Review> Reviews { get; set; } = null!;
public virtual CompanyDriver? Employer { get; set; } = null!;
public string GetFullName() => $"{LastName} {FirstName} {Patronymic}";
}

View File

@ -8,12 +8,12 @@ using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Server.Configurations;
using Server.Constants;
using Server.Data;
using Server.Helpers;
using Server.Models;
using Server.Services;
using SharedModels.DataTransferObjects;
using Utils;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
@ -121,8 +121,8 @@ services.AddScoped<IVehicleManagementService, VehicleManagementService>();
services.AddScoped<IVehicleEnrollmentManagementService, VehicleEnrollmentManagementService>();
services.AddScoped<IRouteManagementService, RouteManagementService>();
services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
services.AddScoped<ISortHelper<ExpandoObject>, SortHelper<ExpandoObject>>();
services.AddScoped<IUserManagementService, UserManagementService>();
services.AddScoped<IDriverManagementService, DriverManagementService>();
services.AddScoped<IDataShaper<CountryDto>, DataShaper<CountryDto>>();
services.AddScoped<IDataShaper<StateDto>, DataShaper<StateDto>>();
@ -139,15 +139,16 @@ services.AddScoped<IDataShaper<VehicleEnrollmentWithDetailsDto>, DataShaper<Vehi
services.AddScoped<IDataShaper<RouteDto>, DataShaper<RouteDto>>();
services.AddScoped<IDataShaper<RouteWithAddressesDto>, DataShaper<RouteWithAddressesDto>>();
services.AddScoped<IDataShaper<RouteAddressDto>, DataShaper<RouteAddressDto>>();
services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
services.AddScoped<IDataShaper<DriverDto>, DataShaper<DriverDto>>();
services.AddScoped<IDataShaper<ExpandoObject>, DataShaper<ExpandoObject>>();
services.AddScoped<ISortHelper<ExpandoObject>, SortHelper<ExpandoObject>>();
services.AddScoped<IPager<ExpandoObject>, Pager<ExpandoObject>>();
services.AddScoped<AutomationService>();
services.AddScoped<IReportService, ReportService>();
services.AddScoped<IStatisticsService, StatisticsService>();
services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
services.AddScoped<IDataShaper<ExpandoObject>, DataShaper<ExpandoObject>>();
// Adding DB Context with PostgreSQL
var connectionString = configuration.GetConnectionString("DefaultConnection");
@ -162,7 +163,7 @@ var serviceProvider = scope.ServiceProvider;
await SeedData.Initialize(serviceProvider);
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
if (Convert.ToBoolean(configuration["UseApiExplorer"]))
{
app.UseSwagger();
app.UseSwaggerUI();

View File

@ -37,6 +37,7 @@
<ItemGroup>
<ProjectReference Include="..\SharedModels\SharedModels.csproj" />
<ProjectReference Include="..\Utils\Utils.csproj" />
</ItemGroup>
</Project>

View File

@ -13,6 +13,7 @@ using Server.Constants;
using Server.Models;
using SharedModels.Requests;
using SharedModels.Responses;
using Utils;
namespace Server.Services;
@ -75,7 +76,7 @@ public class AuthenticationService : IAuthenticationService
return (false, $"{createUserResult.Errors?.First().Description}");
}
await _userManager.AddToRoleAsync(user, Constants.Identity.DefaultRole.ToString());
await _userManager.AddToRoleAsync(user, Identity.DefaultRole.ToString());
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var confirmationLink = _linkGenerator.GetUriByAction(_contextAccessor.HttpContext,
@ -285,10 +286,12 @@ public class AuthenticationService : IAuthenticationService
var claims = new[]
{
new Claim(JwtStandardClaimNames.Sub, user.Id),
new Claim(JwtStandardClaimNames.Name, $"{user.LastName} {user.FirstName} {user.Patronymic}"),
new Claim(JwtStandardClaimNames.Name, user.GetFullName()),
new Claim(JwtStandardClaimNames.GivenName, user.FirstName),
new Claim(JwtStandardClaimNames.FamilyName, user.LastName),
new Claim(JwtStandardClaimNames.MiddleName, user.Patronymic),
new Claim(JwtStandardClaimNames.Gender, user.Gender?.ToString() ?? "Undefined"),
new Claim(JwtStandardClaimNames.BirthDate, user.BirthDate?.ToString()?? "Undefined"),
new Claim(JwtStandardClaimNames.Email, user.Email),
new Claim(JwtStandardClaimNames.EmailVerified, user.EmailConfirmed.ToString()),
new Claim(JwtRegisteredClaimNames.Exp, DateTime.UtcNow.AddMinutes(_jwt.ValidityInMinutes).ToString(CultureInfo.InvariantCulture))

View File

@ -0,0 +1,145 @@
using System.Dynamic;
using AutoMapper;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;
public class DriverManagementService : IDriverManagementService
{
private readonly IUserManagementService _userManagementService;
private readonly UserManager<User> _userManager;
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<ExpandoObject> _userSortHelper;
private readonly IDataShaper<DriverDto> _userDataShaper;
private readonly IPager<ExpandoObject> _pager;
public DriverManagementService(IUserManagementService userManagementService, IMapper mapper,
UserManager<User> userManager, ApplicationDbContext dbContext,
ISortHelper<ExpandoObject> userSortHelper, IDataShaper<DriverDto> userDataShaper,
IPager<ExpandoObject> pager)
{
_userManagementService = userManagementService;
_userManager = userManager;
_dbContext = dbContext;
_userSortHelper = userSortHelper;
_userDataShaper = userDataShaper;
_pager = pager;
_mapper = mapper;
}
public async Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> AddDriver(CreateDriverDto createDriverDto)
{
var createUserDto = _mapper.Map<CreateUserDto>(createDriverDto);
createUserDto.Roles = new List<string> { "Driver" };
createUserDto.Password = createDriverDto.Password;
var result = await _userManagementService.AddUser(createUserDto);
if (!result.isSucceeded)
{
return (false, result.actionResult, null);
}
var driverDto = _mapper.Map<DriverDto>(createUserDto);
_dbContext.CompanyDrivers.Add(new CompanyDriver { CompanyId = createDriverDto.CompanyId, DriverId = driverDto.Id });
await _dbContext.SaveChangesAsync();
driverDto.Roles = result.user.Roles;
return (true, null, driverDto);
}
public async Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> drivers, PagingMetadata<ExpandoObject> pagingMetadata)> GetDrivers(CompanyDriverParameters parameters)
{
var dbUsers = _userManager.Users.Include(u => u.Employer)
.Where(u => u.Employer != null).AsQueryable();
FilterByCompanyId(ref dbUsers, parameters.CompanyId);
SearchByAllUserFields(ref dbUsers, parameters.Search);
var userDtos = _mapper.ProjectTo<DriverDto>(dbUsers);
var shapedData = _userDataShaper.ShapeData(userDtos, parameters.Fields).AsQueryable();
try
{
shapedData = _userSortHelper.ApplySort(shapedData, parameters.Sort);
}
catch (Exception)
{
return (false, new BadRequestObjectResult("Invalid sorting string"), null!, null!);
}
var pagingMetadata = _pager.ApplyPaging(ref shapedData, parameters.PageNumber, parameters.PageSize);
return (true, null, shapedData, pagingMetadata);
void FilterByCompanyId(ref IQueryable<User> users, int? compnayId)
{
if (!users.Any() || compnayId == null)
{
return;
}
users = users.Where(u => u.Employer.CompanyId == compnayId);
}
void SearchByAllUserFields(ref IQueryable<User> users, string? search)
{
if (!users.Any() || search == null)
{
return;
}
users = users.Where(u =>
u.FirstName.ToLower().Contains(search.ToLower()) ||
u.LastName.ToLower().Contains(search.ToLower()) ||
u.Patronymic.ToLower().Contains(search.ToLower()) ||
u.Email.ToLower().Contains(search.ToLower()) ||
u.PhoneNumber.ToLower().Contains(search.ToLower()));
}
}
public async Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject driver)> GetDriver(string id, string? fields)
{
var dbUser = await _userManager.Users.Include(u => u.Employer).
FirstOrDefaultAsync(u => u.Id == id);
if (dbUser == null)
{
return (false, new NotFoundResult(), null!);
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = CompanyDriverParameters.DefaultFields;
}
var userDto = _mapper.Map<DriverDto>(dbUser);
var shapedData = _userDataShaper.ShapeData(userDto, fields);
return (true, null, shapedData);
}
public async Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> UpdateDriver(string id, UpdateDriverDto updateDriverDto)
{
var updateUserDto = _mapper.Map<UpdateUserDto>(updateDriverDto);
var result = await _userManagementService.UpdateUser(id, updateUserDto);
return (result.isSucceeded, result.actionResult, _mapper.Map<DriverDto>(result.user));
}
public async Task<(bool isSucceed, IActionResult? actionResult)> DeleteDriver(string id)
{
return await _userManagementService.DeleteUser(id);
}
}

View File

@ -34,7 +34,7 @@ public class EmailSenderService : IEmailSenderService
mailMessage.Subject = $"{applicationName}. {subject}";
mailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Text) { Text = message};
await _smtpClient.ConnectAsync(_smtpCredentials.Host, Int32.Parse(_smtpCredentials.Port), false);
await _smtpClient.ConnectAsync(_smtpCredentials.Host, _smtpCredentials.Port, false);
await _smtpClient.AuthenticateAsync(Encoding.ASCII, _smtpCredentials.User, _smtpCredentials.Password);
await _smtpClient.SendAsync(mailMessage);
await _smtpClient.DisconnectAsync(true);

View File

@ -0,0 +1,22 @@
using System.Dynamic;
using Microsoft.AspNetCore.Mvc;
using SharedModels.DataTransferObjects;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;
public interface IDriverManagementService
{
Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> AddDriver(CreateDriverDto createDriverDto);
Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> drivers, PagingMetadata<ExpandoObject> pagingMetadata)>
GetDrivers(CompanyDriverParameters parameters);
Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject driver)> GetDriver(string id, string? fields);
Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> UpdateDriver(string id, UpdateDriverDto updateDriverDto);
Task<(bool isSucceed, IActionResult? actionResult)> DeleteDriver(string id);
}

View File

@ -0,0 +1,21 @@
using System.Dynamic;
using Microsoft.AspNetCore.Mvc;
using SharedModels.DataTransferObjects;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;
public interface IUserManagementService
{
Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)> AddUser(CreateUserDto createUserDto);
Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> users, PagingMetadata<ExpandoObject> pagingMetadata)>
GetUsers(UserParameters parameters);
Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject user)> GetUser(string id, string? fields);
Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)> UpdateUser(string id, UpdateUserDto updateUserDto);
Task<(bool isSucceed, IActionResult? actionResult)> DeleteUser(string id);
}

View File

@ -44,11 +44,14 @@ public class ReviewManagementService : IReviewManagementService
PagingMetadata<ExpandoObject> pagingMetadata)> GetReviews(ReviewParameters parameters)
{
var dbReviews = _dbContext.Reviews
.Include(r => r.VehicleEnrollment).ThenInclude(ve => ve.Vehicle)
.ThenInclude(v => v.Company).Include(r => r.User)
.AsQueryable();
FilterByReviewRating(ref dbReviews, parameters.FromRating, parameters.ToRating);
FilterByReviewComment(ref dbReviews, parameters.Comment);
FilterByReviewUserId(ref dbReviews, parameters.UserId);
FilterByReviewCompanyId(ref dbReviews, parameters.CompanyId);
var reviewDtos = _mapper.ProjectTo<ReviewDto>(dbReviews);
var shapedData = _reviewDataShaper.ShapeData(reviewDtos, parameters.Fields).AsQueryable();
@ -103,6 +106,16 @@ public class ReviewManagementService : IReviewManagementService
reviews = reviews.Where(r =>
r.UserId.Contains(userId.ToLower()));
}
void FilterByReviewCompanyId(ref IQueryable<Review> reviews, int? companyId)
{
if (!reviews.Any() || companyId == null)
{
return;
}
reviews = reviews.Where(r => r.VehicleEnrollment.Vehicle.CompanyId == companyId);
}
}
public async Task<(bool isSucceed, IActionResult? actionResult, ExpandoObject review)> GetReview(int id, string? fields)
@ -113,7 +126,8 @@ public class ReviewManagementService : IReviewManagementService
}
var dbReview = await _dbContext.Reviews.Where(r => r.Id == id)
.Include(r => r.VehicleEnrollment)
.Include(r => r.VehicleEnrollment).ThenInclude(ve => ve.Vehicle)
.ThenInclude(v => v.Company).Include(r => r.User)
.FirstAsync();
if (String.IsNullOrWhiteSpace(fields))

View File

@ -0,0 +1,231 @@
using System.Dynamic;
using AutoMapper;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
namespace Server.Services;
public class UserManagementService : IUserManagementService
{
private readonly UserManager<User> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IMapper _mapper;
private readonly ISortHelper<ExpandoObject> _userSortHelper;
private readonly IDataShaper<UserDto> _userDataShaper;
private readonly IPager<ExpandoObject> _pager;
public UserManagementService(IMapper mapper, UserManager<User> userManager, RoleManager<IdentityRole> roleManager,
ISortHelper<ExpandoObject> userSortHelper, IDataShaper<UserDto> userDataShaper, IPager<ExpandoObject> pager,
ApplicationDbContext dbContext)
{
_mapper = mapper;
_userManager = userManager;
_roleManager = roleManager;
_userSortHelper = userSortHelper;
_userDataShaper = userDataShaper;
_pager = pager;
_userManager.UserValidators.Clear();
}
public async Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)> AddUser(CreateUserDto createUserDto)
{
var user = _mapper.Map<User>(createUserDto);
user.BirthDate = user.BirthDate == null ? null : new DateTime(user.BirthDate.Value.Ticks, DateTimeKind.Utc);
var userDto = _mapper.Map<UserDto>(user);
userDto.Roles = new List<string>();
if (await _userManager.FindByEmailAsync(user.Email) != null)
{
return (false, new BadRequestObjectResult("Email already registered"), null);
}
if (user.PhoneNumber != null && await _userManager.Users.FirstOrDefaultAsync(u => u.PhoneNumber == user.PhoneNumber) != null)
{
return (false, new BadRequestObjectResult("Phone number already registered"), null);
}
if (createUserDto.Roles != null!)
{
foreach (var role in createUserDto.Roles)
{
if (!await _roleManager.RoleExistsAsync(role))
{
return (false, new BadRequestObjectResult($"Roles \"{role}\" doesn't exist"), null);
}
userDto.Roles.Add(role);
}
}
await _userManager.CreateAsync(user, createUserDto.Password);
await _userManager.AddToRolesAsync(user, createUserDto.Roles);
userDto.Id = user.Id;
return (true, null, userDto);
}
public async Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> users,
PagingMetadata<ExpandoObject> pagingMetadata)> GetUsers(UserParameters parameters)
{
var dbUsers = _userManager.Users.Include(u => u.Company)
.Include(u => u.Reviews).Include(u => u.TicketGroups)
.ThenInclude(tg => tg.Tickets).AsQueryable();
SearchByAllUserFields(ref dbUsers, parameters.Search);
var userDtos = _mapper.ProjectTo<UserDto>(dbUsers);
var shapedData = _userDataShaper.ShapeData(userDtos, parameters.Fields).AsQueryable();
try
{
shapedData = _userSortHelper.ApplySort(shapedData, parameters.Sort);
}
catch (Exception)
{
return (false, new BadRequestObjectResult("Invalid sorting string"), null!, null!);
}
var pagingMetadata = _pager.ApplyPaging(ref shapedData, parameters.PageNumber, parameters.PageSize);
if ((bool)parameters.Fields?.Contains("roles"))
{
foreach (var user in shapedData)
{
dynamic dynamicUser = user as IDictionary<string, object>;
var roles = await _userManager.GetRolesAsync(new User { Id = dynamicUser.Id });
dynamicUser.Roles = roles;
}
}
return (true, null, shapedData, pagingMetadata);
void SearchByAllUserFields(ref IQueryable<User> users, string? search)
{
if (!users.Any() || search == null)
{
return;
}
users = users.Where(u =>
u.FirstName.ToLower().Contains(search.ToLower()) ||
u.LastName.ToLower().Contains(search.ToLower()) ||
u.Patronymic.ToLower().Contains(search.ToLower()) ||
u.Email.ToLower().Contains(search.ToLower()) ||
u.PhoneNumber.ToLower().Contains(search.ToLower()));
}
}
public async Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject user)>
GetUser(string id, string? fields)
{
var dbUser = await _userManager.Users.Include(u => u.Employer).
FirstOrDefaultAsync(u => u.Id == id);
if (dbUser == null)
{
return (false, new NotFoundResult(), null!);
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = UserParameters.DefaultFields;
}
var userDto = _mapper.Map<DriverDto>(dbUser);
var shapedData = _userDataShaper.ShapeData(userDto, fields);
return (true, null, shapedData);
}
public async Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)>
UpdateUser(string id, UpdateUserDto updateUserDto)
{
if (id != updateUserDto.Id)
{
return (false, new BadRequestObjectResult("Object and query ids don't match"), null);
}
if (!await _userManager.Users.AnyAsync(u => u.Id == id))
{
return (false, new NotFoundResult(), null);
}
var dbUser = await _userManager.FindByIdAsync(id);
var user = _mapper.Map<User>(updateUserDto);
dbUser.FirstName = user.FirstName;
dbUser.LastName = user.LastName;
dbUser.Patronymic = user.Patronymic;
dbUser.BirthDate = new DateTime(user.BirthDate.Value.Ticks, DateTimeKind.Utc);
dbUser.Gender = user.Gender;
dbUser.Document = user.Document;
dbUser.DocumentDetails = user.DocumentDetails;
dbUser.Email = user.Email;
dbUser.EmailConfirmed = user.EmailConfirmed;
dbUser.PhoneNumber = user.PhoneNumber;
dbUser.PhoneNumberConfirmed = user.PhoneNumberConfirmed;
var userDto = _mapper.Map<UserDto>(user);
userDto.Roles = new List<string>();
updateUserDto.Roles = updateUserDto.Roles == null ? new List<string>() : updateUserDto.Roles;
var roles = await _userManager.GetRolesAsync(user);
var rolesToDelete = roles.Except(updateUserDto.Roles).ToArray();
var rolesToAdd = updateUserDto.Roles.Except(roles).ToArray();
userDto.Roles = roles.Except(rolesToDelete).Union(rolesToAdd).ToList();
foreach (var role in rolesToDelete)
{
if (await _roleManager.RoleExistsAsync(role))
{
await _userManager.RemoveFromRoleAsync(dbUser, role);
}
}
foreach (var role in rolesToAdd)
{
if (!await _roleManager.RoleExistsAsync(role))
{
return (false, new BadRequestObjectResult($"Roles \"{role}\" doesn't exist"), null);
}
}
await _userManager.AddToRolesAsync(dbUser, rolesToAdd);
if (updateUserDto.Password != null)
{
await _userManager.RemovePasswordAsync(dbUser);
await _userManager.AddPasswordAsync(dbUser, updateUserDto.Password);
}
await _userManager.UpdateAsync(dbUser);
return (true, null, userDto);
}
public async Task<(bool isSucceed, IActionResult? actionResult)> DeleteUser(string id)
{
var dbUser = await _userManager.FindByIdAsync(id);
if (dbUser == null)
{
return (false, new NotFoundResult());
}
await _userManager.DeleteAsync(dbUser);
return (true, null);
}
}

View File

@ -12,7 +12,7 @@
"ApplicationName": "auto.bus",
"SmtpCredentials": {
"Host": "",
"Port": "",
"Port": 587,
"User": "",
"Password": ""
},

View File

@ -9,10 +9,11 @@
"ConnectionStrings": {
"DefaultConnection": "host=localhost;database=auto.bus;user id=postgres;password=postgres;Include Error Detail = true"
},
"UseApiExplorer": true,
"ApplicationName": "auto.bus",
"SmtpCredentials": {
"Host": "",
"Port": "",
"Port": 587,
"User": "",
"Password": ""
},

View File

@ -0,0 +1,18 @@
namespace SharedModels.DataTransferObjects;
public class DriverDto : UserDto
{
public int CompanyId { get; set; }
}
public class CreateDriverDto : CreateUserDto
{
public int CompanyId { get; set; }
public override IList<string>? Roles { get; set; }
}
public class UpdateDriverDto : UpdateUserDto
{
public override IList<string>? Roles { get; set; }
}

View File

@ -9,6 +9,7 @@ public class ReviewDto : CreateReviewDto
[DataType(DataType.DateTime)]
public DateTime PostDateTimeUtc { get; set; }
public StrippedUserDto User { get; set; } = null!;
public InReviewVehicleEnrollmentDto VehicleEnrollment { get; set; } = null!;
}

View File

@ -1,39 +1,73 @@
using System.ComponentModel.DataAnnotations;
using Utils;
namespace SharedModels.DataTransferObjects;
public class UserDto : UpdateUserDto
public class UserDto
{
public virtual CompanyDto Company { get; set; } = null!;
public string Id { get; set; } = null!;
public virtual IList<TicketDto> Tickets { get; set; } = null!;
public virtual IList<ReviewDto> Ratings { get; set; } = null!;
}
public string FirstName { get; set; } = null!;
public class CreateUserDto
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string LastName { get; set; } = null!;
[Required(ErrorMessage = "Username is required")]
public string UserName { get; set; } = null!;
public string Patronymic { get; set; } = null!;
[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
public Identity.Gender? Gender { get; set; }
public Identity.Document? Document { get; set; }
public string? DocumentDetails { get; set; }
[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 virtual IList<string> Roles { get; set; } = null!;
public virtual IList<TicketGroupDto>? TicketGroups { get; set; } = null!;
public virtual IList<ReviewDto>? Reviews { get; set; } = null!;
}
public class CreateUserDto
{
[Required]
public string FirstName { get; set; } = null!;
[Required]
public string LastName { get; set; } = null!;
[Required]
public string Patronymic { get; set; } = null!;
[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
public Identity.Gender? Gender { get; set; }
public Identity.Document? Document { get; set; }
public string? DocumentDetails { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; } = null!;
public bool EmailConfirmed { get; set; } = false;
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = null!;
[DataType(DataType.PhoneNumber)]
public string? PhoneNumber { get; set; }
public bool? PhoneNumberConfirmed { get; set; } = false;
public virtual IList<string> Roles { get; set; } = null!;
}
public class UpdateUserDto
@ -41,23 +75,54 @@ public class UpdateUserDto
[Required]
public string Id { get; set; } = null!;
public string? FirstName { get; set; }
public string? LastName { get; set; }
[Required]
public string FirstName { get; set; } = null!;
public string UserName { get; set; } = null!;
[Required]
public string LastName { get; set; } = null!;
[Required]
public string Patronymic { get; set; } = null!;
[Required]
[DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
[Required]
public Identity.Gender? Gender { get; set; }
[Required]
public Identity.Document? Document { get; set; }
[Required]
public string? DocumentDetails { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; } = null!;
public bool EmailConfirmed { get; set; }
public bool EmailConfirmed { get; set; } = false;
[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? Password { get; set; } = null!;
[Required]
[DataType(DataType.PhoneNumber)]
public string? PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
[Required]
public bool PhoneNumberConfirmed { get; set; } = false;
public virtual IList<string> RoleIds { get; set; } = new List<string> { "User" };
public virtual IList<string> Roles { get; set; } = null!;
}
public class StrippedUserDto
{
public string Id { get; set; } = null!;
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
public string Patronymic { get; set; } = null!;
public Identity.Gender? Gender { get; set; }
}

View File

@ -0,0 +1,16 @@
namespace SharedModels.QueryParameters.Objects;
public class CompanyDriverParameters : ParametersBase
{
public const string DefaultFields = "id,firstName,lastName,patronymic,email,emailConfirmed,phoneNumber," +
"phoneNumberConfirmed,birthDate,gender,document,documentDetails," +
"companyId";
public CompanyDriverParameters()
{
Sort = "";
Fields = DefaultFields;
}
public int? CompanyId { get; set; }
}

View File

@ -2,7 +2,7 @@ namespace SharedModels.QueryParameters.Objects;
public class ReviewParameters : ParametersBase
{
public const string DefaultFields = "id,userId,vehicleEnrollmentId,vehicleEnrollment,rating,comment";
public const string DefaultFields = "id,rating,comment,userId,user,vehicleEnrollmentId,vehicleEnrollment";
public ReviewParameters()
{
@ -14,4 +14,5 @@ public class ReviewParameters : ParametersBase
public string? Comment { get; set; }
public string? UserId { get; set; }
public int? CompanyId { get; set; }
}

View File

@ -2,17 +2,13 @@ namespace SharedModels.QueryParameters.Objects;
public class UserParameters : ParametersBase
{
public const string DefaultFields = "";
public const string DefaultFields = "id,firstName,lastName,patronymic,email,emailConfirmed,phoneNumber," +
"phoneNumberConfirmed,birthDate,gender,document,documentDetails," +
"roles,reviews,ticketGroups";
public UserParameters()
{
Sort = "id";
Sort = "";
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

@ -6,4 +6,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Utils\Utils.csproj" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
namespace Server.Constants;
namespace Utils;
public class Identity
{
@ -10,7 +10,19 @@ public class Identity
Administrator
}
public enum Gender
{
Male,
Female
}
public enum Document
{
Passport,
DriverLicence
}
public const string DefaultEmail = "admin@subdomain.domain";
public const string DefaultPassword = "123qwe!@#QWE";
public const Roles DefaultRole = Roles.Administrator;
public const Roles DefaultRole = Roles.User;
}

9
Utils/Utils.csproj Normal file
View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0DCB2130-10E7-4C98-AB94-5F8D68032B9F}"
EndProject