chore: add CRUD api endpoints for all remaining entities exept from AspNetUser

This commit is contained in:
cuqmbr 2022-11-13 13:36:07 +02:00
parent 5314b4bd53
commit 6f2fc702df
57 changed files with 4570 additions and 93 deletions

View File

@ -34,8 +34,39 @@ public class MapperInitializer : Profile
CreateMap<RouteAddress, RouteAddressDto>().ReverseMap();
CreateMap<RouteAddress, CreateRouteAddressDto>().ReverseMap();
CreateMap<RouteAddress, UpdateRouteAddressDto>().ReverseMap();
CreateMap<Route, RouteDto>().ReverseMap();
CreateMap<Route, CreateRouteDto>().ReverseMap();
CreateMap<Route, UpdateRouteDto>().ReverseMap();
CreateMap<Ticket, TicketDto>().ReverseMap();
CreateMap<Ticket, CreateTicketDto>().ReverseMap();
CreateMap<Ticket, UpdateTicketDto>().ReverseMap();
CreateMap<Review, ReviewDto>().ReverseMap();
CreateMap<Review, CreateReviewDto>().ReverseMap();
CreateMap<Review, UpdateReviewDto>().ReverseMap();
CreateMap<Company, CompanyDto>().ReverseMap();
CreateMap<Company, CreateCompanyDto>().ReverseMap();
CreateMap<Company, UpdateCompanyDto>().ReverseMap();
CreateMap<Vehicle, VehicleDto>().ReverseMap();
CreateMap<Vehicle, CreateVehicleDto>().ReverseMap();
CreateMap<Vehicle, UpdateVehicleDto>().ReverseMap();
CreateMap<VehicleEnrollment, VehicleEnrollmentDto>().ReverseMap();
CreateMap<VehicleEnrollment, CreateVehicleEnrollmentDto>().ReverseMap();
CreateMap<VehicleEnrollment, UpdateVehicleEnrollmentDto>().ReverseMap();
// CreateMap<User, UserDto>().ReverseMap();
// CreateMap<User, CreateUserDto>().ReverseMap();
// CreateMap<User, UpdateUserDto>().ReverseMap();
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/companies")]
[ApiController]
public class CompanyManagementController : ControllerBase
{
private readonly ICompanyManagementService _companyManagementService;
public CompanyManagementController(ICompanyManagementService companyManagementService)
{
_companyManagementService = companyManagementService;
}
[HttpPost]
public async Task<IActionResult> AddCompany(CreateCompanyDto company)
{
var result = await _companyManagementService.AddCompany(company);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetCompany), new {id = result.company.Id}, result.company);
}
[HttpGet]
public async Task<IActionResult> GetCompanies([FromQuery] CompanyParameters parameters)
{
var result = await _companyManagementService.GetCompanies(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.companies);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetCompany(int id, [FromQuery] string? fields)
{
if (!await _companyManagementService.IsCompanyExists(id))
{
return NotFound();
}
var result = await _companyManagementService.GetCompany(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.company);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateCompany(int id, UpdateCompanyDto company)
{
if (id != company.Id)
{
return BadRequest();
}
var result = await _companyManagementService.UpdateCompany(company);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.company);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteCompany(int id)
{
if (!await _companyManagementService.IsCompanyExists(id))
{
return NotFound();
}
var result = await _companyManagementService.DeleteCompany(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/reviews")]
[ApiController]
public class ReviewManagementController : ControllerBase
{
private readonly IReviewManagementService _reviewManagementService;
public ReviewManagementController(IReviewManagementService reviewManagementService)
{
_reviewManagementService = reviewManagementService;
}
[HttpPost]
public async Task<IActionResult> AddReview(CreateReviewDto review)
{
var result = await _reviewManagementService.AddReview(review);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetReview), new {id = result.review.Id}, result.review);
}
[HttpGet]
public async Task<IActionResult> GetReviews([FromQuery] ReviewParameters parameters)
{
var result = await _reviewManagementService.GetReviews(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.reviews);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetReview(int id, [FromQuery] string? fields)
{
if (!await _reviewManagementService.IsReviewExists(id))
{
return NotFound();
}
var result = await _reviewManagementService.GetReview(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.review);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateReview(int id, UpdateReviewDto review)
{
if (id != review.Id)
{
return BadRequest();
}
var result = await _reviewManagementService.UpdateReview(review);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.review);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteReview(int id)
{
if (!await _reviewManagementService.IsReviewExists(id))
{
return NotFound();
}
var result = await _reviewManagementService.DeleteReview(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/routeAddresses")]
[ApiController]
public class RouteAddressManagementController : ControllerBase
{
private readonly IRouteAddressManagementService _routeAddressManagementService;
public RouteAddressManagementController(IRouteAddressManagementService routeAddressManagementService)
{
_routeAddressManagementService = routeAddressManagementService;
}
[HttpPost]
public async Task<IActionResult> AddRouteAddress(CreateRouteAddressDto routeAddress)
{
var result = await _routeAddressManagementService.AddRouteAddress(routeAddress);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetRouteAddress), new {id = result.routeAddress.Id}, result.routeAddress);
}
[HttpGet]
public async Task<IActionResult> GetRouteAddresses([FromQuery] RouteAddressParameters parameters)
{
var result = await _routeAddressManagementService.GetRouteAddresses(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.routeAddresses);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetRouteAddress(int id, [FromQuery] string? fields)
{
if (!await _routeAddressManagementService.IsRouteAddressExists(id))
{
return NotFound();
}
var result = await _routeAddressManagementService.GetRouteAddress(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.routeAddress);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateRouteAddress(int id, UpdateRouteAddressDto routeAddress)
{
if (id != routeAddress.Id)
{
return BadRequest();
}
var result = await _routeAddressManagementService.UpdateRouteAddress(routeAddress);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.routeAddress);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteRouteAddress(int id)
{
if (!await _routeAddressManagementService.IsRouteAddressExists(id))
{
return NotFound();
}
var result = await _routeAddressManagementService.DeleteRouteAddress(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/routes")]
[ApiController]
public class RouteManagementController : ControllerBase
{
private readonly IRouteManagementService _routeManagementService;
public RouteManagementController(IRouteManagementService routeManagementService)
{
_routeManagementService = routeManagementService;
}
[HttpPost]
public async Task<IActionResult> AddRoute(CreateRouteDto route)
{
var result = await _routeManagementService.AddRoute(route);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetRoute), new {id = result.route.Id}, result.route);
}
[HttpGet]
public async Task<IActionResult> GetRoutes([FromQuery] RouteParameters parameters)
{
var result = await _routeManagementService.GetRoutes(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.routes);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetRoute(int id, [FromQuery] string? fields)
{
if (!await _routeManagementService.IsRouteExists(id))
{
return NotFound();
}
var result = await _routeManagementService.GetRoute(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.route);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateRoute(int id, UpdateRouteDto route)
{
if (id != route.Id)
{
return BadRequest();
}
var result = await _routeManagementService.UpdateRoute(route);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.route);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteRoute(int id)
{
if (!await _routeManagementService.IsRouteExists(id))
{
return NotFound();
}
var result = await _routeManagementService.DeleteRoute(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -27,5 +27,11 @@ public class TestingController : ControllerBase
return NotFound();
}
[HttpPost("timespan")]
public async Task<IActionResult> TestTimeSpan([FromBody] TimeSpan ts)
{
return Ok();
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/tickets")]
[ApiController]
public class TicketManagementController : ControllerBase
{
private readonly ITicketManagementService _ticketManagementService;
public TicketManagementController(ITicketManagementService ticketManagementService)
{
_ticketManagementService = ticketManagementService;
}
[HttpPost]
public async Task<IActionResult> AddTicket(CreateTicketDto ticket)
{
var result = await _ticketManagementService.AddTicket(ticket);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetTicket), new {id = result.ticket.Id}, result.ticket);
}
[HttpGet]
public async Task<IActionResult> GetTickets([FromQuery] TicketParameters parameters)
{
var result = await _ticketManagementService.GetTickets(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.tickets);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetTicket(int id, [FromQuery] string? fields)
{
if (!await _ticketManagementService.IsTicketExists(id))
{
return NotFound();
}
var result = await _ticketManagementService.GetTicket(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.ticket);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateTicket(int id, UpdateTicketDto ticket)
{
if (id != ticket.Id)
{
return BadRequest();
}
var result = await _ticketManagementService.UpdateTicket(ticket);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.ticket);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTicket(int id)
{
if (!await _ticketManagementService.IsTicketExists(id))
{
return NotFound();
}
var result = await _ticketManagementService.DeleteTicket(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -0,0 +1,102 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/vehicleEnrollments")]
[ApiController]
public class VehicleEnrollmentManagementController : ControllerBase
{
private readonly IVehicleEnrollmentManagementService _vehicleEnrollmentManagementService;
public VehicleEnrollmentManagementController(IVehicleEnrollmentManagementService vehicleEnrollmentManagementService)
{
_vehicleEnrollmentManagementService = vehicleEnrollmentManagementService;
}
[HttpPost]
public async Task<IActionResult> AddEnrollment(CreateVehicleEnrollmentDto enrollment)
{
var result = await _vehicleEnrollmentManagementService.AddEnrollment(enrollment);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetEnrollment), new {id = result.enrollment.Id}, result.enrollment);
}
[HttpGet]
public async Task<IActionResult> GetEnrollments([FromQuery] VehicleEnrollmentParameters parameters)
{
var result = await _vehicleEnrollmentManagementService.GetEnrollments(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.enrollments);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetEnrollment(int id, [FromQuery] string? fields)
{
if (!await _vehicleEnrollmentManagementService.IsEnrollmentExists(id))
{
return NotFound();
}
var result = await _vehicleEnrollmentManagementService.GetEnrollment(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.enrollment);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateVehicle(int id, UpdateVehicleEnrollmentDto enrollment)
{
if (id != enrollment.Id)
{
return BadRequest();
}
var result = await _vehicleEnrollmentManagementService.UpdateEnrollment(enrollment);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.enrollment);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteEnrollment(int id)
{
if (!await _vehicleEnrollmentManagementService.IsEnrollmentExists(id))
{
return NotFound();
}
var result = await _vehicleEnrollmentManagementService.DeleteEnrollment(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Controllers;
[Route("api/vehicles")]
[ApiController]
public class VehicleManagementController : ControllerBase
{
private readonly IVehicleManagementService _vehicleManagementService;
public VehicleManagementController(IVehicleManagementService vehicleManagementService)
{
_vehicleManagementService = vehicleManagementService;
}
[HttpPost]
public async Task<IActionResult> AddVehicle(CreateVehicleDto vehicle)
{
var result = await _vehicleManagementService.AddVehicle(vehicle);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return CreatedAtAction(nameof(GetVehicle), new {id = result.vehicle.Id}, result.vehicle);
}
[HttpGet]
public async Task<IActionResult> GetVehicles([FromQuery] VehicleParameters parameters)
{
var result = await _vehicleManagementService.GetVehicles(parameters);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(result.pagingMetadata));
return Ok(result.vehicles);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetVehicle(int id, [FromQuery] string? fields)
{
if (!await _vehicleManagementService.IsVehicleExists(id))
{
return NotFound();
}
var result = await _vehicleManagementService.GetVehicle(id, fields);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.vehicle);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateVehicle(int id, UpdateVehicleDto vehicle)
{
if (id != vehicle.Id)
{
return BadRequest();
}
var result = await _vehicleManagementService.UpdateVehicle(vehicle);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return Ok(result.vehicle);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteVehicle(int id)
{
if (!await _vehicleManagementService.IsVehicleExists(id))
{
return NotFound();
}
var result = await _vehicleManagementService.DeleteVehicle(id);
if (!result.isSucceed)
{
return BadRequest(result.message);
}
return NoContent();
}
}

View File

@ -23,18 +23,4 @@ public class ApplicationDbContext : IdentityDbContext<User>
public DbSet<Country> Countries { get; set; } = null!;
public DbSet<Ticket> Tickets { get; set; } = null!;
public DbSet<Review> Reviews { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<RouteAddress>()
.HasKey(ra => new {ra.RouteId, ra.AddressId});
modelBuilder.Entity<Ticket>()
.HasKey(t => new {t.UserId, t.VehicleEnrollmentId});
modelBuilder.Entity<Review>()
.HasKey(t => new {t.UserId, t.VehicleEnrollmentId});
}
}

View File

@ -0,0 +1,798 @@
// <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("20221110081525_Replace_Composite_Keys_With_Single_Ones")]
partial class Replace_Composite_Keys_With_Single_Ones
{
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")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Rating")
.HasColumnType("integer");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Reviews");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Routes");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AddressId")
.HasColumnType("integer");
b.Property<double>("CostToNextCity")
.HasColumnType("double precision");
b.Property<int>("Order")
.HasColumnType("integer");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<TimeSpan>("TimeSpanToNextCity")
.HasColumnType("interval");
b.Property<TimeSpan>("WaitTimeSpan")
.HasColumnType("interval");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CountryId")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CountryId");
b.ToTable("States");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsReturned")
.HasColumnType("boolean");
b.Property<DateTime>("PurchaseDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Server.Models.Vehicle", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("Capacity")
.HasColumnType("integer");
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<bool>("HasBelts")
.HasColumnType("boolean");
b.Property<bool>("HasClimateControl")
.HasColumnType("boolean");
b.Property<bool>("HasOutlet")
.HasColumnType("boolean");
b.Property<bool>("HasStewardess")
.HasColumnType("boolean");
b.Property<bool>("HasTV")
.HasColumnType("boolean");
b.Property<bool>("HasWC")
.HasColumnType("boolean");
b.Property<bool>("HasWiFi")
.HasColumnType("boolean");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CompanyId");
b.ToTable("Vehicles");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("CancelationComment")
.IsRequired()
.HasColumnType("text");
b.Property<TimeSpan>("DelayTimeSpan")
.HasColumnType("interval");
b.Property<DateOnly>("DepartureDateOnly")
.HasColumnType("date");
b.Property<TimeOnly>("DepartureTimeOnlyUtc")
.HasColumnType("time without time zone");
b.Property<bool>("IsCanceled")
.HasColumnType("boolean");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<int>("VehicleId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.HasOne("Server.Models.City", "City")
.WithMany("Addresses")
.HasForeignKey("CityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("City");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.HasOne("Server.Models.State", "State")
.WithMany("Cities")
.HasForeignKey("StateId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("State");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.HasOne("Server.Models.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.HasOne("Server.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
.WithMany()
.HasForeignKey("VehicleEnrollmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
b.Navigation("VehicleEnrollment");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.HasOne("Server.Models.Address", "Address")
.WithMany("RouteAddresses")
.HasForeignKey("AddressId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.Route", "Route")
.WithMany("RouteAddresses")
.HasForeignKey("RouteId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Address");
b.Navigation("Route");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.HasOne("Server.Models.Country", "Country")
.WithMany("States")
.HasForeignKey("CountryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Country");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.HasOne("Server.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
.WithMany()
.HasForeignKey("VehicleEnrollmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
b.Navigation("VehicleEnrollment");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 =>
{
b1.Property<string>("UserId")
.HasColumnType("text");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("Created")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("Expires")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime?>("Revoked")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Token")
.IsRequired()
.HasColumnType("text");
b1.HasKey("UserId", "Id");
b1.ToTable("RefreshToken");
b1.WithOwner()
.HasForeignKey("UserId");
});
b.Navigation("RefreshTokens");
});
modelBuilder.Entity("Server.Models.Vehicle", b =>
{
b.HasOne("Server.Models.Company", "Company")
.WithMany("Vehicles")
.HasForeignKey("CompanyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Company");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.HasOne("Server.Models.Route", "Route")
.WithMany()
.HasForeignKey("RouteId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.Vehicle", "Vehicle")
.WithMany()
.HasForeignKey("VehicleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Route");
b.Navigation("Vehicle");
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.Navigation("RouteAddresses");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.Navigation("Addresses");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Navigation("Vehicles");
});
modelBuilder.Entity("Server.Models.Country", b =>
{
b.Navigation("States");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Navigation("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Navigation("Cities");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,133 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Server.Migrations
{
public partial class Replace_Composite_Keys_With_Single_Ones : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_Tickets",
table: "Tickets");
migrationBuilder.DropPrimaryKey(
name: "PK_RouteAddresses",
table: "RouteAddresses");
migrationBuilder.DropPrimaryKey(
name: "PK_Reviews",
table: "Reviews");
migrationBuilder.AddColumn<int>(
name: "Id",
table: "Tickets",
type: "integer",
nullable: false,
defaultValue: 0)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
migrationBuilder.AddColumn<int>(
name: "Id",
table: "RouteAddresses",
type: "integer",
nullable: false,
defaultValue: 0)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
migrationBuilder.AddColumn<int>(
name: "Id",
table: "Reviews",
type: "integer",
nullable: false,
defaultValue: 0)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
migrationBuilder.AddPrimaryKey(
name: "PK_Tickets",
table: "Tickets",
column: "Id");
migrationBuilder.AddPrimaryKey(
name: "PK_RouteAddresses",
table: "RouteAddresses",
column: "Id");
migrationBuilder.AddPrimaryKey(
name: "PK_Reviews",
table: "Reviews",
column: "Id");
migrationBuilder.CreateIndex(
name: "IX_Tickets_UserId",
table: "Tickets",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_RouteAddresses_RouteId",
table: "RouteAddresses",
column: "RouteId");
migrationBuilder.CreateIndex(
name: "IX_Reviews_UserId",
table: "Reviews",
column: "UserId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_Tickets",
table: "Tickets");
migrationBuilder.DropIndex(
name: "IX_Tickets_UserId",
table: "Tickets");
migrationBuilder.DropPrimaryKey(
name: "PK_RouteAddresses",
table: "RouteAddresses");
migrationBuilder.DropIndex(
name: "IX_RouteAddresses_RouteId",
table: "RouteAddresses");
migrationBuilder.DropPrimaryKey(
name: "PK_Reviews",
table: "Reviews");
migrationBuilder.DropIndex(
name: "IX_Reviews_UserId",
table: "Reviews");
migrationBuilder.DropColumn(
name: "Id",
table: "Tickets");
migrationBuilder.DropColumn(
name: "Id",
table: "RouteAddresses");
migrationBuilder.DropColumn(
name: "Id",
table: "Reviews");
migrationBuilder.AddPrimaryKey(
name: "PK_Tickets",
table: "Tickets",
columns: new[] { "UserId", "VehicleEnrollmentId" });
migrationBuilder.AddPrimaryKey(
name: "PK_RouteAddresses",
table: "RouteAddresses",
columns: new[] { "RouteId", "AddressId" });
migrationBuilder.AddPrimaryKey(
name: "PK_Reviews",
table: "Reviews",
columns: new[] { "UserId", "VehicleEnrollmentId" });
}
}
}

View File

@ -0,0 +1,793 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Server.Data;
#nullable disable
namespace Server.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20221113104931_Merge_departure_DateOnly_and_TimeOnly_into_DateTime_in_VehicleEnrollment")]
partial class Merge_departure_DateOnly_and_TimeOnly_into_DateTime_in_VehicleEnrollment
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CityId")
.HasColumnType("integer");
b.Property<double>("Latitude")
.HasColumnType("double precision");
b.Property<double>("Longitude")
.HasColumnType("double precision");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CityId");
b.ToTable("Addresses");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("StateId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("StateId");
b.ToTable("Cities");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.ToTable("Companies");
});
modelBuilder.Entity("Server.Models.Country", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Code")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Countries");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Comment")
.HasColumnType("text");
b.Property<int>("Rating")
.HasColumnType("integer");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Reviews");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Routes");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AddressId")
.HasColumnType("integer");
b.Property<double>("CostToNextCity")
.HasColumnType("double precision");
b.Property<int>("Order")
.HasColumnType("integer");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<TimeSpan>("TimeSpanToNextCity")
.HasColumnType("interval");
b.Property<TimeSpan>("WaitTimeSpan")
.HasColumnType("interval");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("CountryId")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CountryId");
b.ToTable("States");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsReturned")
.HasColumnType("boolean");
b.Property<DateTime>("PurchaseDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Server.Models.Vehicle", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("Capacity")
.HasColumnType("integer");
b.Property<int>("CompanyId")
.HasColumnType("integer");
b.Property<bool>("HasBelts")
.HasColumnType("boolean");
b.Property<bool>("HasClimateControl")
.HasColumnType("boolean");
b.Property<bool>("HasOutlet")
.HasColumnType("boolean");
b.Property<bool>("HasStewardess")
.HasColumnType("boolean");
b.Property<bool>("HasTV")
.HasColumnType("boolean");
b.Property<bool>("HasWC")
.HasColumnType("boolean");
b.Property<bool>("HasWiFi")
.HasColumnType("boolean");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CompanyId");
b.ToTable("Vehicles");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("CancelationComment")
.HasColumnType("text");
b.Property<TimeSpan?>("DelayTimeSpan")
.HasColumnType("interval");
b.Property<DateTime>("DepartureDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsCanceled")
.HasColumnType("boolean");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<int>("VehicleId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Server.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.HasOne("Server.Models.City", "City")
.WithMany("Addresses")
.HasForeignKey("CityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("City");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.HasOne("Server.Models.State", "State")
.WithMany("Cities")
.HasForeignKey("StateId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("State");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.HasOne("Server.Models.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.HasOne("Server.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
.WithMany()
.HasForeignKey("VehicleEnrollmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
b.Navigation("VehicleEnrollment");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.HasOne("Server.Models.Address", "Address")
.WithMany("RouteAddresses")
.HasForeignKey("AddressId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.Route", "Route")
.WithMany("RouteAddresses")
.HasForeignKey("RouteId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Address");
b.Navigation("Route");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.HasOne("Server.Models.Country", "Country")
.WithMany("States")
.HasForeignKey("CountryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Country");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.HasOne("Server.Models.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.VehicleEnrollment", "VehicleEnrollment")
.WithMany()
.HasForeignKey("VehicleEnrollmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
b.Navigation("VehicleEnrollment");
});
modelBuilder.Entity("Server.Models.User", b =>
{
b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 =>
{
b1.Property<string>("UserId")
.HasColumnType("text");
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property<int>("Id"));
b1.Property<DateTime>("Created")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime>("Expires")
.HasColumnType("timestamp with time zone");
b1.Property<DateTime?>("Revoked")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Token")
.IsRequired()
.HasColumnType("text");
b1.HasKey("UserId", "Id");
b1.ToTable("RefreshToken");
b1.WithOwner()
.HasForeignKey("UserId");
});
b.Navigation("RefreshTokens");
});
modelBuilder.Entity("Server.Models.Vehicle", b =>
{
b.HasOne("Server.Models.Company", "Company")
.WithMany("Vehicles")
.HasForeignKey("CompanyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Company");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
{
b.HasOne("Server.Models.Route", "Route")
.WithMany()
.HasForeignKey("RouteId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Server.Models.Vehicle", "Vehicle")
.WithMany()
.HasForeignKey("VehicleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Route");
b.Navigation("Vehicle");
});
modelBuilder.Entity("Server.Models.Address", b =>
{
b.Navigation("RouteAddresses");
});
modelBuilder.Entity("Server.Models.City", b =>
{
b.Navigation("Addresses");
});
modelBuilder.Entity("Server.Models.Company", b =>
{
b.Navigation("Vehicles");
});
modelBuilder.Entity("Server.Models.Country", b =>
{
b.Navigation("States");
});
modelBuilder.Entity("Server.Models.Route", b =>
{
b.Navigation("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
{
b.Navigation("Cities");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,103 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Server.Migrations
{
public partial class Merge_departure_DateOnly_and_TimeOnly_into_DateTime_in_VehicleEnrollment : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DepartureDateOnly",
table: "VehicleEnrollments");
migrationBuilder.DropColumn(
name: "DepartureTimeOnlyUtc",
table: "VehicleEnrollments");
migrationBuilder.AlterColumn<TimeSpan>(
name: "DelayTimeSpan",
table: "VehicleEnrollments",
type: "interval",
nullable: true,
oldClrType: typeof(TimeSpan),
oldType: "interval");
migrationBuilder.AlterColumn<string>(
name: "CancelationComment",
table: "VehicleEnrollments",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddColumn<DateTime>(
name: "DepartureDateTimeUtc",
table: "VehicleEnrollments",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AlterColumn<string>(
name: "Comment",
table: "Reviews",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DepartureDateTimeUtc",
table: "VehicleEnrollments");
migrationBuilder.AlterColumn<TimeSpan>(
name: "DelayTimeSpan",
table: "VehicleEnrollments",
type: "interval",
nullable: false,
defaultValue: new TimeSpan(0, 0, 0, 0, 0),
oldClrType: typeof(TimeSpan),
oldType: "interval",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "CancelationComment",
table: "VehicleEnrollments",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AddColumn<DateOnly>(
name: "DepartureDateOnly",
table: "VehicleEnrollments",
type: "date",
nullable: false,
defaultValue: new DateOnly(1, 1, 1));
migrationBuilder.AddColumn<TimeOnly>(
name: "DepartureTimeOnlyUtc",
table: "VehicleEnrollments",
type: "time without time zone",
nullable: false,
defaultValue: new TimeOnly(0, 0, 0));
migrationBuilder.AlterColumn<string>(
name: "Comment",
table: "Reviews",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
}
}
}

View File

@ -179,7 +179,7 @@ namespace Server.Migrations
b.HasIndex("CityId");
b.ToTable("Addresses", (string)null);
b.ToTable("Addresses");
});
modelBuilder.Entity("Server.Models.City", b =>
@ -201,7 +201,7 @@ namespace Server.Migrations
b.HasIndex("StateId");
b.ToTable("Cities", (string)null);
b.ToTable("Cities");
});
modelBuilder.Entity("Server.Models.Company", b =>
@ -224,7 +224,7 @@ namespace Server.Migrations
b.HasIndex("OwnerId");
b.ToTable("Companies", (string)null);
b.ToTable("Companies");
});
modelBuilder.Entity("Server.Models.Country", b =>
@ -245,29 +245,37 @@ namespace Server.Migrations
b.HasKey("Id");
b.ToTable("Countries", (string)null);
b.ToTable("Countries");
});
modelBuilder.Entity("Server.Models.Review", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Comment")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Rating")
.HasColumnType("integer");
b.HasKey("UserId", "VehicleEnrollmentId");
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", (string)null);
b.ToTable("Reviews");
});
modelBuilder.Entity("Server.Models.Route", b =>
@ -284,14 +292,17 @@ namespace Server.Migrations
b.HasKey("Id");
b.ToTable("Routes", (string)null);
b.ToTable("Routes");
});
modelBuilder.Entity("Server.Models.RouteAddress", b =>
{
b.Property<int>("RouteId")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AddressId")
.HasColumnType("integer");
@ -301,17 +312,22 @@ namespace Server.Migrations
b.Property<int>("Order")
.HasColumnType("integer");
b.Property<int>("RouteId")
.HasColumnType("integer");
b.Property<TimeSpan>("TimeSpanToNextCity")
.HasColumnType("interval");
b.Property<TimeSpan>("WaitTimeSpan")
.HasColumnType("interval");
b.HasKey("RouteId", "AddressId");
b.HasKey("Id");
b.HasIndex("AddressId");
b.ToTable("RouteAddresses", (string)null);
b.HasIndex("RouteId");
b.ToTable("RouteAddresses");
});
modelBuilder.Entity("Server.Models.State", b =>
@ -333,28 +349,37 @@ namespace Server.Migrations
b.HasIndex("CountryId");
b.ToTable("States", (string)null);
b.ToTable("States");
});
modelBuilder.Entity("Server.Models.Ticket", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<bool>("IsReturned")
.HasColumnType("boolean");
b.Property<DateTime>("PurchaseDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.HasKey("UserId", "VehicleEnrollmentId");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("VehicleEnrollmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VehicleEnrollmentId");
b.ToTable("Tickets", (string)null);
b.ToTable("Tickets");
});
modelBuilder.Entity("Server.Models.User", b =>
@ -474,7 +499,7 @@ namespace Server.Migrations
b.HasIndex("CompanyId");
b.ToTable("Vehicles", (string)null);
b.ToTable("Vehicles");
});
modelBuilder.Entity("Server.Models.VehicleEnrollment", b =>
@ -486,17 +511,13 @@ namespace Server.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("CancelationComment")
.IsRequired()
.HasColumnType("text");
b.Property<TimeSpan>("DelayTimeSpan")
b.Property<TimeSpan?>("DelayTimeSpan")
.HasColumnType("interval");
b.Property<DateOnly>("DepartureDateOnly")
.HasColumnType("date");
b.Property<TimeOnly>("DepartureTimeOnlyUtc")
.HasColumnType("time without time zone");
b.Property<DateTime>("DepartureDateTimeUtc")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsCanceled")
.HasColumnType("boolean");
@ -513,7 +534,7 @@ namespace Server.Migrations
b.HasIndex("VehicleId");
b.ToTable("VehicleEnrollments", (string)null);
b.ToTable("VehicleEnrollments");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
@ -670,7 +691,7 @@ namespace Server.Migrations
modelBuilder.Entity("Server.Models.User", b =>
{
b.OwnsMany("Server.Models.User.RefreshTokens#Server.Models.RefreshToken", "RefreshTokens", b1 =>
b.OwnsMany("Server.Models.RefreshToken", "RefreshTokens", b1 =>
{
b1.Property<string>("UserId")
.HasColumnType("text");
@ -696,7 +717,7 @@ namespace Server.Migrations
b1.HasKey("UserId", "Id");
b1.ToTable("RefreshToken", (string)null);
b1.ToTable("RefreshToken");
b1.WithOwner()
.HasForeignKey("UserId");

View File

@ -1,9 +1,13 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Server.Models;
public class Review
{
[Key]
public int Id { get; set; }
[ForeignKey("UserId")]
public string UserId { get; set; } = null!;
public User User { get; set; } = null!;
@ -13,5 +17,5 @@ public class Review
public VehicleEnrollment VehicleEnrollment { get; set; } = null!;
public int Rating { get; set; }
public string Comment { get; set; } = null!;
public string? Comment { get; set; }
}

View File

@ -1,10 +1,13 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using SharedModels.DataTransferObjects;
namespace Server.Models;
public class RouteAddress
{
[Key]
public int Id { get; set; }
[ForeignKey("RouteId")]
public int RouteId { get; set; }
public Route Route { get; set; } = null!;

View File

@ -1,9 +1,13 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Server.Models;
public class Ticket
{
[Key]
public int Id { get; set; }
[ForeignKey("UserId")]
public string UserId { get; set; } = null!;
public User User { get; set; } = null!;

View File

@ -16,11 +16,10 @@ public class VehicleEnrollment
public int RouteId { get; set; }
public Route Route { get; set; } = null!;
public DateOnly DepartureDateOnly { get; set; }
public TimeOnly DepartureTimeOnlyUtc { get; set; }
public DateTime DepartureDateTimeUtc { get; set; }
public TimeSpan DelayTimeSpan { get; set; }
public bool IsCanceled {get; set; }
public string CancelationComment { get; set; } = null!;
public TimeSpan? DelayTimeSpan { get; set; }
public bool IsCanceled { get; set; } = false;
public string? CancelationComment { get; set; } = null!;
}

View File

@ -11,6 +11,7 @@ using Server.Data;
using Server.Helpers;
using Server.Models;
using Server.Services;
using Route = Server.Models.Route;
var builder = WebApplication.CreateBuilder(args);
@ -94,18 +95,37 @@ builder.Services.AddScoped<ICountryManagementService, CountryManagementService>(
builder.Services.AddScoped<IStateManagementService, StateManagementService>();
builder.Services.AddScoped<ICityManagementService, CityManagementService>();
builder.Services.AddScoped<IAddressManagementService, AddressManagementService>();
builder.Services.AddScoped<IDateTimeService, DateTimeService>();
builder.Services.AddScoped<ITicketManagementService, TicketManagementService>();
builder.Services.AddScoped<IReviewManagementService, ReviewManagementService>();
builder.Services.AddScoped<ICompanyManagementService, CompanyManagementService>();
builder.Services.AddScoped<IVehicleManagementService, VehicleManagementService>();
builder.Services.AddScoped<IVehicleEnrollmentManagementService, VehicleEnrollmentManagementService>();
builder.Services.AddScoped<IRouteManagementService, RouteManagementService>();
builder.Services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
builder.Services.AddScoped<ISortHelper<Country>, SortHelper<Country>>();
builder.Services.AddScoped<ISortHelper<State>, SortHelper<State>>();
builder.Services.AddScoped<ISortHelper<City>, SortHelper<City>>();
builder.Services.AddScoped<ISortHelper<Address>, SortHelper<Address>>();
builder.Services.AddScoped<ISortHelper<Ticket>, SortHelper<Ticket>>();
builder.Services.AddScoped<ISortHelper<Review>, SortHelper<Review>>();
builder.Services.AddScoped<ISortHelper<Company>, SortHelper<Company>>();
builder.Services.AddScoped<ISortHelper<Vehicle>, SortHelper<Vehicle>>();
builder.Services.AddScoped<ISortHelper<VehicleEnrollment>, SortHelper<VehicleEnrollment>>();
builder.Services.AddScoped<ISortHelper<Route>, SortHelper<Route>>();
builder.Services.AddScoped<ISortHelper<RouteAddress>, SortHelper<RouteAddress>>();
builder.Services.AddScoped<IDataShaper<Country>, DataShaper<Country>>();
builder.Services.AddScoped<IDataShaper<State>, DataShaper<State>>();
builder.Services.AddScoped<IDataShaper<City>, DataShaper<City>>();
builder.Services.AddScoped<IDataShaper<Address>, DataShaper<Address>>();
builder.Services.AddScoped<IDataShaper<Ticket>, DataShaper<Ticket>>();
builder.Services.AddScoped<IDataShaper<Review>, DataShaper<Review>>();
builder.Services.AddScoped<IDataShaper<Company>, DataShaper<Company>>();
builder.Services.AddScoped<IDataShaper<Vehicle>, DataShaper<Vehicle>>();
builder.Services.AddScoped<IDataShaper<VehicleEnrollment>, DataShaper<VehicleEnrollment>>();
builder.Services.AddScoped<IDataShaper<Route>, DataShaper<Route>>();
builder.Services.AddScoped<IDataShaper<RouteAddress>, DataShaper<RouteAddress>>();
// Adding DB Context with PostgreSQL
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
@ -124,10 +144,10 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection();
// Data seeding
using var scope = app.Services.CreateScope();
var userManager = (UserManager<User>)scope.ServiceProvider.GetService(typeof(UserManager<User>))!;
var roleManager = (RoleManager<IdentityRole>)scope.ServiceProvider.GetService(typeof(RoleManager<IdentityRole>))!;
await ApplicationDbContextSeed.SeedEssentialsAsync(userManager, roleManager);
// using var scope = app.Services.CreateScope();
// var userManager = (UserManager<User>)scope.ServiceProvider.GetService(typeof(UserManager<User>))!;
// var roleManager = (RoleManager<IdentityRole>)scope.ServiceProvider.GetService(typeof(RoleManager<IdentityRole>))!;
// await ApplicationDbContextSeed.SeedEssentialsAsync(userManager, roleManager);
app.MapControllers();

View File

@ -43,8 +43,8 @@ public class AddressManagementService : IAddressManagementService
.AsQueryable();
SearchByAllAddressFields(ref dbAddresses, parameters.Search);
SearchByAddressName(ref dbAddresses, parameters.Name);
SearchByCityId(ref dbAddresses, parameters.CityId);
FilterByAddressName(ref dbAddresses, parameters.Name);
FilterByCityId(ref dbAddresses, parameters.CityId);
try
{
@ -79,7 +79,7 @@ public class AddressManagementService : IAddressManagementService
a.Name.ToLower().Contains(search.ToLower()));
}
void SearchByCityId(ref IQueryable<Address> addresses,
void FilterByCityId(ref IQueryable<Address> addresses,
int? cityId)
{
if (!addresses.Any() || cityId == null)
@ -90,7 +90,7 @@ public class AddressManagementService : IAddressManagementService
addresses = addresses.Where(a => a.CityId == cityId);
}
void SearchByAddressName(ref IQueryable<Address> addresses,
void FilterByAddressName(ref IQueryable<Address> addresses,
string? addressName)
{
if (!addresses.Any() || String.IsNullOrWhiteSpace(addressName))

View File

@ -43,8 +43,8 @@ public class CityManagementService : ICityManagementService
.AsQueryable();
SearchByAllCityFields(ref dbCities, parameters.Search);
SearchByCityName(ref dbCities, parameters.Name);
SearchByStateId(ref dbCities, parameters.StateId);
FilterByCityName(ref dbCities, parameters.Name);
FilterByStateId(ref dbCities, parameters.StateId);
try
{
@ -79,7 +79,7 @@ public class CityManagementService : ICityManagementService
s.Name.ToLower().Contains(search.ToLower()));
}
void SearchByStateId(ref IQueryable<City> cities,
void FilterByStateId(ref IQueryable<City> cities,
int? stateId)
{
if (!cities.Any() || stateId == null)
@ -90,7 +90,7 @@ public class CityManagementService : ICityManagementService
cities = cities.Where(s => s.StateId == stateId);
}
void SearchByCityName(ref IQueryable<City> cities,
void FilterByCityName(ref IQueryable<City> cities,
string? cityName)
{
if (!cities.Any() || String.IsNullOrWhiteSpace(cityName))

View File

@ -0,0 +1,183 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public class CompanyManagementService : ICompanyManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<Company> _companySortHelper;
private readonly IDataShaper<Company> _companyDataShaper;
public CompanyManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<Company> companySortHelper,
IDataShaper<Company> companyDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_companySortHelper = companySortHelper;
_companyDataShaper = companyDataShaper;
}
public async Task<(bool isSucceed, string message, CompanyDto company)> AddCompany(CreateCompanyDto createCompanyDto)
{
var company = _mapper.Map<Company>(createCompanyDto);
await _dbContext.Companies.AddAsync(company);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<CompanyDto>(company));
}
public async Task<(bool isSucceed, string message, IEnumerable<CompanyDto> companies,
PagingMetadata<Company> pagingMetadata)> GetCompanies(CompanyParameters parameters)
{
var dbCompanies = _dbContext.Companies
.AsQueryable();
var v = dbCompanies.Any();
SearchByAllCompanyFields(ref dbCompanies, parameters.Search);
FilterByCompanyName(ref dbCompanies, parameters.Name);
FilterByCompanyOwnerId(ref dbCompanies, parameters.OwnerId);
try
{
dbCompanies = _companySortHelper.ApplySort(dbCompanies, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbCompanies.Any();
}
catch (Exception e)
{
return (false, "Invalid sorting string", null, null)!;
}
var pagingMetadata = ApplyPaging(ref dbCompanies, parameters.PageNumber,
parameters.PageSize);
var shapedCompaniesData = _companyDataShaper.ShapeData(dbCompanies, parameters.Fields);
var companyDtos = shapedCompaniesData.ToList().ConvertAll(c => _mapper.Map<CompanyDto>(c));
return (true, "", companyDtos, pagingMetadata);
void SearchByAllCompanyFields(ref IQueryable<Company> companies,
string? search)
{
if (!companies.Any() || String.IsNullOrWhiteSpace(search))
{
return;
}
companies = companies.Where(c =>
c.Name.ToLower().Contains(search.ToLower()));
}
void FilterByCompanyName(ref IQueryable<Company> companies,
string? name)
{
if (!companies.Any() || String.IsNullOrWhiteSpace(name))
{
return;
}
companies = companies.Where(c => c.Name == name);
}
void FilterByCompanyOwnerId(ref IQueryable<Company> companies,
string? ownerId)
{
if (!companies.Any() || String.IsNullOrWhiteSpace(ownerId))
{
return;
}
companies = companies.Where(c => c.OwnerId == ownerId);
}
PagingMetadata<Company> ApplyPaging(ref IQueryable<Company> companies,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<Company>(companies,
pageNumber, pageSize);
companies = companies
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, CompanyDto company)> GetCompany(int id, string? fields)
{
var dbCompany = await _dbContext.Companies.Where(c => c.Id == id)
.FirstOrDefaultAsync();
if (dbCompany == null)
{
return (false, $"Company doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = CompanyParameters.DefaultFields;
}
var shapedCompanyData = _companyDataShaper.ShapeData(dbCompany, fields);
var companyDto = _mapper.Map<CompanyDto>(shapedCompanyData);
return (true, "", companyDto);
}
public async Task<(bool isSucceed, string message, UpdateCompanyDto company)> UpdateCompany(UpdateCompanyDto updateCompanyDto)
{
var company = _mapper.Map<Company>(updateCompanyDto);
_dbContext.Entry(company).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsCompanyExists(updateCompanyDto.Id))
{
return (false, $"Company with id:{updateCompanyDto.Id} doesn'c exist", null)!;
}
throw;
}
var dbCompany = await _dbContext.Companies.FirstOrDefaultAsync(c => c.Id == company.Id);
return (true, String.Empty, _mapper.Map<UpdateCompanyDto>(dbCompany));
}
public async Task<(bool isSucceed, string message)> DeleteCompany(int id)
{
var dbCompany = await _dbContext.Companies.FirstOrDefaultAsync(c => c.Id == id);
if (dbCompany == null)
{
return (false, $"Company with id:{id} doesn't exist");
}
_dbContext.Companies.Remove(dbCompany);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsCompanyExists(int id)
{
return await _dbContext.Companies.AnyAsync(c => c.Id == id);
}
}

View File

@ -44,8 +44,8 @@ public class CountryManagementService : ICountryManagementService
.AsQueryable();
SearchByAllCountryFields(ref dbCountries, parameters.Search);
SearchByCountryCode(ref dbCountries, parameters.Code);
SearchByCountryName(ref dbCountries, parameters.Name);
FilterByCountryCode(ref dbCountries, parameters.Code);
FilterByCountryName(ref dbCountries, parameters.Name);
try
{
@ -81,7 +81,7 @@ public class CountryManagementService : ICountryManagementService
c.Name.ToLower().Contains(search.ToLower()));
}
void SearchByCountryCode(ref IQueryable<Country> countries,
void FilterByCountryCode(ref IQueryable<Country> countries,
string? countryCode)
{
if (!countries.Any() || String.IsNullOrWhiteSpace(countryCode))
@ -93,7 +93,7 @@ public class CountryManagementService : ICountryManagementService
c.Code.ToLower().Contains(countryCode.Trim().ToLower()));
}
void SearchByCountryName(ref IQueryable<Country> countries,
void FilterByCountryName(ref IQueryable<Country> countries,
string? countryName)
{
if (!countries.Any() || String.IsNullOrWhiteSpace(countryName))

View File

@ -7,7 +7,6 @@ namespace Server.Services;
public interface IAddressManagementService
{
Task<(bool isSucceed, string message, AddressDto address)> AddAddress(CreateAddressDto createAddressDto);
Task<(bool isSucceed, string message, IEnumerable<AddressDto> addresses,
PagingMetadata<Address> pagingMetadata)> GetAddresses(AddressParameters parameters);
Task<(bool isSucceed, string message, AddressDto address)> GetAddress(int id, string? fields);

View File

@ -7,7 +7,6 @@ namespace Server.Services;
public interface ICityManagementService
{
Task<(bool isSucceed, string message, CityDto city)> AddCity(CreateCityDto createCityDto);
Task<(bool isSucceed, string message, IEnumerable<CityDto> cities,
PagingMetadata<City> pagingMetadata)> GetCities(CityParameters parameters);
Task<(bool isSucceed, string message, CityDto city)> GetCity(int id, string? fields);

View File

@ -0,0 +1,16 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public interface ICompanyManagementService
{
Task<(bool isSucceed, string message, CompanyDto company)> AddCompany(CreateCompanyDto createCompanyDto);
Task<(bool isSucceed, string message, IEnumerable<CompanyDto> companies,
PagingMetadata<Company> pagingMetadata)> GetCompanies(CompanyParameters parameters);
Task<(bool isSucceed, string message, CompanyDto company)> GetCompany(int id, string? fields);
Task<(bool isSucceed, string message, UpdateCompanyDto company)> UpdateCompany(UpdateCompanyDto updateCompanyDto);
Task<(bool isSucceed, string message)> DeleteCompany(int id);
Task<bool> IsCompanyExists(int id);
}

View File

@ -7,7 +7,6 @@ namespace Server.Services;
public interface ICountryManagementService
{
Task<(bool isSucceed, string message, CountryDto country)> AddCountry(CreateCountryDto createCountryDto);
Task<(bool isSucceed, string message, IEnumerable<CountryDto> countries,
PagingMetadata<Country> pagingMetadata)> GetCountries(CountryParameters parameters);
Task<(bool isSucceed, string message, CountryDto country)> GetCountry(int id, string? fields);

View File

@ -0,0 +1,16 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public interface IReviewManagementService
{
Task<(bool isSucceed, string message, ReviewDto review)> AddReview(CreateReviewDto createReviewDto);
Task<(bool isSucceed, string message, IEnumerable<ReviewDto> reviews,
PagingMetadata<Review> pagingMetadata)> GetReviews(ReviewParameters parameters);
Task<(bool isSucceed, string message, ReviewDto review)> GetReview(int id, string? fields);
Task<(bool isSucceed, string message, UpdateReviewDto review)> UpdateReview(UpdateReviewDto updateReviewDto);
Task<(bool isSucceed, string message)> DeleteReview(int id);
Task<bool> IsReviewExists(int id);
}

View File

@ -0,0 +1,16 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public interface IRouteAddressManagementService
{
Task<(bool isSucceed, string message, RouteAddressDto routeAddress)> AddRouteAddress(CreateRouteAddressDto createRouteAddressDto);
Task<(bool isSucceed, string message, IEnumerable<RouteAddressDto> routeAddresses,
PagingMetadata<RouteAddress> pagingMetadata)> GetRouteAddresses(RouteAddressParameters parameters);
Task<(bool isSucceed, string message, RouteAddressDto routeAddress)> GetRouteAddress(int id, string? fields);
Task<(bool isSucceed, string message, UpdateRouteAddressDto routeAddress)> UpdateRouteAddress(UpdateRouteAddressDto updateRouteAddressDto);
Task<(bool isSucceed, string message)> DeleteRouteAddress(int id);
Task<bool> IsRouteAddressExists(int id);
}

View File

@ -0,0 +1,16 @@
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using Route = Server.Models.Route;
namespace Server.Services;
public interface IRouteManagementService
{
Task<(bool isSucceed, string message, RouteDto route)> AddRoute(CreateRouteDto createRouteDto);
Task<(bool isSucceed, string message, IEnumerable<RouteDto> routes,
PagingMetadata<Route> pagingMetadata)> GetRoutes(RouteParameters parameters);
Task<(bool isSucceed, string message, RouteDto route)> GetRoute(int id, string? fields);
Task<(bool isSucceed, string message, UpdateRouteDto route)> UpdateRoute(UpdateRouteDto updateRouteDto);
Task<(bool isSucceed, string message)> DeleteRoute(int id);
Task<bool> IsRouteExists(int id);
}

View File

@ -7,7 +7,6 @@ namespace Server.Services;
public interface IStateManagementService
{
Task<(bool isSucceed, string message, StateDto state)> AddState(CreateStateDto createStateDto);
Task<(bool isSucceed, string message, IEnumerable<StateDto> states,
PagingMetadata<State> pagingMetadata)> GetStates(StateParameters parameters);
Task<(bool isSucceed, string message, StateDto state)> GetState(int id, string? fields);

View File

@ -0,0 +1,16 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public interface ITicketManagementService
{
Task<(bool isSucceed, string message, TicketDto ticket)> AddTicket(CreateTicketDto createTicketDto);
Task<(bool isSucceed, string message, IEnumerable<TicketDto> tickets,
PagingMetadata<Ticket> pagingMetadata)> GetTickets(TicketParameters parameters);
Task<(bool isSucceed, string message, TicketDto ticket)> GetTicket(int id, string? fields);
Task<(bool isSucceed, string message, UpdateTicketDto ticket)> UpdateTicket(UpdateTicketDto updateTicketDto);
Task<(bool isSucceed, string message)> DeleteTicket(int id);
Task<bool> IsTicketExists(int id);
}

View File

@ -0,0 +1,16 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public interface IVehicleEnrollmentManagementService
{
Task<(bool isSucceed, string message, VehicleEnrollmentDto enrollment)> AddEnrollment(CreateVehicleEnrollmentDto createEnrollmentDto);
Task<(bool isSucceed, string message, IEnumerable<VehicleEnrollmentDto> enrollments,
PagingMetadata<VehicleEnrollment> pagingMetadata)> GetEnrollments(VehicleEnrollmentParameters parameters);
Task<(bool isSucceed, string message, VehicleEnrollmentDto enrollment)> GetEnrollment(int id, string? fields);
Task<(bool isSucceed, string message, UpdateVehicleEnrollmentDto enrollment)> UpdateEnrollment(UpdateVehicleEnrollmentDto updateEnrollmentDto);
Task<(bool isSucceed, string message)> DeleteEnrollment(int id);
Task<bool> IsEnrollmentExists(int id);
}

View File

@ -0,0 +1,16 @@
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public interface IVehicleManagementService
{
Task<(bool isSucceed, string message, VehicleDto vehicle)> AddVehicle(CreateVehicleDto createVehicleDto);
Task<(bool isSucceed, string message, IEnumerable<VehicleDto> vehicles,
PagingMetadata<Vehicle> pagingMetadata)> GetVehicles(VehicleParameters parameters);
Task<(bool isSucceed, string message, VehicleDto vehicle)> GetVehicle(int id, string? fields);
Task<(bool isSucceed, string message, UpdateVehicleDto vehicle)> UpdateVehicle(UpdateVehicleDto updateVehicleDto);
Task<(bool isSucceed, string message)> DeleteVehicle(int id);
Task<bool> IsVehicleExists(int id);
}

View File

@ -0,0 +1,170 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public class ReviewManagementService : IReviewManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<Review> _reviewSortHelper;
private readonly IDataShaper<Review> _reviewDataShaper;
public ReviewManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<Review> reviewSortHelper,
IDataShaper<Review> reviewDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_reviewSortHelper = reviewSortHelper;
_reviewDataShaper = reviewDataShaper;
}
public async Task<(bool isSucceed, string message, ReviewDto review)> AddReview(CreateReviewDto createReviewDto)
{
var review = _mapper.Map<Review>(createReviewDto);
await _dbContext.Reviews.AddAsync(review);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<ReviewDto>(review));
}
public async Task<(bool isSucceed, string message, IEnumerable<ReviewDto> reviews,
PagingMetadata<Review> pagingMetadata)> GetReviews(ReviewParameters parameters)
{
var dbReviews = _dbContext.Reviews
.AsQueryable();
FilterByReviewRating(ref dbReviews, parameters.Rating);
FilterByReviewComment(ref dbReviews, parameters.Comment);
try
{
dbReviews = _reviewSortHelper.ApplySort(dbReviews, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbReviews.Any();
}
catch (Exception e)
{
return (false, "Invalid sorting string", null, null)!;
}
var pagingMetadata = ApplyPaging(ref dbReviews, parameters.PageNumber,
parameters.PageSize);
var shapedReviewsData = _reviewDataShaper.ShapeData(dbReviews, parameters.Fields);
var reviewDtos = shapedReviewsData.ToList().ConvertAll(r => _mapper.Map<ReviewDto>(r));
return (true, "", reviewDtos, pagingMetadata);
void FilterByReviewRating(ref IQueryable<Review> reviews,
int? rating)
{
if (!reviews.Any() || rating == null)
{
return;
}
reviews = reviews.Where(r => r.Rating == rating);
}
void FilterByReviewComment(ref IQueryable<Review> reviews,
string? comment)
{
if (!reviews.Any() || String.IsNullOrWhiteSpace(comment))
{
return;
}
reviews = reviews.Where(r =>
r.Comment != null &&
r.Comment.ToLower().Contains(comment.ToLower()));
}
PagingMetadata<Review> ApplyPaging(ref IQueryable<Review> reviews,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<Review>(reviews,
pageNumber, pageSize);
reviews = reviews
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, ReviewDto review)> GetReview(int id, string? fields)
{
var dbReview = await _dbContext.Reviews.Where(r => r.Id == id)
.FirstOrDefaultAsync();
if (dbReview == null)
{
return (false, $"Review doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = ReviewParameters.DefaultFields;
}
var shapedReviewData = _reviewDataShaper.ShapeData(dbReview, fields);
var reviewDto = _mapper.Map<ReviewDto>(shapedReviewData);
return (true, "", reviewDto);
}
public async Task<(bool isSucceed, string message, UpdateReviewDto review)> UpdateReview(UpdateReviewDto updateReviewDto)
{
var review = _mapper.Map<Review>(updateReviewDto);
_dbContext.Entry(review).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsReviewExists(updateReviewDto.Id))
{
return (false, $"Review with id:{updateReviewDto.Id} doesn't exist", null)!;
}
throw;
}
var dbReview = await _dbContext.Reviews.FirstOrDefaultAsync(r => r.Id == review.Id);
return (true, String.Empty, _mapper.Map<UpdateReviewDto>(dbReview));
}
public async Task<(bool isSucceed, string message)> DeleteReview(int id)
{
var dbReview = await _dbContext.Reviews.FirstOrDefaultAsync(r => r.Id == id);
if (dbReview == null)
{
return (false, $"Review with id:{id} doesn't exist");
}
_dbContext.Reviews.Remove(dbReview);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsReviewExists(int id)
{
return await _dbContext.Reviews.AnyAsync(r => r.Id == id);
}
}

View File

@ -0,0 +1,168 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public class RouteAddressManagementService : IRouteAddressManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<RouteAddress> _routeAddressSortHelper;
private readonly IDataShaper<RouteAddress> _routeAddressDataShaper;
public RouteAddressManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<RouteAddress> routeAddressSortHelper,
IDataShaper<RouteAddress> routeAddressDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_routeAddressSortHelper = routeAddressSortHelper;
_routeAddressDataShaper = routeAddressDataShaper;
}
public async Task<(bool isSucceed, string message, RouteAddressDto routeAddress)> AddRouteAddress(CreateRouteAddressDto createRouteAddressDto)
{
var routeAddress = _mapper.Map<RouteAddress>(createRouteAddressDto);
await _dbContext.RouteAddresses.AddAsync(routeAddress);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<RouteAddressDto>(routeAddress));
}
public async Task<(bool isSucceed, string message, IEnumerable<RouteAddressDto> routeAddresses,
PagingMetadata<RouteAddress> pagingMetadata)> GetRouteAddresses(RouteAddressParameters parameters)
{
var dbRouteAddresses = _dbContext.RouteAddresses
.AsQueryable();
FilterByRouteAddressRouteId(ref dbRouteAddresses, parameters.RouteId);
FilterByRouteAddressAddressId(ref dbRouteAddresses, parameters.AddressId);
try
{
dbRouteAddresses = _routeAddressSortHelper.ApplySort(dbRouteAddresses, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbRouteAddresses.Any();
}
catch (Exception e)
{
return (false, "Invalid sorting string", null, null)!;
}
var pagingMetadata = ApplyPaging(ref dbRouteAddresses, parameters.PageNumber,
parameters.PageSize);
var shapedRouteAddressesData = _routeAddressDataShaper.ShapeData(dbRouteAddresses, parameters.Fields);
var routeAddressDtos = shapedRouteAddressesData.ToList().ConvertAll(ra => _mapper.Map<RouteAddressDto>(ra));
return (true, "", routeAddressDtos, pagingMetadata);
void FilterByRouteAddressRouteId(ref IQueryable<RouteAddress> routeAddresses,
int? routeId)
{
if (!routeAddresses.Any() || routeId == null)
{
return;
}
routeAddresses = routeAddresses.Where(ra => ra.RouteId == routeId);
}
void FilterByRouteAddressAddressId(ref IQueryable<RouteAddress> routeAddresses,
int? addressId)
{
if (!routeAddresses.Any() || addressId == null)
{
return;
}
routeAddresses = routeAddresses.Where(ra => ra.AddressId == addressId);
}
PagingMetadata<RouteAddress> ApplyPaging(ref IQueryable<RouteAddress> routeAddresses,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<RouteAddress>(routeAddresses,
pageNumber, pageSize);
routeAddresses = routeAddresses
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, RouteAddressDto routeAddress)> GetRouteAddress(int id, string? fields)
{
var dbRouteAddress = await _dbContext.RouteAddresses.Where(ra => ra.Id == id)
.FirstOrDefaultAsync();
if (dbRouteAddress == null)
{
return (false, $"RouteAddress doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = RouteAddressParameters.DefaultFields;
}
var shapedRouteAddressData = _routeAddressDataShaper.ShapeData(dbRouteAddress, fields);
var routeAddressDto = _mapper.Map<RouteAddressDto>(shapedRouteAddressData);
return (true, "", routeAddressDto);
}
public async Task<(bool isSucceed, string message, UpdateRouteAddressDto routeAddress)> UpdateRouteAddress(UpdateRouteAddressDto updateRouteAddressDto)
{
var routeAddress = _mapper.Map<RouteAddress>(updateRouteAddressDto);
_dbContext.Entry(routeAddress).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsRouteAddressExists(updateRouteAddressDto.Id))
{
return (false, $"RouteAddress with id:{updateRouteAddressDto.Id} doesn't exist", null)!;
}
throw;
}
var dbRouteAddress = await _dbContext.RouteAddresses.FirstOrDefaultAsync(ra => ra.Id == routeAddress.Id);
return (true, String.Empty, _mapper.Map<UpdateRouteAddressDto>(dbRouteAddress));
}
public async Task<(bool isSucceed, string message)> DeleteRouteAddress(int id)
{
var dbRouteAddress = await _dbContext.RouteAddresses.FirstOrDefaultAsync(ra => ra.Id == id);
if (dbRouteAddress == null)
{
return (false, $"RouteAddress with id:{id} doesn't exist");
}
_dbContext.RouteAddresses.Remove(dbRouteAddress);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsRouteAddressExists(int id)
{
return await _dbContext.RouteAddresses.AnyAsync(ra => ra.Id == id);
}
}

View File

@ -0,0 +1,170 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
using Route = Server.Models.Route;
namespace Server.Services;
public class RouteManagementService : IRouteManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<Route> _routeSortHelper;
private readonly IDataShaper<Route> _routeDataShaper;
public RouteManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<Route> routeSortHelper,
IDataShaper<Route> routeDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_routeSortHelper = routeSortHelper;
_routeDataShaper = routeDataShaper;
}
public async Task<(bool isSucceed, string message, RouteDto route)> AddRoute(CreateRouteDto createRouteDto)
{
var route = _mapper.Map<Route>(createRouteDto);
await _dbContext.Routes.AddAsync(route);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<RouteDto>(route));
}
public async Task<(bool isSucceed, string message, IEnumerable<RouteDto> routes,
PagingMetadata<Route> pagingMetadata)> GetRoutes(RouteParameters parameters)
{
var dbRoutes = _dbContext.Routes
.AsQueryable();
SearchByAllRouteFields(ref dbRoutes, parameters.Search);
FilterByRouteType(ref dbRoutes, parameters.Type);
try
{
dbRoutes = _routeSortHelper.ApplySort(dbRoutes, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbRoutes.Any();
}
catch (Exception e)
{
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);
void SearchByAllRouteFields(ref IQueryable<Route> route,
string? search)
{
if (!route.Any() || String.IsNullOrWhiteSpace(search))
{
return;
}
route = route.Where(c =>
c.Type.ToLower().Contains(search.ToLower()));
}
void FilterByRouteType(ref IQueryable<Route> routes,
string? type)
{
if (!routes.Any() || String.IsNullOrWhiteSpace(type))
{
return;
}
routes = routes.Where(r => r.Type == type);
}
PagingMetadata<Route> ApplyPaging(ref IQueryable<Route> routes,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<Route>(routes,
pageNumber, pageSize);
routes = routes
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, RouteDto route)> GetRoute(int id, string? fields)
{
var dbRoute = await _dbContext.Routes.Where(r => r.Id == id)
.FirstOrDefaultAsync();
if (dbRoute == null)
{
return (false, $"Route doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = RouteParameters.DefaultFields;
}
var shapedRouteData = _routeDataShaper.ShapeData(dbRoute, fields);
var routeDto = _mapper.Map<RouteDto>(shapedRouteData);
return (true, "", routeDto);
}
public async Task<(bool isSucceed, string message, UpdateRouteDto route)> UpdateRoute(UpdateRouteDto updateRouteDto)
{
var route = _mapper.Map<Route>(updateRouteDto);
_dbContext.Entry(route).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsRouteExists(updateRouteDto.Id))
{
return (false, $"Route with id:{updateRouteDto.Id} doesn't exist", null)!;
}
throw;
}
var dbRoute = await _dbContext.Routes.FirstOrDefaultAsync(r => r.Id == route.Id);
return (true, String.Empty, _mapper.Map<UpdateRouteDto>(dbRoute));
}
public async Task<(bool isSucceed, string message)> DeleteRoute(int id)
{
var dbRoute = await _dbContext.Routes.FirstOrDefaultAsync(r => r.Id == id);
if (dbRoute == null)
{
return (false, $"Route with id:{id} doesn't exist");
}
_dbContext.Routes.Remove(dbRoute);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsRouteExists(int id)
{
return await _dbContext.Routes.AnyAsync(r => r.Id == id);
}
}

View File

@ -44,8 +44,8 @@ public class StateManagementService : IStateManagementService
.ThenInclude(c => c.Addresses).AsQueryable();
SearchByAllStateFields(ref dbStates, parameters.Search);
SearchByStateName(ref dbStates, parameters.Name);
SearchByCountryId(ref dbStates, parameters.CountryId);
FilterByStateName(ref dbStates, parameters.Name);
FilterByCountryId(ref dbStates, parameters.CountryId);
try
{
@ -80,7 +80,7 @@ public class StateManagementService : IStateManagementService
s.Name.ToLower().Contains(search.ToLower()));
}
void SearchByCountryId(ref IQueryable<State> states,
void FilterByCountryId(ref IQueryable<State> states,
int? countryId)
{
if (!states.Any() || countryId == null)
@ -91,7 +91,7 @@ public class StateManagementService : IStateManagementService
states = states.Where(s => s.CountryId == countryId);
}
void SearchByStateName(ref IQueryable<State> states,
void FilterByStateName(ref IQueryable<State> states,
string? stateName)
{
if (!states.Any() || String.IsNullOrWhiteSpace(stateName))

View File

@ -0,0 +1,172 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public class TicketManagementService : ITicketManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<Ticket> _ticketSortHelper;
private readonly IDataShaper<Ticket> _ticketDataShaper;
public TicketManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<Ticket> ticketSortHelper,
IDataShaper<Ticket> ticketDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_ticketSortHelper = ticketSortHelper;
_ticketDataShaper = ticketDataShaper;
}
public async Task<(bool isSucceed, string message, TicketDto ticket)> AddTicket(CreateTicketDto createTicketDto)
{
var ticket = _mapper.Map<Ticket>(createTicketDto);
await _dbContext.Tickets.AddAsync(ticket);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<TicketDto>(ticket));
}
public async Task<(bool isSucceed, string message, IEnumerable<TicketDto> tickets,
PagingMetadata<Ticket> pagingMetadata)> GetTickets(TicketParameters parameters)
{
var dbTickets = _dbContext.Tickets
.AsQueryable();
FilterByTicketPurchaseDateTime(ref dbTickets,
parameters.FromPurchaseDateTimeUtc,
parameters.ToPurchaseDateTimeUtc);
FilterByTicketReturnedState(ref dbTickets, parameters.IsReturned);
try
{
dbTickets = _ticketSortHelper.ApplySort(dbTickets, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbTickets.Any();
}
catch (Exception e)
{
return (false, "Invalid sorting string", null, null)!;
}
var pagingMetadata = ApplyPaging(ref dbTickets, parameters.PageNumber,
parameters.PageSize);
var shapedTicketsData = _ticketDataShaper.ShapeData(dbTickets, parameters.Fields);
var ticketDtos = shapedTicketsData.ToList().ConvertAll(t => _mapper.Map<TicketDto>(t));
return (true, "", ticketDtos, pagingMetadata);
void FilterByTicketPurchaseDateTime(ref IQueryable<Ticket> tickets,
DateTime? fromDateTime, DateTime? toDateTime)
{
if (!tickets.Any() || fromDateTime == null || toDateTime == null)
{
return;
}
tickets = tickets.Where(t =>
t.PurchaseDateTimeUtc >= fromDateTime.Value.ToUniversalTime() &&
t.PurchaseDateTimeUtc <= toDateTime.Value.ToUniversalTime());
}
void FilterByTicketReturnedState(ref IQueryable<Ticket> tickets,
bool? isReturned)
{
if (!tickets.Any() || !isReturned.HasValue)
{
return;
}
tickets = tickets.Where(t => t.IsReturned == isReturned);
}
PagingMetadata<Ticket> ApplyPaging(ref IQueryable<Ticket> tickets,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<Ticket>(tickets,
pageNumber, pageSize);
tickets = tickets
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, TicketDto ticket)> GetTicket(int id, string? fields)
{
var dbTicket = await _dbContext.Tickets.Where(t => t.Id == id)
.FirstOrDefaultAsync();
if (dbTicket == null)
{
return (false, $"Ticket doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = TicketParameters.DefaultFields;
}
var shapedTicketData = _ticketDataShaper.ShapeData(dbTicket, fields);
var ticketDto = _mapper.Map<TicketDto>(shapedTicketData);
return (true, "", ticketDto);
}
public async Task<(bool isSucceed, string message, UpdateTicketDto ticket)> UpdateTicket(UpdateTicketDto updateTicketDto)
{
var ticket = _mapper.Map<Ticket>(updateTicketDto);
_dbContext.Entry(ticket).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsTicketExists(updateTicketDto.Id))
{
return (false, $"Ticket with id:{updateTicketDto.Id} doesn't exist", null)!;
}
throw;
}
var dbTicket = await _dbContext.Tickets.FirstOrDefaultAsync(t => t.Id == ticket.Id);
return (true, String.Empty, _mapper.Map<UpdateTicketDto>(dbTicket));
}
public async Task<(bool isSucceed, string message)> DeleteTicket(int id)
{
var dbTicket = await _dbContext.Tickets.FirstOrDefaultAsync(t => t.Id == id);
if (dbTicket == null)
{
return (false, $"Ticket with id:{id} doesn't exist");
}
_dbContext.Tickets.Remove(dbTicket);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsTicketExists(int id)
{
return await _dbContext.Tickets.AnyAsync(t => t.Id == id);
}
}

View File

@ -0,0 +1,222 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public class VehicleEnrollmentManagementService : IVehicleEnrollmentManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<VehicleEnrollment> _enrollmentSortHelper;
private readonly IDataShaper<VehicleEnrollment> _enrollmentDataShaper;
public VehicleEnrollmentManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<VehicleEnrollment> enrollmentSortHelper,
IDataShaper<VehicleEnrollment> enrollmentDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_enrollmentSortHelper = enrollmentSortHelper;
_enrollmentDataShaper = enrollmentDataShaper;
}
public async Task<(bool isSucceed, string message, VehicleEnrollmentDto enrollment)> AddEnrollment(CreateVehicleEnrollmentDto createEnrollmentDto)
{
var enrollment = _mapper.Map<VehicleEnrollment>(createEnrollmentDto);
await _dbContext.VehicleEnrollments.AddAsync(enrollment);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<VehicleEnrollmentDto>(enrollment));
}
public async Task<(bool isSucceed, string message, IEnumerable<VehicleEnrollmentDto> enrollments,
PagingMetadata<VehicleEnrollment> pagingMetadata)> GetEnrollments(VehicleEnrollmentParameters parameters)
{
var dbEnrollments = _dbContext.VehicleEnrollments
.AsQueryable();
SearchByAllEnrollmentFields(ref dbEnrollments, parameters.Search);
FilterByEnrollmentVehicleId(ref dbEnrollments, parameters.VehicleId);
FilterByEnrollmentRouteId(ref dbEnrollments, parameters.RouteId);
FilterByEnrollmentDepartureDateTime(ref dbEnrollments,
parameters.FromDepartureDateTime, parameters.ToDepartureDateTime);
FilterByEnrollmentDelayedValue(ref dbEnrollments, parameters.IsDelayed);
FilterByEnrollmentCancelledValue(ref dbEnrollments, parameters.IsCanceled);
try
{
dbEnrollments = _enrollmentSortHelper.ApplySort(dbEnrollments, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbEnrollments.Any();
}
catch (Exception e)
{
return (false, "Invalid sorting string", null, null)!;
}
var pagingMetadata = ApplyPaging(ref dbEnrollments, parameters.PageNumber,
parameters.PageSize);
var shapedEnrollmentsData = _enrollmentDataShaper.ShapeData(dbEnrollments, parameters.Fields);
var enrollmentDtos = shapedEnrollmentsData.ToList().ConvertAll(e => _mapper.Map<VehicleEnrollmentDto>(e));
return (true, "", enrollmentDtos, pagingMetadata);
void SearchByAllEnrollmentFields(ref IQueryable<VehicleEnrollment> enrollment,
string? search)
{
if (!enrollment.Any() || String.IsNullOrWhiteSpace(search))
{
return;
}
enrollment = enrollment.Where(e =>
e.CancelationComment.ToLower().Contains(search.ToLower()));
}
void FilterByEnrollmentVehicleId(ref IQueryable<VehicleEnrollment> enrollments,
int? vehicleId)
{
if (!enrollments.Any() || vehicleId == null)
{
return;
}
enrollments = enrollments.Where(e => e.VehicleId == vehicleId);
}
void FilterByEnrollmentRouteId(ref IQueryable<VehicleEnrollment> enrollments,
int? routeId)
{
if (!enrollments.Any() || routeId == null)
{
return;
}
enrollments = enrollments.Where(e => e.RouteId == routeId);
}
void FilterByEnrollmentDepartureDateTime(ref IQueryable<VehicleEnrollment> enrollments,
DateTime? fromDateTime, DateTime? toDateTime)
{
if (!enrollments.Any() || fromDateTime == null || toDateTime == null)
{
return;
}
enrollments = enrollments.Where(e =>
e.DepartureDateTimeUtc >= fromDateTime.Value.ToUniversalTime() &&
e.DepartureDateTimeUtc <= toDateTime.Value.ToUniversalTime());
}
void FilterByEnrollmentDelayedValue(ref IQueryable<VehicleEnrollment> enrollments,
bool? isDelayed)
{
if (!enrollments.Any() || !isDelayed.HasValue)
{
return;
}
enrollments = isDelayed.Value
? enrollments.Where(e => e.DelayTimeSpan != null)
: enrollments.Where(e => e.DelayTimeSpan == null);
}
void FilterByEnrollmentCancelledValue(ref IQueryable<VehicleEnrollment> enrollments,
bool? isCancelled)
{
if (!enrollments.Any() || !isCancelled.HasValue)
{
return;
}
enrollments = enrollments.Where(e => e.IsCanceled == isCancelled);
}
PagingMetadata<VehicleEnrollment> ApplyPaging(ref IQueryable<VehicleEnrollment> enrollments,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<VehicleEnrollment>(enrollments,
pageNumber, pageSize);
enrollments = enrollments
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, VehicleEnrollmentDto enrollment)> GetEnrollment(int id, string? fields)
{
var dbEnrollment = await _dbContext.VehicleEnrollments.Where(e => e.Id == id)
.FirstOrDefaultAsync();
if (dbEnrollment == null)
{
return (false, $"Enrollment doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = VehicleEnrollmentParameters.DefaultFields;
}
var shapedEnrollmentData = _enrollmentDataShaper.ShapeData(dbEnrollment, fields);
var enrollmentDto = _mapper.Map<VehicleEnrollmentDto>(shapedEnrollmentData);
return (true, "", enrollmentDto);
}
public async Task<(bool isSucceed, string message, UpdateVehicleEnrollmentDto enrollment)> UpdateEnrollment(UpdateVehicleEnrollmentDto updateEnrollmentDto)
{
var enrollment = _mapper.Map<VehicleEnrollment>(updateEnrollmentDto);
_dbContext.Entry(enrollment).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsEnrollmentExists(updateEnrollmentDto.Id))
{
return (false, $"Enrollment with id:{updateEnrollmentDto.Id} doesn't exist", null)!;
}
throw;
}
var dbEnrollment = await _dbContext.VehicleEnrollments.FirstOrDefaultAsync(e => e.Id == enrollment.Id);
return (true, String.Empty, _mapper.Map<UpdateVehicleEnrollmentDto>(dbEnrollment));
}
public async Task<(bool isSucceed, string message)> DeleteEnrollment(int id)
{
var dbEnrollment = await _dbContext.VehicleEnrollments.FirstOrDefaultAsync(e => e.Id == id);
if (dbEnrollment == null)
{
return (false, $"Enrollment with id:{id} doesn't exist");
}
_dbContext.VehicleEnrollments.Remove(dbEnrollment);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsEnrollmentExists(int id)
{
return await _dbContext.VehicleEnrollments.AnyAsync(e => e.Id == id);
}
}

View File

@ -0,0 +1,306 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Server.Data;
using Server.Helpers;
using Server.Models;
using SharedModels.DataTransferObjects;
using SharedModels.QueryStringParameters;
namespace Server.Services;
public class VehicleManagementService : IVehicleManagementService
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<Vehicle> _vehicleSortHelper;
private readonly IDataShaper<Vehicle> _vehicleDataShaper;
public VehicleManagementService(ApplicationDbContext dbContext,
IMapper mapper, ISortHelper<Vehicle> vehicleSortHelper,
IDataShaper<Vehicle> vehicleDataShaper)
{
_dbContext = dbContext;
_mapper = mapper;
_vehicleSortHelper = vehicleSortHelper;
_vehicleDataShaper = vehicleDataShaper;
}
public async Task<(bool isSucceed, string message, VehicleDto vehicle)> AddVehicle(CreateVehicleDto createVehicleDto)
{
var vehicle = _mapper.Map<Vehicle>(createVehicleDto);
await _dbContext.Vehicles.AddAsync(vehicle);
await _dbContext.SaveChangesAsync();
return (true, String.Empty, _mapper.Map<VehicleDto>(vehicle));
}
public async Task<(bool isSucceed, string message, IEnumerable<VehicleDto> vehicles,
PagingMetadata<Vehicle> pagingMetadata)> GetVehicles(VehicleParameters parameters)
{
var dbVehicles = _dbContext.Vehicles
.AsQueryable();
bool a = dbVehicles.Any();
SearchByAllVehicleFields(ref dbVehicles, parameters.Search);
a = dbVehicles.Any();
FilterByVehicleNumber(ref dbVehicles, parameters.Number);
a = dbVehicles.Any();
FilterByVehicleType(ref dbVehicles, parameters.Type);
a = dbVehicles.Any();
FilterByVehicleCapacity(ref dbVehicles, parameters.FromCapacity,
parameters.ToCapacity);
a = dbVehicles.Any();
FilterByVehicleClimateControlAvailability(ref dbVehicles, parameters.HasClimateControl);
a = dbVehicles.Any();
FilterByVehicleWiFiAvailability(ref dbVehicles, parameters.HasWiFi);
a = dbVehicles.Any();
FilterByVehicleWCAvailability(ref dbVehicles, parameters.HasWC);
a = dbVehicles.Any();
FilterByStewardessAvailability(ref dbVehicles, parameters.HasStewardess);
a = dbVehicles.Any();
FilterByVehicleTVAvailability(ref dbVehicles, parameters.HasTV);
a = dbVehicles.Any();
FilterByVehicleOutletAvailability(ref dbVehicles, parameters.HasOutlet);
a = dbVehicles.Any();
FilterByVehicleBeltsAvailability(ref dbVehicles, parameters.HasBelts);
a = dbVehicles.Any();
FilterByVehicleCompanyId(ref dbVehicles, parameters.CompanyId);
a = dbVehicles.Any();
try
{
dbVehicles = _vehicleSortHelper.ApplySort(dbVehicles, parameters.Sort);
// By calling Any() we will check if LINQ to Entities Query will be
// executed. If not it will throw an InvalidOperationException exception
var isExecuted = dbVehicles.Any();
}
catch (Exception e)
{
return (false, "Invalid sorting string", null, null)!;
}
var pagingMetadata = ApplyPaging(ref dbVehicles, parameters.PageNumber,
parameters.PageSize);
var shapedVehiclesData = _vehicleDataShaper.ShapeData(dbVehicles, parameters.Fields);
var vehicleDtos = shapedVehiclesData.ToList().ConvertAll(v => _mapper.Map<VehicleDto>(v));
return (true, "", vehicleDtos, pagingMetadata);
void SearchByAllVehicleFields(ref IQueryable<Vehicle> vehicle,
string? search)
{
if (!vehicle.Any() || String.IsNullOrWhiteSpace(search))
{
return;
}
vehicle = vehicle.Where(v =>
v.Number.ToLower().Contains(search.ToLower()) ||
v.Type.ToLower().Contains(search.ToLower()));
}
void FilterByVehicleNumber(ref IQueryable<Vehicle> vehicles,
string? number)
{
if (!vehicles.Any() || String.IsNullOrWhiteSpace(number))
{
return;
}
vehicles = vehicles.Where(v => v.Number == number);
}
void FilterByVehicleType(ref IQueryable<Vehicle> vehicles,
string? type)
{
if (!vehicles.Any() || String.IsNullOrWhiteSpace(type))
{
return;
}
vehicles = vehicles.Where(v => v.Type == type);
}
void FilterByVehicleCapacity(ref IQueryable<Vehicle> vehicles,
int? fromCapacity, int? toCapacity)
{
if (!vehicles.Any() || fromCapacity == null && toCapacity == null)
{
return;
}
vehicles = vehicles.Where(v => v.Capacity >= fromCapacity &&
v.Capacity <= toCapacity);
}
void FilterByVehicleClimateControlAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasClimateControl)
{
if (!vehicles.Any() || hasClimateControl == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasClimateControl == hasClimateControl);
}
void FilterByVehicleWiFiAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasWiFi)
{
if (!vehicles.Any() || hasWiFi == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasWiFi == hasWiFi);
}
void FilterByVehicleWCAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasWC)
{
if (!vehicles.Any() || hasWC == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasWC == hasWC);
}
void FilterByStewardessAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasStewardess)
{
if (!vehicles.Any() || hasStewardess == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasStewardess == hasStewardess);
}
void FilterByVehicleTVAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasTV)
{
if (!vehicles.Any() || hasTV == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasTV == hasTV);
}
void FilterByVehicleOutletAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasOutlet)
{
if (!vehicles.Any() || hasOutlet == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasOutlet == hasOutlet);
}
void FilterByVehicleBeltsAvailability(ref IQueryable<Vehicle> vehicles,
bool? hasBelts)
{
if (!vehicles.Any() || hasBelts == null)
{
return;
}
vehicles = vehicles.Where(v => v.HasBelts == hasBelts);
}
void FilterByVehicleCompanyId(ref IQueryable<Vehicle> vehicles,
int? companyId)
{
if (!vehicles.Any() || companyId == null)
{
return;
}
vehicles = vehicles.Where(v => v.CompanyId == companyId);
}
PagingMetadata<Vehicle> ApplyPaging(ref IQueryable<Vehicle> vehicles,
int pageNumber, int pageSize)
{
var metadata = new PagingMetadata<Vehicle>(vehicles,
pageNumber, pageSize);
vehicles = vehicles
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
return metadata;
}
}
public async Task<(bool isSucceed, string message, VehicleDto vehicle)> GetVehicle(int id, string? fields)
{
var dbVehicle = await _dbContext.Vehicles.Where(v => v.Id == id)
.FirstOrDefaultAsync();
if (dbVehicle == null)
{
return (false, $"Vehicle doesn't exist", null)!;
}
if (String.IsNullOrWhiteSpace(fields))
{
fields = VehicleParameters.DefaultFields;
}
var shapedVehicleData = _vehicleDataShaper.ShapeData(dbVehicle, fields);
var vehicleDto = _mapper.Map<VehicleDto>(shapedVehicleData);
return (true, "", vehicleDto);
}
public async Task<(bool isSucceed, string message, UpdateVehicleDto vehicle)> UpdateVehicle(UpdateVehicleDto updateVehicleDto)
{
var vehicle = _mapper.Map<Vehicle>(updateVehicleDto);
_dbContext.Entry(vehicle).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await IsVehicleExists(updateVehicleDto.Id))
{
return (false, $"Vehicle with id:{updateVehicleDto.Id} doesn't exist", null)!;
}
throw;
}
var dbVehicle = await _dbContext.Vehicles.FirstOrDefaultAsync(v => v.Id == vehicle.Id);
return (true, String.Empty, _mapper.Map<UpdateVehicleDto>(dbVehicle));
}
public async Task<(bool isSucceed, string message)> DeleteVehicle(int id)
{
var dbVehicle = await _dbContext.Vehicles.FirstOrDefaultAsync(v => v.Id == id);
if (dbVehicle == null)
{
return (false, $"Vehicle with id:{id} doesn't exist");
}
_dbContext.Vehicles.Remove(dbVehicle);
await _dbContext.SaveChangesAsync();
return (true, String.Empty);
}
public async Task<bool> IsVehicleExists(int id)
{
return await _dbContext.Vehicles.AnyAsync(v => v.Id == id);
}
}

View File

@ -17,11 +17,9 @@ public class CreateAddressDto
[StringLength(maximumLength: 250, ErrorMessage = "Address name is too long")]
public string Name { get; set; } = null!;
[Required]
[Range(-90, 90, ErrorMessage = "Latitude must be in range(-90, 90)")]
public double Latitude { get; set; }
[Required]
[Range(-180, 180, ErrorMessage = "Longitude must be in range(-180, 180)")]
public double Longitude { get; set; }

View File

@ -0,0 +1,29 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class CompanyDto
{
public int Id { get; set; }
public string Name { get; set; } = null!;
public string OwnerId { get; set; } = null!;
}
public class CreateCompanyDto
{
[Required]
public string Name { get; set; } = null!;
[Required]
public string OwnerId { get; set; } = null!;
}
public class UpdateCompanyDto
{
[Required]
public int Id { get; set; }
public string Name { get; set; } = null!;
public string OwnerId { get; set; } = null!;
}

View File

@ -0,0 +1,40 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class ReviewDto
{
public int Id { get; set; }
public int Rating { get; set; }
public string Comment { get; set; } = null!;
}
public class CreateReviewDto
{
[Required]
public string UserId { get; set; } = null!;
[Required]
public int VehicleEnrollmentId { get; set; }
[Range(0,100)]
public int Rating { get; set; }
[MaxLength(255)]
public string Comment { get; set; } = null!;
}
public class UpdateReviewDto
{
[Required]
public int Id { get; set; }
public string UserId { get; set; } = null!;
public int VehicleEnrollmentId { get; set; }
[Range(0,100)]
public int Rating { get; set; }
[MaxLength(255)]
public string Comment { get; set; } = null!;
}

View File

@ -2,13 +2,18 @@ using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class RouteAddressDto : CreateRouteAddressDto
public class RouteAddressDto
{
public int Id { get; set; }
public RouteDto Route { get; set; } = null!;
public AddressDto Address { get; set; } = null!;
public int RouteId { get; set; }
public int AddressId { get; set; }
public int Order { get; set; }
[DataType(DataType.Duration)]
public TimeSpan TimeSpanToNextCity { get; set; }
[DataType(DataType.Duration)]
public TimeSpan WaitTimeSpan { get; set; }
[DataType(DataType.Currency)]
public double CostToNextCity { get; set; }
}
public class CreateRouteAddressDto
@ -33,4 +38,19 @@ public class CreateRouteAddressDto
[Required]
[DataType(DataType.Currency)]
public double CostToNextCity { get; set; }
}
public class UpdateRouteAddressDto
{
[Required]
public int Id { get; set; }
public int RouteId { get; set; }
public int AddressId { get; set; }
public int Order { get; set; }
[DataType(DataType.Duration)]
public TimeSpan TimeSpanToNextCity { get; set; }
[DataType(DataType.Duration)]
public TimeSpan WaitTimeSpan { get; set; }
[DataType(DataType.Currency)]
public double CostToNextCity { get; set; }
}

View File

@ -2,18 +2,23 @@ using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class RouteDto : CreateRouteDto
public class RouteDto
{
public int Id { get; set; }
public virtual IList<RouteAddressDto> RouteAddresses { get; set; } = null!;
public string Type { get; set; } = null!;
}
public class CreateRouteDto
{
[Required]
public string Type { get; set; } = null!;
}
public class UpdateRouteDto
{
[Required]
public TimeOnly IntendedDepartureTimeOnlyUtc { get; set; }
public int Id { get; set; }
public string Type { get; set; } = null!;
}

View File

@ -0,0 +1,31 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class TicketDto : CreateTicketDto
{
public int Id { get; set; }
[DataType(DataType.DateTime)]
public DateTime PurchaseDateTimeUtc { get; set; }
public bool IsReturned { get; set; } = false;
}
public class CreateTicketDto
{
[Required]
public string UserId { get; set; } = null!;
[Required]
public int VehicleEnrollmentId { get; set; }
}
public class UpdateTicketDto : CreateTicketDto
{
[Required]
public int Id { get; set; }
[DataType(DataType.DateTime)]
public DateTime PurchaseDateTimeUtc { get; set; }
public bool IsReturned { get; set; } = false;
}

View File

@ -0,0 +1,78 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class VehicleDto
{
public int Id { get; set; }
public string? Number { get; set; }
public string? Type { get; set; }
public int Capacity { get; set; }
public bool HasClimateControl { get; set; }
public bool HasWiFi { get; set; }
public bool HasWC { get; set; }
public bool HasStewardess { get; set; }
public bool HasTV { get; set; }
public bool HasOutlet { get; set; }
public bool HasBelts { get; set; }
public int CompanyId { get; set; }
}
public class CreateVehicleDto
{
[Required]
[MaxLength(8)]
public string? Number { get; set; }
[Required]
public string? Type { get; set; }
[Required]
[Range(10, 100)]
public int Capacity { get; set; }
[Required]
public bool HasClimateControl { get; set; } = false;
[Required]
public bool HasWiFi { get; set; } = false;
[Required]
public bool HasWC { get; set; } = false;
[Required]
public bool HasStewardess { get; set; } = false;
[Required]
public bool HasTV { get; set; } = false;
[Required]
public bool HasOutlet { get; set; } = false;
[Required]
public bool HasBelts { get; set; } = false;
[Required]
public int CompanyId { get; set; }
}
public class UpdateVehicleDto
{
[Required]
public int Id { get; set; }
[MaxLength(8)]
public string? Number { get; set; }
public string? Type { get; set; }
[Range(10, 100)]
public int Capacity { get; set; }
public bool HasClimateControl { get; set; } = false;
public bool HasWiFi { get; set; } = false;
public bool HasWC { get; set; } = false;
public bool HasStewardess { get; set; } = false;
public bool HasTV { get; set; } = false;
public bool HasOutlet { get; set; } = false;
public bool HasBelts { get; set; } = false;
public int CompanyId { get; set; }
}

View File

@ -0,0 +1,44 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.DataTransferObjects;
public class VehicleEnrollmentDto
{
public int Id { get; set; }
public int VehicleId { get; set; }
public int RouteId { get; set; }
public DateTime DepartureDateTimeUtc { get; set; }
public TimeSpan DelayTimeSpan { get; set; }
public bool IsCanceled {get; set; }
public string CancelationComment { get; set; } = null!;
}
public class CreateVehicleEnrollmentDto
{
[Required]
public int VehicleId { get; set; }
[Required]
public int RouteId { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime DepartureDateTimeUtc { get; set; }
public TimeSpan DelayTimeSpan { get; set; } = TimeSpan.Zero;
public bool IsCanceled { get; set; } = false;
public string? CancelationComment { get; set; } = null!;
}
public class UpdateVehicleEnrollmentDto
{
[Required]
public int Id { get; set; }
public int VehicleId { get; set; }
public int RouteId { get; set; }
public DateTime DepartureDateTimeUtc { get; set; }
public TimeSpan DelayTimeSpan { get; set; }
public bool IsCanceled {get; set; }
public string CancelationComment { get; set; } = null!;
}

View File

@ -0,0 +1,15 @@
namespace SharedModels.QueryStringParameters;
public class CompanyParameters : QueryStringParameters
{
public const string DefaultFields = "id,ownerId,name";
public CompanyParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public string? Name { get; set; }
public string? OwnerId { get; set; }
}

View File

@ -0,0 +1,15 @@
namespace SharedModels.QueryStringParameters;
public class ReviewParameters : QueryStringParameters
{
public const string DefaultFields = "id,userId,vehicleEnrollmentId,rating,comment";
public ReviewParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public int? Rating { get; set; }
public string? Comment { get; set; }
}

View File

@ -0,0 +1,16 @@
namespace SharedModels.QueryStringParameters;
public class RouteAddressParameters : QueryStringParameters
{
public const string DefaultFields = "id,routeId,addressId,order,timeSpanToNextCity," +
"waitTimeSpan,costToNextCity";
public RouteAddressParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public int? RouteId { get; set; }
public int? AddressId { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace SharedModels.QueryStringParameters;
public class RouteParameters : QueryStringParameters
{
public const string DefaultFields = "id,type";
public RouteParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public string? Type { get; set; }
}

View File

@ -0,0 +1,16 @@
namespace SharedModels.QueryStringParameters;
public class TicketParameters : QueryStringParameters
{
public const string DefaultFields = "id,userId,vehicleEnrollmentId,purchaseDateTimeUtc,isReturned";
public TicketParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public DateTime? FromPurchaseDateTimeUtc { get; set; }
public DateTime? ToPurchaseDateTimeUtc { get; set; }
public bool? IsReturned { get; set; }
}

View File

@ -0,0 +1,20 @@
namespace SharedModels.QueryStringParameters;
public class VehicleEnrollmentParameters : QueryStringParameters
{
public const string DefaultFields = "id,vehicleId,routeId,departureDateTimeUtc," +
"delayTimeSpan,isCancelled,cancellationComment";
public VehicleEnrollmentParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public int? VehicleId { get; set; }
public int? RouteId { get; set; }
public DateTime? FromDepartureDateTime { get; set; }
public DateTime? ToDepartureDateTime { get; set; }
public bool? IsDelayed { get; set; }
public bool? IsCanceled {get; set; }
}

View File

@ -0,0 +1,28 @@
namespace SharedModels.QueryStringParameters;
public class VehicleParameters : QueryStringParameters
{
public const string DefaultFields = "id,companyId,number,type,capacity,hasClimateControl," +
"hasWiFi,hasWC,hasStewardess,hasTV,hasOutlet,hasBelts";
public VehicleParameters()
{
Sort = "id";
Fields = DefaultFields;
}
public string? Number { get; set; }
public string? Type { get; set; }
public int? FromCapacity { get; set; }
public int? ToCapacity { get; set; }
public bool? HasClimateControl { get; set; }
public bool? HasWiFi { get; set; }
public bool? HasWC { get; set; }
public bool? HasStewardess { get; set; }
public bool? HasTV { get; set; }
public bool? HasOutlet { get; set; }
public bool? HasBelts { get; set; }
public int? CompanyId { get; set; }
}