Compare commits

...

16 Commits

45 changed files with 2788 additions and 30 deletions

View File

@ -0,0 +1,98 @@
using Npgsql;
using RentalBusiness.Models.ViewModels;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public class BrandLogic
{
public List<BrandViewModel> _brand;
public BrandLogic()
{
_brand = new();
_brand = ReadBrands().Result;
}
public async Task<List<BrandViewModel>> ReadBrands()
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
List<BrandViewModel> brands = new List<BrandViewModel>();
connection.Open();
await using (NpgsqlCommand getRecordStorage = new NpgsqlCommand("SELECT brand_id, brand_name, brand_ratio FROM brand", connection))
{
await using (NpgsqlDataReader reader = await getRecordStorage.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
BrandViewModel viewModel = ReadModelView(reader);
brands.Add(viewModel);
}
}
}
connection.Close();
return brands;
}
public BrandViewModel ReadModelView(NpgsqlDataReader reader)
{
int? id = reader["brand_id"] as int?;
string brandName = reader["brand_name"] as string;
int? ratio = reader["brand_ratio"] as int?;
BrandViewModel view = new BrandViewModel
{
ID = id.Value,
BrandName = new string(brandName),
BrandRatio = ratio.Value,
};
return view;
}
public void PostBrand(BrandViewModel view)
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using var checkDuplicate = new NpgsqlCommand("SELECT brand_id FROM brand WHERE brand_name LIKE @bn",connection)
{
Parameters =
{
new("bn", view.BrandName)
}
};
int? buff = Convert.ToInt32(checkDuplicate.ExecuteScalar());
if(buff == null)
{
return;
}
using var postBrand = new NpgsqlCommand("INSERT INTO brand (brand_name,brand_ratio) VALUES(@bs,@br)",connection)
{
Parameters =
{
new("bs",view.BrandName),
new("br",view.BrandRatio)
}
};
postBrand.ExecuteNonQueryAsync();
connection.Close();
}
}
}

View File

@ -0,0 +1,121 @@
using Npgsql;
using RentalBusiness.Enums;
using RentalBusiness.Models.ViewModels;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public class ClientLogic
{
public List<ClientViewModel> _clients;
public ClientLogic()
{
_clients = new List<ClientViewModel>();
_clients = ReadClients().Result;
}
public async Task<List<ClientViewModel>> ReadClients()
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
List<ClientViewModel> clients = new List<ClientViewModel>();
connection.Open();
await using (NpgsqlCommand getRecordStorage = new NpgsqlCommand("SELECT C.customer_id, C.last_name, C.first_name, C.middle_name, C.id_card " +
"FROM customer C ", connection))
{
await using (NpgsqlDataReader reader = await getRecordStorage.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
ClientViewModel viewModel = ReadClientView(reader);
clients.Add(viewModel);
}
}
}
connection.Close();
return clients;
}
public ClientViewModel ReadClientView(NpgsqlDataReader reader)
{
int? id = reader["customer_id"] as int?;
string lastName = reader["last_name"] as string;
string firstName = reader["first_name"] as string;
string middleName = reader["middle_name"] as string;
string idcard = reader["id_card"] as string;
ClientViewModel view = new ClientViewModel
{
ID = id.Value,
FullName = new string(lastName + " " + firstName + " " + middleName),
IDCard = new string(idcard)
};
return view;
}
public void PostClient(ClientViewModel model)
{
List<string> NameParts = model.FullName.Split(' ').ToList();
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using var command = new NpgsqlCommand("INSERT INTO customer (last_name,first_name,middle_name,id_card) VALUES(@ln,@fn,@mn,@ic)", connection)
{
Parameters =
{
new("ln",NameParts[1]),
new("fn",NameParts[0]),
new("mn",NameParts[2]),
new("ic",model.IDCard)
}
};
command.ExecuteNonQueryAsync();
connection.Close();
}
public void UpdateClient(ClientViewModel model)
{
List<string> NameParts = model.FullName.Split(' ').ToList();
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using (var fcommand = new NpgsqlCommand("UPDATE customer SET first_name = @fn WHERE customer_id = @cid", connection))
{
fcommand.Parameters.AddWithValue("cid", model.ID);
fcommand.Parameters.AddWithValue("fn", NameParts[0]);
fcommand.ExecuteNonQueryAsync();
};
using (var lcommand = new NpgsqlCommand("UPDATE customer SET last_name = @ln WHERE customer_id = @cid", connection))
{
lcommand.Parameters.AddWithValue("cid", model.ID);
lcommand.Parameters.AddWithValue("ln", NameParts[1]);
lcommand.ExecuteNonQueryAsync();
};
using (var mcommand = new NpgsqlCommand("UPDATE customer SET middle_name = @mn WHERE customer_id = @cid", connection))
{
mcommand.Parameters.AddWithValue("cid", model.ID);
mcommand.Parameters.AddWithValue("mn", NameParts[2]);
mcommand.ExecuteNonQueryAsync();
};
using (var icommand = new NpgsqlCommand("UPDATE customer SET id_card = @ic WHERE customer_id = @cid", connection))
{
icommand.Parameters.AddWithValue("cid", model.ID);
icommand.Parameters.AddWithValue("ic", model.IDCard);
icommand.ExecuteNonQueryAsync();
};
connection.Close();
}
}
}

View File

@ -0,0 +1,61 @@
using Npgsql;
using RentalBusiness.Models;
using RentalBusiness.Models.ViewModels;
using System.Text.RegularExpressions;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public class ComplicatedQueriesLogic
{
public List<TopCarViewModel> _topCars;
public ComplicatedQueriesLogic()
{
_topCars = new List<TopCarViewModel>();
_topCars = ReadTopCars().Result;
}
public async Task<List<TopCarViewModel>> ReadTopCars()
{
List<TopCarViewModel> topCarViewModels = new List<TopCarViewModel>();
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
await using (var getCars = new NpgsqlCommand("SELECT C.car_id,B.brand_name, M.model_spec, SUM(Price) AS Total, COUNT(*) AS Quantity FROM Contract C JOIN Storage S ON C.car_id = S.car_id JOIN Brand B ON B.brand_id = S.brand_id JOIN Model M ON M.model_id = S.model_id GROUP BY(C.car_id, B.brand_name, M.model_spec) ORDER BY 5 DESC", connection))
{
await using (var reader = await getCars.ExecuteReaderAsync())
{
while(await reader.ReadAsync())
{
TopCarViewModel viewModel = ReadCar(reader);
topCarViewModels.Add(viewModel);
}
}
}
connection.Close();
return topCarViewModels;
}
public TopCarViewModel ReadCar(NpgsqlDataReader reader)
{
int? id = reader["car_id"] as int?;
string BrandName = reader["brand_name"] as string;
string ModelName = reader["model_spec"] as string;
decimal? total = reader["Total"] as decimal?;
int? qt = Convert.ToInt32(reader["Quantity"] as long?);
TopCarViewModel topCarViewModel = new()
{
ID = id.Value,
CarInfo = new string(BrandName + " " + ModelName),
TotalIncome = total.Value,
Quantity = qt.Value,
};
return topCarViewModel;
}
}
}

View File

@ -0,0 +1,173 @@
using Npgsql;
using RentalBusiness.Enums;
using RentalBusiness.Models;
using RentalBusiness.Models.ViewModels;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using System.Diagnostics.Contracts;
using Microsoft.EntityFrameworkCore.Query.Internal;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public class ContractLogic
{
public List<ContractViewModel> _contracts;
public ContractLogic()
{
_contracts = new List<ContractViewModel>();
_contracts = ReadContracts().Result;
}
public async Task<List<ContractViewModel>> ReadContracts()
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
List<ContractViewModel> contracts = new List<ContractViewModel>();
connection.Open();
await using (NpgsqlCommand getRecordStorage = new NpgsqlCommand("SELECT C.contract_id, C.car_id, B.brand_name, M.model_spec, C.customer_id, CS.first_name, CS.last_name, CS.id_card , C.rental_date, C.return_date, C.price, C.contract_status " +
"FROM contract C, brand B, model M, customer CS, storage S " +
"WHERE C.car_id = S.car_id AND S.brand_id = B.brand_id AND S.model_id = M.model_id AND C.customer_id = CS.customer_id", connection))
{
await using (NpgsqlDataReader reader = await getRecordStorage.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
ContractViewModel viewModel = ReadStorageView(reader);
contracts.Add(viewModel);
}
}
}
connection.Close();
return contracts;
}
public ContractViewModel ReadStorageView(NpgsqlDataReader reader)
{
int? contract_id = reader["contract_id"] as int?;
int? car_id = reader["car_id"] as int?;
string brandName = reader["brand_name"] as string;
string modelName = reader["model_spec"] as string;
int? customer_id = reader["customer_id"] as int?;
string firstname = reader["first_name"] as string;
string lastname = reader["last_name"] as string;
string idcard = reader["id_card"] as string;
DateTime? rental_date = reader["rental_date"] as DateTime?;
DateTime? return_date = reader["return_date"] as DateTime?;
decimal? price = reader["price"] as decimal?;
string contractStatus = reader["contract_status"] as string;
ContractViewModel view = new ContractViewModel
{
ID = contract_id.Value,
CarID = car_id.Value,
CarInfo = new string(brandName + " " + modelName),
CustomerID = customer_id.Value,
CustomerFullName = new string(firstname + " " + lastname),
CustomerIDCard = new string(idcard),
CurDate = (DateTime)rental_date,
ReturnDate = (DateTime)return_date,
Price = price.Value,
Status = (ContractStatus)Enum.Parse(typeof(ContractStatus),contractStatus)
};
if(view.Status == ContractStatus.in_process)
{
ChangeContractStatus(view);
}
return view;
}
public void PostContract(ContractViewModel contract)
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using var command = new NpgsqlCommand("INSERT INTO contract (car_id,customer_id,rental_date,return_date,price,contract_status) VALUES(@caid,@cuid,@rend,@retd,@price,@cs)", connection)
{
Parameters =
{
new("caid",contract.CarID),
new("cuid",contract.CustomerID),
new("rend",contract.CurDate),
new("retd",contract.ReturnDate),
new("price",contract.Price),
new("cs",contract.Status)
}
};
command.ExecuteNonQueryAsync();
connection.Close();
UpdateCarState(contract.CarID,contract.Status);
}
public void UpdateCarState(int carID, ContractStatus status)
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
if (status == ContractStatus.in_process)
{
using (var carcommand = new NpgsqlCommand("UPDATE storage SET car_status = @cs WHERE car_id = @caid", connection))
{
carcommand.Parameters.AddWithValue("caid", carID);
carcommand.Parameters.AddWithValue("cs", CarStatus.is_taken);
carcommand.ExecuteNonQueryAsync();
};
}
else
{
using (var carcommand = new NpgsqlCommand("UPDATE storage SET car_status = @cs WHERE car_id = @caid", connection))
{
carcommand.Parameters.AddWithValue("caid", carID);
carcommand.Parameters.AddWithValue("cs", CarStatus.available);
carcommand.ExecuteNonQueryAsync();
};
}
connection.Close();
}
public void ChangeContractStatus(ContractViewModel model, bool flag = true)
{
DateTime curDate = DateTime.Today;
if(model.ReturnDate.HasValue && DateTime.Compare(curDate, (DateTime)model.ReturnDate) < 0)
{
return;
}
if (flag)
{
model.Status = ContractStatus.expired;
}
else
{
model.Status = ContractStatus.finished;
}
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using (var contractStatusChange = new NpgsqlCommand("UPDATE contract SET contract_status = @cs WHERE contract_id = @caid", connection))
{
contractStatusChange.Parameters.AddWithValue("caid", model.ID);
contractStatusChange.Parameters.AddWithValue("cs", model.Status);
contractStatusChange.ExecuteNonQueryAsync();
};
connection.Close();
UpdateCarState(model.CarID, model.Status);
}
}
}

View File

@ -0,0 +1,79 @@
using Npgsql;
using RentalBusiness.Enums;
using RentalBusiness.Models.ViewModels;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public class ModelLogic
{
public List<ModelViewModel> _model;
public ModelLogic()
{
_model = new();
_model = ReadModels().Result;
}
public async Task<List<ModelViewModel>> ReadModels()
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
List<ModelViewModel> models = new List<ModelViewModel>();
connection.Open();
await using (NpgsqlCommand getRecordStorage = new NpgsqlCommand("SELECT model_id, model_spec, model_ratio FROM model", connection))
{
await using (NpgsqlDataReader reader = await getRecordStorage.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
ModelViewModel viewModel = ReadModelView(reader);
models.Add(viewModel);
}
}
}
connection.Close();
return models;
}
public ModelViewModel ReadModelView(NpgsqlDataReader reader)
{
int? id = reader["model_id"] as int?;
string modelSpec = reader["model_spec"] as string;
int? ratio = reader["model_ratio"] as int?;
ModelViewModel view = new ModelViewModel
{
ID = id.Value,
ModelSpec = new string(modelSpec),
ModelRatio = ratio.Value,
};
return view;
}
public void PostModel(ModelViewModel view)
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using var postModel = new NpgsqlCommand("INSERT INTO model (model_spec,model_ratio) VALUES(@ms,@mr)",connection)
{
Parameters =
{
new("ms",view.ModelSpec),
new("mr",view.ModelRatio)
}
};
postModel.ExecuteNonQueryAsync();
connection.Close();
}
}
}

View File

@ -0,0 +1,141 @@
using Microsoft.EntityFrameworkCore;
using Npgsql;
using RentalBusiness.AuxilaryElements;
using RentalBusiness.AuxilaryElements.Implements;
using RentalBusiness.AuxilaryElements.ImplementsCars;
using RentalBusiness.Enums;
using RentalBusiness.Models.ViewModels;
using System.Security.Cryptography.X509Certificates;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public static class SeedData
{
private static ICarBrand car;
static readonly List<ICarBrand> Brands = new()
{
{ car = new Porsche()},
{ car = new Tesla()},
{ car = new Peugeot()},
{ car = new Mazda()},
{ car = new Kia()},
{ car = new Jaguar()},
{ car = new Honda()}
};
public static async Task InitializeBrands(NpgsqlConnection connection)
{
for (int i = 0; i < Brands.Count; i++)
{
car = Brands.ElementAt(i);
await using var command = new NpgsqlCommand("INSERT INTO brand (brand_name,brand_ratio) VALUES(@name,@ratio)", connection)
{
Parameters =
{
new("name",car.Name),
new("ratio",car.Ratio)
}
};
await command.ExecuteNonQueryAsync();
}
}
public static async Task InitializeModels(NpgsqlConnection connection)
{
foreach (var brand in Brands)
{
foreach (var model in brand.Models)
{
await using var command = new NpgsqlCommand("INSERT INTO model (model_spec,model_ratio) VALUES(@spec,@ratio)", connection)
{
Parameters =
{
new("spec",model.Name),
new("ratio",model.Ratio)
}
};
await command.ExecuteNonQueryAsync();
}
}
}
public static async Task InitializeCustomers(NpgsqlConnection connection)
{
List<string> firstName = new List<string> { "Ivanov", "Lisov", "Verner", "Antonov", "Reinvald", "Spotter", "Rein" };
List<string> lastName = new List<string> { "Nikita", "Artem", "Kirill", "Charlie", "Max", "Polie", "Mike", "El" };
List<string> middleName = new List<string> { "Andreevich", "Polynovich" };
var rnd = new Random();
for (int i = 0; i < 15; i++)
{
await using var command = new NpgsqlCommand("INSERT INTO customer (last_name,first_name,middle_name,id_card) VALUES(@ln,@fn,@mn,@ic)", connection)
{
Parameters =
{
new("ln",lastName.ElementAt(rnd.Next(0,lastName.Count))),
new("fn",firstName.ElementAt(rnd.Next(0,firstName.Count))),
new("mn",middleName.ElementAt(rnd.Next(0,middleName.Count))),
new("ic",rnd.Next(34678398,67806786).ToString())
}
};
await command.ExecuteNonQueryAsync();
}
}
public static async Task InitializeCars(NpgsqlConnection connection)
{
int brandID = 0;
int modelID = 0;
foreach (var brand in Brands)
{
await using (var brandIDcommand = new NpgsqlCommand("SELECT brand_id FROM brand WHERE brand.brand_name = @bbn", connection))
{
brandIDcommand.Parameters.AddWithValue("bbn", brand.Name);
await using (NpgsqlDataReader reader = await brandIDcommand.ExecuteReaderAsync())
{
while (reader.Read())
{
brandID = Convert.ToInt32(reader[0].ToString());
}
}
};
foreach (var model in brand.Models)
{
await using (var modelIDcommand = new NpgsqlCommand("SELECT model_id FROM model WHERE model.model_spec = @mmn", connection))
{
modelIDcommand.Parameters.AddWithValue("mmn", model.Name);
await using (NpgsqlDataReader reader = await modelIDcommand.ExecuteReaderAsync())
{
while (reader.Read())
{
modelID = Convert.ToInt32(reader[0].ToString());
}
}
};
await using var command = new NpgsqlCommand("INSERT INTO storage (brand_id,model_id,car_ratio_per_hour,car_status) VALUES(@bid,@mid,@ratio,@status)", connection)
{
Parameters =
{
new("bid", brandID),
new("mid", modelID),
new("ratio",model.Ratio += brand.Ratio),
new("status",CarStatus.available)
}
};
await command.ExecuteNonQueryAsync();
}
}
}
}
}

View File

@ -0,0 +1,120 @@
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Npgsql;
using RentalBusiness.Enums;
using RentalBusiness.Models.ViewModels;
namespace RentalBusiness.AuxilaryElements.BusinessLogic
{
public class StorageLogic
{
public List<StorageViewModel> _storageFull;
public List<StorageViewModel> _storageFree;
public StorageLogic()
{
_storageFree = new List<StorageViewModel>();
_storageFree = ReadStorage(true).Result;
_storageFull = new List<StorageViewModel>();
_storageFull = ReadStorage(false).Result;
}
public async Task<List<StorageViewModel>> ReadStorage(bool flag = true)
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
List<StorageViewModel> cars = new List<StorageViewModel>();
connection.Open();
if(flag)
{
await using (NpgsqlCommand getRecordStorage = new NpgsqlCommand("SELECT S.car_id, B.brand_name, M.model_spec, S.car_ratio_per_hour, S.car_status " +
"FROM storage S, brand B, model M " +
"WHERE S.car_status = 'available' AND S.model_id = M.model_id " +
"AND S.brand_id = B.brand_id", connection))
{
await using (NpgsqlDataReader reader = await getRecordStorage.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
StorageViewModel viewModel = ReadStorageView(reader);
cars.Add(viewModel);
}
}
}
}
else
{
await using (NpgsqlCommand getRecordStorage = new NpgsqlCommand("SELECT S.car_id, B.brand_name, M.model_spec, S.car_ratio_per_hour, S.car_status " +
"FROM storage S, brand B, model M " +
"WHERE S.model_id = M.model_id " +
"AND S.brand_id = B.brand_id", connection))
{
await using (NpgsqlDataReader reader = await getRecordStorage.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
StorageViewModel viewModel = ReadStorageView(reader);
cars.Add(viewModel);
}
}
}
}
connection.Close();
return cars;
}
public StorageViewModel ReadStorageView(NpgsqlDataReader reader)
{
int? id = reader["car_id"] as int?;
string brandName = reader["brand_name"] as string;
string modelName = reader["model_spec"] as string;
int? ratio = reader["car_ratio_per_hour"] as int?;
string carStatus = reader["car_status"] as string;
StorageViewModel view = new StorageViewModel
{
ID = id.Value,
CarInfo = new string(brandName + " " + modelName),
CarRatio = ratio.Value,
CarStatus = (CarStatus)Enum.Parse(typeof(CarStatus), carStatus)
};
return view;
}
public void PostCar(StorageViewModel model)
{
NpgsqlConnection connection = new NpgsqlConnection("Host=localhost;Database=local;Username=postgres;Password=postgres");
connection.Open();
using var checkDuplicate = new NpgsqlCommand("SELECT car_id FROM storage WHERE brand_id = @bid AND model_id = @mid", connection)
{
Parameters =
{
new("bid",model.Brand_ID),
new("mid",model.Model_ID),
}
};
int id = Convert.ToInt32(checkDuplicate.ExecuteScalar());
if(id != 0)
{
return;
}
using var postCar = new NpgsqlCommand("INSERT INTO storage(brand_id,model_id,car_ratio_per_hour,car_status) VALUES(@bid,@mid,@ratio,@cs)", connection)
{
Parameters =
{
new("bid",model.Brand_ID),
new("mid",model.Model_ID),
new("ratio",model.CarRatio),
new("cs",model.CarStatus),
}
};
postCar.ExecuteNonQueryAsync();
connection.Close();
}
}
}

View File

@ -0,0 +1,14 @@
namespace RentalBusiness.AuxilaryElements
{
public class CarModel : ICarModel
{
public string Name { get; set; }
public int Ratio { get; set; }
public CarModel(string Name, int Ratio)
{
this.Name = Name;
this.Ratio = Ratio;
}
}
}

View File

@ -0,0 +1,9 @@
namespace RentalBusiness.AuxilaryElements
{
public interface ICarBrand
{
public string Name { get; set; }
public int Ratio { get; set; }
public List<ICarModel> Models { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace RentalBusiness.AuxilaryElements
{
public interface ICarModel
{
public string Name { get; set; }
public int Ratio { get; set; }
}
}

View File

@ -0,0 +1,25 @@
namespace RentalBusiness.AuxilaryElements.ImplementsCars
{
public class Honda : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models { get; set; }
public int Ratio { get; set; }
Random rand = new Random();
public Honda()
{
Name = "Honda";
Ratio = rand.Next(2, 9);
Models = new List<ICarModel>
{
new CarModel("CR-V", rand.Next(2, 9)),
new CarModel("Civic", rand.Next(2, 9)),
new CarModel("HR-V", rand.Next(2, 9)),
new CarModel("Fit", rand.Next(2, 9)),
new CarModel("Accord", rand.Next(2, 9)),
new CarModel("Integra", rand.Next(2, 9))
};
}
}
}

View File

@ -0,0 +1,24 @@
namespace RentalBusiness.AuxilaryElements.ImplementsCars
{
public class Jaguar : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models { get; set; }
public int Ratio { get; set; }
Random rand = new Random();
public Jaguar()
{
Name = "Jaguar";
Ratio = rand.Next(2, 9);
Models = new List<ICarModel>
{
new CarModel("F-type", rand.Next(2, 9)),
new CarModel("F-PACE", rand.Next(2, 9)),
new CarModel("E-PACE", rand.Next(2, 9)),
new CarModel("XF", rand.Next(2, 9)),
new CarModel("I-PACE", rand.Next(2, 9))
};
}
}
}

View File

@ -0,0 +1,27 @@
namespace RentalBusiness.AuxilaryElements.ImplementsCars
{
public class Kia : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models { get; set; }
public int Ratio { get; set; }
Random rand = new Random();
public Kia()
{
Name = "Kia";
Ratio = rand.Next(2, 9);
Models = new List<ICarModel>
{
new CarModel("Sportage", rand.Next(2, 9)),
new CarModel("Sorento", rand.Next(2, 9)),
new CarModel("Rio", rand.Next(2, 9)),
new CarModel("Picanto", rand.Next(2, 9)),
new CarModel("Seltos", rand.Next(2, 9)),
new CarModel("Soul", rand.Next(2, 9)),
new CarModel("Carnival", rand.Next(2, 9)),
new CarModel("Cerato", rand.Next(2, 9))
};
}
}
}

View File

@ -0,0 +1,24 @@
namespace RentalBusiness.AuxilaryElements.ImplementsCars
{
public class Mazda : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models { get; set; }
public int Ratio { get; set; }
Random rand = new Random();
public Mazda()
{
Name = "Mazda";
Ratio = rand.Next(2, 9);
Models = new List<ICarModel>
{
new CarModel("F-A", rand.Next(2, 9)),
new CarModel("6", rand.Next(2, 9)),
new CarModel("8", rand.Next(2, 9)),
new CarModel("POL", rand.Next(2, 9)),
new CarModel("FGHJ", rand.Next(2, 9))
};
}
}
}

View File

@ -0,0 +1,24 @@
namespace RentalBusiness.AuxilaryElements.ImplementsCars
{
public class Peugeot : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models { get; set; }
public int Ratio { get; set; }
Random rand = new Random();
public Peugeot()
{
Name = "Peugeot";
Ratio = rand.Next(2, 9);
Models = new List<ICarModel>
{
new CarModel("3008", rand.Next(2, 9)),
new CarModel("2008", rand.Next(2, 9)),
new CarModel("408", rand.Next(2, 9)),
new CarModel("5008", rand.Next(2, 9)),
new CarModel("C504", rand.Next(2, 9))
};
}
}
}

View File

@ -0,0 +1,25 @@
namespace RentalBusiness.AuxilaryElements.Implements
{
public class Porsche : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models {get; set;}
public int Ratio { get; set; }
Random rand = new Random();
public Porsche()
{
Name = "Porsche";
Ratio = rand.Next(2,9);
Models = new List<ICarModel>
{
new CarModel("911", rand.Next(2, 9)),
new CarModel("718", rand.Next(2, 9)),
new CarModel("Cayman", rand.Next(2, 9)),
new CarModel("CarreraS", rand.Next(2, 9)),
new CarModel("Cayenne", rand.Next(2, 9)),
new CarModel("Taycan", rand.Next(2, 9))
};
}
}
}

View File

@ -0,0 +1,24 @@
namespace RentalBusiness.AuxilaryElements.ImplementsCars
{
public class Tesla : ICarBrand
{
public string Name { get; set; }
public List<ICarModel> Models { get; set; }
public int Ratio { get; set; }
Random rand = new Random();
public Tesla()
{
Name = "Tesla";
Ratio = rand.Next(2, 9);
Models = new List<ICarModel>
{
new CarModel("ModelS", rand.Next(2, 9)),
new CarModel("Model3", rand.Next(2, 9)),
new CarModel("ModelX", rand.Next(2, 9)),
new CarModel("ModelY", rand.Next(2, 9)),
new CarModel("Cybertruck", rand.Next(2, 9))
};
}
}
}

View File

@ -1,5 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using RentalBusiness.AuxilaryElements.BusinessLogic;
using RentalBusiness.Enums;
using RentalBusiness.Models;
using RentalBusiness.Models.ViewModels;
using System.Diagnostics;
namespace RentalBusiness.Controllers
@ -7,26 +10,174 @@ namespace RentalBusiness.Controllers
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly StorageLogic _storageLogic;
private readonly ClientLogic _clientLogic;
private readonly ContractLogic _contractLogic;
private readonly ModelLogic _modelLogic;
private readonly BrandLogic _brandLogic;
private readonly ComplicatedQueriesLogic _complicatedQueriesLogic;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
_storageLogic = new StorageLogic();
_clientLogic = new ClientLogic();
_contractLogic = new ContractLogic();
_modelLogic = new ModelLogic();
_brandLogic = new BrandLogic();
_complicatedQueriesLogic = new ComplicatedQueriesLogic();
}
[HttpGet]
public IActionResult Index()
{
UpdateData();
ViewBag.Cars = _storageLogic._storageFree;
ViewBag.Clients = _clientLogic._clients;
return View();
}
public IActionResult Privacy()
[HttpPost]
public void Index(int car,int customer,string returnDate)
{
ContractViewModel contract = new()
{
CarID = car,
CarInfo = _storageLogic._storageFull.First(x => x.ID == car).CarInfo,
CustomerID = customer,
CustomerFullName = _clientLogic._clients.First(x => x.ID == customer).FullName,
ReturnDate = DateTime.Parse(returnDate),
Price = Calc(car, returnDate)
};
_contractLogic.PostContract(contract);
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Customer()
{
ViewBag.Clients = _clientLogic._clients;
return View();
}
[HttpPost]
public void Customer(int customer, string? fname, string? lname, string? mname, string? idcard, string funcbutton)
{
ClientViewModel client = new()
{
ID = customer,
FullName = new string(fname + " " + lname + " " + mname),
IDCard = new string(idcard)
};
if (funcbutton.Equals("Add"))
{
_clientLogic.PostClient(client);
}
else
{
_clientLogic.UpdateClient(client);
}
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Car()
{
ViewBag.Models = _modelLogic._model;
ViewBag.Brands = _brandLogic._brand;
return View();
}
[HttpPost]
public void Car(string? brandname, int? brandratio, string? modelname, int? modelratio, int? brand, int? model )
{
if(!string.IsNullOrEmpty(brandname) && !string.IsNullOrEmpty(brandratio.ToString()))
{
BrandViewModel brandModel = new()
{
BrandName = brandname,
BrandRatio = brandratio
};
_brandLogic.PostBrand(brandModel);
}
if (!string.IsNullOrEmpty(modelname) && !string.IsNullOrEmpty(modelratio.ToString()))
{
ModelViewModel modelModel = new()
{
ModelSpec = modelname,
ModelRatio = modelratio
};
_modelLogic.PostModel(modelModel);
}
if(brand != null && model != null)
{
StorageViewModel storageModel = new()
{
Brand_ID = brand,
Model_ID = model,
CarRatio = _modelLogic._model.First(x => x.ID == model).ModelRatio + _brandLogic._brand.First(x => x.ID == brand).BrandRatio
};
_storageLogic.PostCar(storageModel);
}
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Storage()
{
return View(_storageLogic._storageFull);
}
[HttpGet]
public IActionResult Contracts()
{
ViewBag.Contracts = _contractLogic._contracts.Where(contract => contract.Status != ContractStatus.finished).ToList();
return View(_contractLogic._contracts);
}
[HttpPost]
public void Contracts(int contract)
{
ContractViewModel model = new()
{
ID = contract,
CarID = _contractLogic._contracts.First(x => x.ID == contract).CarID,
};
_contractLogic.ChangeContractStatus(model, false);
Response.Redirect("Index");
}
[HttpGet]
public IActionResult TopCars()
{
return View(_complicatedQueriesLogic._topCars);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[HttpPost]
public decimal Calc(int id, string date)
{
return (decimal)(_storageLogic._storageFull.First(x => x.ID == id).CarRatio * (Convert.ToInt32((DateTime.Parse(date) - DateTime.Now).TotalHours) * 5));
}
public void UpdateData()
{
_contractLogic._contracts = _contractLogic.ReadContracts().Result;
_storageLogic._storageFree = _storageLogic.ReadStorage(true).Result;
_storageLogic._storageFull = _storageLogic.ReadStorage(false).Result;
_clientLogic._clients = _clientLogic.ReadClients().Result;
}
}
}

View File

@ -0,0 +1,9 @@

namespace RentalBusiness.Enums
{
public enum CarStatus
{
available,
is_taken
}
}

View File

@ -0,0 +1,9 @@
namespace RentalBusiness.Enums
{
public enum ContractStatus
{
in_process,
finished,
expired
}
}

View File

@ -0,0 +1,316 @@
// <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 RentalBusiness.Enums;
using RentalBusiness.Models;
#nullable disable
namespace RentalBusiness.Migrations
{
[DbContext(typeof(RentalbusinessContext))]
[Migration("20230402145704_EnumsCreation")]
partial class EnumsCreation
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "car_status", new[] { "available", "is_taken" });
NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "contract_status", new[] { "in_process", "finished", "expired" });
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("RentalBusiness.Models.Brand", b =>
{
b.Property<int>("BrandId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("brand_id")
.HasComment("Contains serial variable to identify each car brand.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("BrandId"));
b.Property<string>("BrandName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("brand_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains brand name of car.");
b.Property<int>("BrandRatio")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("brand_ratio")
.HasDefaultValueSql("1")
.HasComment("Contains ratio to calculate renting price.");
b.HasKey("BrandId")
.HasName("brand_pkey");
b.ToTable("brand", null, t =>
{
t.HasComment("Contains info about existing brand names and their ratio for future renting price.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Contract", b =>
{
b.Property<int>("ContractId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("contract_id")
.HasComment("Contains serial variable to identify each contract.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ContractId"));
b.Property<int>("CarId")
.HasColumnType("integer")
.HasColumnName("car_id")
.HasComment("Contains key which depicts a specific car from foreign table.");
b.Property<int>("CustomerId")
.HasColumnType("integer")
.HasColumnName("customer_id")
.HasComment("Contains key which depicts a specific customer from foreign table.");
b.Property<decimal>("Price")
.HasPrecision(10)
.HasColumnType("numeric(10)")
.HasColumnName("price")
.HasComment("Contains a total cost of a contract from brand and model ration multiplying the length of rental date.");
b.Property<DateTime>("RentalDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp without time zone")
.HasColumnName("rental_date")
.HasDefaultValueSql("'1111-01-01 00:00:00'::timestamp without time zone")
.HasComment("Contains info about start rental date.");
b.Property<DateTime>("ReturnDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp without time zone")
.HasColumnName("return_date")
.HasDefaultValueSql("'1111-01-01 00:00:00'::timestamp without time zone")
.HasComment("Contains info about ending rental date.");
b.Property<ContractStatus>("Status")
.HasColumnType("contract_status");
b.HasKey("ContractId")
.HasName("contract_pkey");
b.HasIndex("CarId");
b.HasIndex("CustomerId");
b.ToTable("contract", null, t =>
{
t.HasComment("Contains info about contracts which have ever been made.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Customer", b =>
{
b.Property<int>("CustomerId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("customer_id")
.HasComment("Contains serial variable to identify each customer.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("CustomerId"));
b.Property<string>("FirstName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("first_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains first name of a customer.");
b.Property<string>("IdCard")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("id_card")
.HasDefaultValueSql("0")
.HasComment("Contains id card digits.");
b.Property<string>("LastName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("last_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains last name of a customer.");
b.Property<string>("MiddleName")
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("middle_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains(if exists) middle name of a customer.");
b.HasKey("CustomerId")
.HasName("customer_pkey");
b.ToTable("customer", null, t =>
{
t.HasComment("Contains info about customer who have ever rented cars.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Model", b =>
{
b.Property<int>("ModelId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("model_id")
.HasComment("Contains serial variable to identify each model specification.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ModelId"));
b.Property<int>("ModelRatio")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("model_ratio")
.HasDefaultValueSql("1")
.HasComment("Contains ratio of model specification to calculate price of renting.");
b.Property<string>("ModelSpec")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("model_spec")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains name of model specification.");
b.HasKey("ModelId")
.HasName("model_pkey");
b.ToTable("model", null, t =>
{
t.HasComment("Contains info about existing model specifications and ration for future calculation of renting price.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Storage", b =>
{
b.Property<int>("CarId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("car_id")
.HasComment("Contains serial variable to identify each car.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("CarId"));
b.Property<int>("BrandId")
.HasColumnType("integer")
.HasColumnName("brand_id")
.HasComment("Contains key from brand table which depicts brand.");
b.Property<int>("CarRatioPerHour")
.HasColumnType("integer")
.HasColumnName("car_ratio_per_hour")
.HasComment("Contains variable which consists of ratio from model and brand columns in foreign tables.");
b.Property<int>("ModelId")
.HasColumnType("integer")
.HasColumnName("model_id")
.HasComment("Contains key from model table which depicts model.");
b.Property<CarStatus>("Status")
.HasColumnType("car_status");
b.HasKey("CarId")
.HasName("storage_pkey");
b.HasIndex("BrandId");
b.HasIndex("ModelId");
b.ToTable("storage", null, t =>
{
t.HasComment("Contains info about available cars for renting.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Contract", b =>
{
b.HasOne("RentalBusiness.Models.Storage", "Car")
.WithMany("Contracts")
.HasForeignKey("CarId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("contract_storage_id_fkey");
b.HasOne("RentalBusiness.Models.Customer", "Customer")
.WithMany("Contracts")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("contract_customer_id_fkey");
b.Navigation("Car");
b.Navigation("Customer");
});
modelBuilder.Entity("RentalBusiness.Models.Storage", b =>
{
b.HasOne("RentalBusiness.Models.Brand", "Brand")
.WithMany("Storages")
.HasForeignKey("BrandId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("storage_brand_id_fkey");
b.HasOne("RentalBusiness.Models.Model", "Model")
.WithMany("Storages")
.HasForeignKey("ModelId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("storage_model_id_fkey");
b.Navigation("Brand");
b.Navigation("Model");
});
modelBuilder.Entity("RentalBusiness.Models.Brand", b =>
{
b.Navigation("Storages");
});
modelBuilder.Entity("RentalBusiness.Models.Customer", b =>
{
b.Navigation("Contracts");
});
modelBuilder.Entity("RentalBusiness.Models.Model", b =>
{
b.Navigation("Storages");
});
modelBuilder.Entity("RentalBusiness.Models.Storage", b =>
{
b.Navigation("Contracts");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,167 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using RentalBusiness.Enums;
#nullable disable
namespace RentalBusiness.Migrations
{
/// <inheritdoc />
public partial class EnumsCreation : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("Npgsql:Enum:car_status", "available,is_taken")
.Annotation("Npgsql:Enum:contract_status", "in_process,finished,expired");
migrationBuilder.CreateTable(
name: "brand",
columns: table => new
{
brand_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains serial variable to identify each car brand.")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
brand_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, defaultValueSql: "'unknown'::character varying", comment: "Contains brand name of car."),
brand_ratio = table.Column<int>(type: "integer", nullable: false, defaultValueSql: "1", comment: "Contains ratio to calculate renting price.")
},
constraints: table =>
{
table.PrimaryKey("brand_pkey", x => x.brand_id);
},
comment: "Contains info about existing brand names and their ratio for future renting price.");
migrationBuilder.CreateTable(
name: "customer",
columns: table => new
{
customer_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains serial variable to identify each customer.")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
last_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, defaultValueSql: "'unknown'::character varying", comment: "Contains last name of a customer."),
first_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, defaultValueSql: "'unknown'::character varying", comment: "Contains first name of a customer."),
middle_name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true, defaultValueSql: "'unknown'::character varying", comment: "Contains(if exists) middle name of a customer."),
id_card = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, defaultValueSql: "0", comment: "Contains id card digits.")
},
constraints: table =>
{
table.PrimaryKey("customer_pkey", x => x.customer_id);
},
comment: "Contains info about customer who have ever rented cars.");
migrationBuilder.CreateTable(
name: "model",
columns: table => new
{
model_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains serial variable to identify each model specification.")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
model_spec = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false, defaultValueSql: "'unknown'::character varying", comment: "Contains name of model specification."),
model_ratio = table.Column<int>(type: "integer", nullable: false, defaultValueSql: "1", comment: "Contains ratio of model specification to calculate price of renting.")
},
constraints: table =>
{
table.PrimaryKey("model_pkey", x => x.model_id);
},
comment: "Contains info about existing model specifications and ration for future calculation of renting price.");
migrationBuilder.CreateTable(
name: "storage",
columns: table => new
{
car_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains serial variable to identify each car.")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
brand_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains key from brand table which depicts brand."),
model_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains key from model table which depicts model."),
car_ratio_per_hour = table.Column<int>(type: "integer", nullable: false, comment: "Contains variable which consists of ratio from model and brand columns in foreign tables."),
car_status = table.Column<CarStatus>(type: "car_status", nullable: false, comment: "Contains the current state of car, whether it's available for rent or not.")
},
constraints: table =>
{
table.PrimaryKey("storage_pkey", x => x.car_id);
table.ForeignKey(
name: "storage_brand_id_fkey",
column: x => x.brand_id,
principalTable: "brand",
principalColumn: "brand_id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "storage_model_id_fkey",
column: x => x.model_id,
principalTable: "model",
principalColumn: "model_id",
onDelete: ReferentialAction.Cascade);
},
comment: "Contains info about available cars for renting.");
migrationBuilder.CreateTable(
name: "contract",
columns: table => new
{
contract_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains serial variable to identify each contract.")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
car_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains key which depicts a specific car from foreign table."),
customer_id = table.Column<int>(type: "integer", nullable: false, comment: "Contains key which depicts a specific customer from foreign table."),
rental_date = table.Column<DateTime>(type: "timestamp without time zone", nullable: false, defaultValueSql: "'1111-01-01 00:00:00'::timestamp without time zone", comment: "Contains info about start rental date."),
return_date = table.Column<DateTime>(type: "timestamp without time zone", nullable: false, defaultValueSql: "'1111-01-01 00:00:00'::timestamp without time zone", comment: "Contains info about ending rental date."),
price = table.Column<decimal>(type: "numeric(10)", precision: 10, nullable: false, comment: "Contains a total cost of a contract from brand and model ration multiplying the length of rental date."),
contract_status = table.Column<ContractStatus>(type: "contract_status", nullable: false, comment: "Contains the current state of contract.")
},
constraints: table =>
{
table.PrimaryKey("contract_pkey", x => x.contract_id);
table.ForeignKey(
name: "contract_customer_id_fkey",
column: x => x.customer_id,
principalTable: "customer",
principalColumn: "customer_id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "contract_storage_id_fkey",
column: x => x.car_id,
principalTable: "storage",
principalColumn: "car_id",
onDelete: ReferentialAction.Cascade);
},
comment: "Contains info about contracts which have ever been made.");
migrationBuilder.CreateIndex(
name: "IX_contract_car_id",
table: "contract",
column: "car_id");
migrationBuilder.CreateIndex(
name: "IX_contract_customer_id",
table: "contract",
column: "customer_id");
migrationBuilder.CreateIndex(
name: "IX_storage_brand_id",
table: "storage",
column: "brand_id");
migrationBuilder.CreateIndex(
name: "IX_storage_model_id",
table: "storage",
column: "model_id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "contract");
migrationBuilder.DropTable(
name: "customer");
migrationBuilder.DropTable(
name: "storage");
migrationBuilder.DropTable(
name: "brand");
migrationBuilder.DropTable(
name: "model");
}
}
}

View File

@ -0,0 +1,313 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using RentalBusiness.Enums;
using RentalBusiness.Models;
#nullable disable
namespace RentalBusiness.Migrations
{
[DbContext(typeof(RentalbusinessContext))]
partial class RentalbusinessContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "car_status", new[] { "available", "is_taken" });
NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "contract_status", new[] { "in_process", "finished", "expired" });
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("RentalBusiness.Models.Brand", b =>
{
b.Property<int>("BrandId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("brand_id")
.HasComment("Contains serial variable to identify each car brand.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("BrandId"));
b.Property<string>("BrandName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("brand_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains brand name of car.");
b.Property<int>("BrandRatio")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("brand_ratio")
.HasDefaultValueSql("1")
.HasComment("Contains ratio to calculate renting price.");
b.HasKey("BrandId")
.HasName("brand_pkey");
b.ToTable("brand", null, t =>
{
t.HasComment("Contains info about existing brand names and their ratio for future renting price.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Contract", b =>
{
b.Property<int>("ContractId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("contract_id")
.HasComment("Contains serial variable to identify each contract.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ContractId"));
b.Property<int>("CarId")
.HasColumnType("integer")
.HasColumnName("car_id")
.HasComment("Contains key which depicts a specific car from foreign table.");
b.Property<int>("CustomerId")
.HasColumnType("integer")
.HasColumnName("customer_id")
.HasComment("Contains key which depicts a specific customer from foreign table.");
b.Property<decimal>("Price")
.HasPrecision(10)
.HasColumnType("numeric(10)")
.HasColumnName("price")
.HasComment("Contains a total cost of a contract from brand and model ration multiplying the length of rental date.");
b.Property<DateTime>("RentalDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp without time zone")
.HasColumnName("rental_date")
.HasDefaultValueSql("'1111-01-01 00:00:00'::timestamp without time zone")
.HasComment("Contains info about start rental date.");
b.Property<DateTime>("ReturnDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp without time zone")
.HasColumnName("return_date")
.HasDefaultValueSql("'1111-01-01 00:00:00'::timestamp without time zone")
.HasComment("Contains info about ending rental date.");
b.Property<ContractStatus>("Status")
.HasColumnType("contract_status");
b.HasKey("ContractId")
.HasName("contract_pkey");
b.HasIndex("CarId");
b.HasIndex("CustomerId");
b.ToTable("contract", null, t =>
{
t.HasComment("Contains info about contracts which have ever been made.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Customer", b =>
{
b.Property<int>("CustomerId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("customer_id")
.HasComment("Contains serial variable to identify each customer.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("CustomerId"));
b.Property<string>("FirstName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("first_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains first name of a customer.");
b.Property<string>("IdCard")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("id_card")
.HasDefaultValueSql("0")
.HasComment("Contains id card digits.");
b.Property<string>("LastName")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("last_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains last name of a customer.");
b.Property<string>("MiddleName")
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("middle_name")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains(if exists) middle name of a customer.");
b.HasKey("CustomerId")
.HasName("customer_pkey");
b.ToTable("customer", null, t =>
{
t.HasComment("Contains info about customer who have ever rented cars.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Model", b =>
{
b.Property<int>("ModelId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("model_id")
.HasComment("Contains serial variable to identify each model specification.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("ModelId"));
b.Property<int>("ModelRatio")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("model_ratio")
.HasDefaultValueSql("1")
.HasComment("Contains ratio of model specification to calculate price of renting.");
b.Property<string>("ModelSpec")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("model_spec")
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains name of model specification.");
b.HasKey("ModelId")
.HasName("model_pkey");
b.ToTable("model", null, t =>
{
t.HasComment("Contains info about existing model specifications and ration for future calculation of renting price.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Storage", b =>
{
b.Property<int>("CarId")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("car_id")
.HasComment("Contains serial variable to identify each car.");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("CarId"));
b.Property<int>("BrandId")
.HasColumnType("integer")
.HasColumnName("brand_id")
.HasComment("Contains key from brand table which depicts brand.");
b.Property<int>("CarRatioPerHour")
.HasColumnType("integer")
.HasColumnName("car_ratio_per_hour")
.HasComment("Contains variable which consists of ratio from model and brand columns in foreign tables.");
b.Property<int>("ModelId")
.HasColumnType("integer")
.HasColumnName("model_id")
.HasComment("Contains key from model table which depicts model.");
b.Property<CarStatus>("Status")
.HasColumnType("car_status");
b.HasKey("CarId")
.HasName("storage_pkey");
b.HasIndex("BrandId");
b.HasIndex("ModelId");
b.ToTable("storage", null, t =>
{
t.HasComment("Contains info about available cars for renting.");
});
});
modelBuilder.Entity("RentalBusiness.Models.Contract", b =>
{
b.HasOne("RentalBusiness.Models.Storage", "Car")
.WithMany("Contracts")
.HasForeignKey("CarId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("contract_storage_id_fkey");
b.HasOne("RentalBusiness.Models.Customer", "Customer")
.WithMany("Contracts")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("contract_customer_id_fkey");
b.Navigation("Car");
b.Navigation("Customer");
});
modelBuilder.Entity("RentalBusiness.Models.Storage", b =>
{
b.HasOne("RentalBusiness.Models.Brand", "Brand")
.WithMany("Storages")
.HasForeignKey("BrandId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("storage_brand_id_fkey");
b.HasOne("RentalBusiness.Models.Model", "Model")
.WithMany("Storages")
.HasForeignKey("ModelId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("storage_model_id_fkey");
b.Navigation("Brand");
b.Navigation("Model");
});
modelBuilder.Entity("RentalBusiness.Models.Brand", b =>
{
b.Navigation("Storages");
});
modelBuilder.Entity("RentalBusiness.Models.Customer", b =>
{
b.Navigation("Contracts");
});
modelBuilder.Entity("RentalBusiness.Models.Model", b =>
{
b.Navigation("Storages");
});
modelBuilder.Entity("RentalBusiness.Models.Storage", b =>
{
b.Navigation("Contracts");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace RentalBusiness.Models;
/// <summary>
/// Contains info about existing brand names and their ratio for future renting price.
/// </summary>
public partial class Brand
{
/// <summary>
/// Contains serial variable to identify each car brand.
/// </summary>
public int BrandId { get; set; }
/// <summary>
/// Contains brand name of car.
/// </summary>
public string BrandName { get; set; } = null!;
/// <summary>
/// Contains ratio to calculate renting price.
/// </summary>
public int BrandRatio { get; set; }
public virtual ICollection<Storage> Storages { get; } = new List<Storage>();
}

View File

@ -0,0 +1,49 @@
using RentalBusiness.Enums;
using System;
using System.Collections.Generic;
namespace RentalBusiness.Models;
/// <summary>
/// Contains info about contracts which have ever been made.
/// </summary>
public partial class Contract
{
/// <summary>
/// Contains serial variable to identify each contract.
/// </summary>
public int ContractId { get; set; }
/// <summary>
/// Contains key which depicts a specific car from foreign table.
/// </summary>
public int CarId { get; set; }
/// <summary>
/// Contains key which depicts a specific customer from foreign table.
/// </summary>
public int CustomerId { get; set; }
/// <summary>
/// Contains info about start rental date.
/// </summary>
public DateTime RentalDate { get; set; }
/// <summary>
/// Contains info about ending rental date.
/// </summary>
public DateTime ReturnDate { get; set; }
/// <summary>
/// Contains a total cost of a contract from brand and model ration multiplying the length of rental date.
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// Contains a current state of contract.
/// </summary>
public ContractStatus Status { get; set; }
public virtual Storage Car { get; set; } = null!;
public virtual Customer Customer { get; set; } = null!;
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
namespace RentalBusiness.Models;
/// <summary>
/// Contains info about customer who have ever rented cars.
/// </summary>
public partial class Customer
{
/// <summary>
/// Contains serial variable to identify each customer.
/// </summary>
public int CustomerId { get; set; }
/// <summary>
/// Contains last name of a customer.
/// </summary>
public string LastName { get; set; } = null!;
/// <summary>
/// Contains first name of a customer.
/// </summary>
public string FirstName { get; set; } = null!;
/// <summary>
/// Contains(if exists) middle name of a customer.
/// </summary>
public string? MiddleName { get; set; }
/// <summary>
/// Contains id card digits.
/// </summary>
public string IdCard { get; set; } = null!;
public virtual ICollection<Contract> Contracts { get; } = new List<Contract>();
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace RentalBusiness.Models;
/// <summary>
/// Contains info about existing model specifications and ration for future calculation of renting price.
/// </summary>
public partial class Model
{
/// <summary>
/// Contains serial variable to identify each model specification.
/// </summary>
public int ModelId { get; set; }
/// <summary>
/// Contains name of model specification.
/// </summary>
public string ModelSpec { get; set; } = null!;
/// <summary>
/// Contains ratio of model specification to calculate price of renting.
/// </summary>
public int ModelRatio { get; set; }
public virtual ICollection<Storage> Storages { get; } = new List<Storage>();
}

View File

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using RentalBusiness.Enums;
namespace RentalBusiness.Models;
public partial class RentalbusinessContext : DbContext
{
public RentalbusinessContext()
{
}
public RentalbusinessContext(DbContextOptions<RentalbusinessContext> options)
: base(options)
{
}
public virtual DbSet<Brand> Brands { get; set; }
public virtual DbSet<Contract> Contracts { get; set; }
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<Model> Models { get; set; }
public virtual DbSet<Storage> Storages { get; set; }
static RentalbusinessContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseNpgsql("Host=localhost;Port=5432;Database=local;Username=postgres;Password=postgres");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.HasPostgresEnum<CarStatus>()
.HasPostgresEnum<ContractStatus>();
modelBuilder.Entity<Brand>(entity =>
{
entity.HasKey(e => e.BrandId).HasName("brand_pkey");
entity.ToTable("brand", tb => tb.HasComment("Contains info about existing brand names and their ratio for future renting price."));
entity.Property(e => e.BrandId)
.HasComment("Contains serial variable to identify each car brand.")
.HasColumnName("brand_id");
entity.Property(e => e.BrandName)
.HasMaxLength(255)
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains brand name of car.")
.HasColumnName("brand_name");
entity.Property(e => e.BrandRatio)
.HasDefaultValueSql("1")
.HasComment("Contains ratio to calculate renting price.")
.HasColumnName("brand_ratio");
});
modelBuilder.Entity<Contract>(entity =>
{
entity.HasKey(e => e.ContractId).HasName("contract_pkey");
entity.ToTable("contract", tb => tb.HasComment("Contains info about contracts which have ever been made."));
entity.Property(e => e.ContractId)
.HasComment("Contains serial variable to identify each contract.")
.HasColumnName("contract_id");
entity.Property(e => e.CarId)
.HasComment("Contains key which depicts a specific car from foreign table.")
.HasColumnName("car_id");
entity.Property(e => e.CustomerId)
.HasComment("Contains key which depicts a specific customer from foreign table.")
.HasColumnName("customer_id");
entity.Property(e => e.Price)
.HasPrecision(10)
.HasComment("Contains a total cost of a contract from brand and model ration multiplying the length of rental date.")
.HasColumnName("price");
entity.Property(e => e.RentalDate)
.HasDefaultValueSql("'1111-01-01 00:00:00'::timestamp without time zone")
.HasComment("Contains info about start rental date.")
.HasColumnType("timestamp without time zone")
.HasColumnName("rental_date");
entity.Property(e => e.ReturnDate)
.HasDefaultValueSql("'1111-01-01 00:00:00'::timestamp without time zone")
.HasComment("Contains info about ending rental date.")
.HasColumnType("timestamp without time zone")
.HasColumnName("return_date");
entity.HasOne(d => d.Car).WithMany(p => p.Contracts)
.HasForeignKey(d => d.CarId)
.HasConstraintName("contract_storage_id_fkey");
entity.HasOne(d => d.Customer).WithMany(p => p.Contracts)
.HasForeignKey(d => d.CustomerId)
.HasConstraintName("contract_customer_id_fkey");
});
modelBuilder.Entity<Customer>(entity =>
{
entity.HasKey(e => e.CustomerId).HasName("customer_pkey");
entity.ToTable("customer", tb => tb.HasComment("Contains info about customer who have ever rented cars."));
entity.Property(e => e.CustomerId)
.HasComment("Contains serial variable to identify each customer.")
.HasColumnName("customer_id");
entity.Property(e => e.FirstName)
.HasMaxLength(255)
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains first name of a customer.")
.HasColumnName("first_name");
entity.Property(e => e.IdCard)
.HasMaxLength(255)
.HasDefaultValueSql("0")
.HasComment("Contains id card digits.")
.HasColumnName("id_card");
entity.Property(e => e.LastName)
.HasMaxLength(255)
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains last name of a customer.")
.HasColumnName("last_name");
entity.Property(e => e.MiddleName)
.HasMaxLength(255)
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains(if exists) middle name of a customer.")
.HasColumnName("middle_name");
});
modelBuilder.Entity<Model>(entity =>
{
entity.HasKey(e => e.ModelId).HasName("model_pkey");
entity.ToTable("model", tb => tb.HasComment("Contains info about existing model specifications and ration for future calculation of renting price."));
entity.Property(e => e.ModelId)
.HasComment("Contains serial variable to identify each model specification.")
.HasColumnName("model_id");
entity.Property(e => e.ModelRatio)
.HasDefaultValueSql("1")
.HasComment("Contains ratio of model specification to calculate price of renting.")
.HasColumnName("model_ratio");
entity.Property(e => e.ModelSpec)
.HasMaxLength(255)
.HasDefaultValueSql("'unknown'::character varying")
.HasComment("Contains name of model specification.")
.HasColumnName("model_spec");
});
modelBuilder.Entity<Storage>(entity =>
{
entity.HasKey(e => e.CarId).HasName("storage_pkey");
entity.ToTable("storage", tb => tb.HasComment("Contains info about available cars for renting."));
entity.Property(e => e.CarId)
.HasComment("Contains serial variable to identify each car.")
.HasColumnName("car_id");
entity.Property(e => e.BrandId)
.HasComment("Contains key from brand table which depicts brand.")
.HasColumnName("brand_id");
entity.Property(e => e.CarRatioPerHour)
.HasComment("Contains variable which consists of ratio from model and brand columns in foreign tables.")
.HasColumnName("car_ratio_per_hour");
entity.Property(e => e.ModelId)
.HasComment("Contains key from model table which depicts model.")
.HasColumnName("model_id");
entity.HasOne(d => d.Brand).WithMany(p => p.Storages)
.HasForeignKey(d => d.BrandId)
.HasConstraintName("storage_brand_id_fkey");
entity.HasOne(d => d.Model).WithMany(p => p.Storages)
.HasForeignKey(d => d.ModelId)
.HasConstraintName("storage_model_id_fkey");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

View File

@ -0,0 +1,41 @@
using RentalBusiness.Enums;
using System;
using System.Collections.Generic;
namespace RentalBusiness.Models;
/// <summary>
/// Contains info about available cars for renting.
/// </summary>
public partial class Storage
{
/// <summary>
/// Contains serial variable to identify each car.
/// </summary>
public int CarId { get; set; }
/// <summary>
/// Contains key from brand table which depicts brand.
/// </summary>
public int BrandId { get; set; }
/// <summary>
/// Contains key from model table which depicts model.
/// </summary>
public int ModelId { get; set; }
/// <summary>
/// Contains variable which consists of ratio from model and brand columns in foreign tables.
/// </summary>
public int CarRatioPerHour { get; set; }
/// <summary>
/// Contains a current state of car.
/// </summary>
public CarStatus Status { get; set; }
public virtual Brand Brand { get; set; } = null!;
public virtual ICollection<Contract> Contracts { get; } = new List<Contract>();
public virtual Model Model { get; set; } = null!;
}

View File

@ -0,0 +1,9 @@
namespace RentalBusiness.Models.ViewModels
{
public class BrandViewModel
{
public int? ID { get; set; }
public string BrandName { get; set; } = string.Empty;
public int? BrandRatio { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace RentalBusiness.Models.ViewModels
{
public class ClientViewModel
{
public int ID { get; set; }
public string FullName { get; set; } = string.Empty;
public string IDCard { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,18 @@
using RentalBusiness.Enums;
namespace RentalBusiness.Models.ViewModels
{
public class ContractViewModel
{
public int? ID { get; set; }
public int CarID { get; set; }
public string CarInfo { get; set; } = string.Empty;
public int CustomerID { get; set; }
public string CustomerFullName { get; set; } = string.Empty;
public string CustomerIDCard { get; set; } = string.Empty;
public DateTime CurDate { get; set; } = DateTime.Now;
public DateTime? ReturnDate { get; set; }
public decimal Price { get; set; }
public ContractStatus Status { get; set; } = ContractStatus.in_process;
}
}

View File

@ -0,0 +1,10 @@
namespace RentalBusiness.Models.ViewModels
{
public class ModelViewModel
{
public int? ID { get; set; }
public string ModelSpec { get; set; } = string.Empty;
public int? ModelRatio { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using RentalBusiness.Enums;
namespace RentalBusiness.Models.ViewModels
{
public class StorageViewModel
{
public int ID { get; set; }
public string CarInfo { get; set; } = string.Empty;
public int? CarRatio { get; set; }
public CarStatus CarStatus { get; set; } = CarStatus.available;
public int? Brand_ID { get; set; }
public int? Model_ID { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace RentalBusiness.Models.ViewModels
{
public class TopCarViewModel
{
public int ID { get; set; }
public string CarInfo { get; set; } = string.Empty;
public int Quantity { get; set; }
public decimal TotalIncome { get; set; }
}
}

View File

@ -1,10 +1,37 @@
var builder = WebApplication.CreateBuilder(args);
using Microsoft.EntityFrameworkCore;
using Npgsql;
using RentalBusiness.AuxilaryElements.BusinessLogic;
using RentalBusiness.Enums;
using RentalBusiness.Models;
var builder = WebApplication.CreateBuilder(args);
var dataSourceBuilder = new NpgsqlDataSourceBuilder("Host=localhost;Database=local;Username=postgres;Password=postgres");
dataSourceBuilder.MapEnum<CarStatus>();
dataSourceBuilder.MapEnum<ContractStatus>();
await using var dataSource = dataSourceBuilder.Build();
await using var connection = await dataSource.OpenConnectionAsync();
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext<RentalbusinessContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("ASPDB")));
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
using (var context = new RentalbusinessContext(services.GetRequiredService<DbContextOptions<RentalbusinessContext>>()))
{
if(!context.Models.Any() && !context.Brands.Any() && !context.Customers.Any() && !context.Storages.Any())
{
await SeedData.InitializeBrands(connection);
await SeedData.InitializeModels(connection);
await SeedData.InitializeCustomers(connection);
await SeedData.InitializeCars(connection);
}
}
}
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{

View File

@ -6,4 +6,12 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,51 @@
@{
ViewData["Title"] = "Car";
}
<div class="text-center">
<h2 class="display-4">Add a car</h2>
</div>
<form method="post">
<div class="flex-container" style="flex-direction: row; justify-content: space-between; display: flex; height: 100vh;">
<aside style="flex: 1"></aside>
<div class="flex-containerB1" style="flex-direction: column; flex: 4; gap: 20px; display: flex; align-items: center; justify-content: center;">
<div class="brandtitle" style="text-align: center; font-size: 25px;">ADD A BRAND</div>
<div class="brandname" style="text-align: left; font-size: 15px;">Brand name:</div>
<input type="text" id="brandname" name="brandname" />
<div class="brandratio" style="text-align: left; font-size: 15px;">Brand ratio:</div>
<input type="text" id="brandratio" name="brandratio" />
<input type="submit" id="brandbtn" value="Brand" class="btn btn-primary" />
</div>
<aside style="flex: 1"></aside>
<div class="flex-containerB2" style="flex-direction: column; flex: 4; gap: 20px;display: flex; align-items: center; justify-content: center;">
<div class="modeltitle" style="text-align: center; font-size: 25px;">ADD A MODEL</div>
<div class="modelname" style="text-align: left; font-size: 15px;">Model name:</div>
<input type="text" id="modelname" name="modelname" />
<div class="modelratio" style="text-align: left; font-size: 15px;">Model ratio:</div>
<input type="text" id="modelratio" name="modelratio" />
<input type="submit" id="modelbtn" value="Model" class="btn btn-primary" />
</div>
<aside style="flex: 1"></aside>
<div class="flex-containerB3" style="flex-direction: column; flex: 4; gap: 20px;display: flex; align-items: center; justify-content: center;">
<div class="brandtitle" style="text-align: center; font-size: 25px;">ADD A CAR</div>
<select id="brand" name="brand" class="form-control" asp-items="@(new SelectList(@ViewBag.Brands,"ID","BrandName"))"></select>
<select id="model" name="model" class="form-control" asp-items="@(new SelectList(@ViewBag.Models,"ID","ModelSpec"))"></select>
<input type="submit" id="carbtn" value="Car" class="btn btn-primary" />
</div>
<aside style="flex: 1"></aside>
</div>
</form>
<script>
$('#update').on('change', function () {
buttonchange();
});
function buttonchange() {
if (document.getElementById('update').checked) {
document.getElementById('funcbutton').value = "Update";
}
else
{
document.getElementById('funcbutton').value = "Add";
};
}
</script>

View File

@ -0,0 +1,80 @@
@using RentalBusiness.Models.ViewModels
@model List<ContractViewModel>
@{
ViewData["Title"] = "Contracts";
}
<div class="text-center">
<h1 class="display-4">Contracts</h1>
</div>
<div class="text-center">
@{
<table class="table">
<thead>
<tr>
<th>
ID
</th>
<th>
Car
</th>
<th>
Customer
</th>
<th>
IDCard
</th>
<th>
Creation date
</th>
<th>
Return date
</th>
<th>
Total
</th>
<th>
Status
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.ID)
</td>
<td>
@Html.DisplayFor(modelItem => item.CarInfo)
</td>
<td>
@Html.DisplayFor(modelItem => item.CustomerFullName)
</td>
<td>
@Html.DisplayFor(modelItem => item.CustomerIDCard)
</td>
<td>
@Html.DisplayFor(modelItem => item.CurDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReturnDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Status)
</td>
</tr>
}
</tbody>
</table>
}
<form method="post">
<select id="contract" name="contract" class="form-control" asp-items="@(new SelectList(@ViewBag.Contracts,"ID","ID"))"></select>
<input type="submit" value="Finished" class="btn btn-primary" />
</form>
</div>

View File

@ -0,0 +1,47 @@
@{
ViewData["Title"] = "Customer";
}
<div class="text-center">
<h2 class="display-4">Add/Update a customer</h2>
</div>
<form method="post">
<div class="row">
<div class="col-6">Customer:</div>
<div class="col-8"><select id="customer" name="customer" class="form-control" asp-items="@(new SelectList(@ViewBag.Clients,"ID","FullName"))"></select></div>
</div>
<div class="row">
<div class="col-6">FirstName:</div>
<div class="col-8"><input type="text" id="firstname" name="fname" /></div>
</div>
<div class="row">
<div class="col-6">LastName:</div>
<div class="col-8"><input type="text" id="lastname" name="lname" /></div>
</div>
<div class="row">
<div class="col-6">MiddleName:</div>
<div class="col-8"><input type="text" id="middlename" name="mname" /></div>
</div>
<div class="row">
<div class="col-6">IDCard:</div>
<div class="col-8"><input type="text" id="customercard" name="idcard" /></div>
</div>
<div class="row">
<div class="col-3"><input type="checkbox" id="update" name="update">
<label for="update">Update</label>
</div>
<div class="col-8"><input type="submit" id="funcbutton" name="funcbutton" value="Add" class="btn btn-primary" /></div>
</div>
</form>
<script>
$('#update').on('change', function () {
buttonchange();
});
function buttonchange() {
if (document.getElementById('update').checked) {
document.getElementById('funcbutton').value = "Update";
}
else {
document.getElementById('funcbutton').value = "Add";
};
}
</script>

View File

@ -1,8 +1,60 @@
@{
ViewData["Title"] = "Home Page";
ViewData["Title"] = "Rent";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
<h2 class="display-4">Rent page</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Car:</div>
<div class="col-8">
<select id="car" name="car" class="form-control" asp-items="@(new SelectList(@ViewBag.Cars,"ID","CarInfo"))"></select>
</div>
</div>
<div class="row">
<div class="col-4">Customer:</div>
<div class="col-8">
<select id="customer" name="customer" class="form-control" asp-items="@(new SelectList(@ViewBag.Clients,"ID","FullName"))"></select>
</div>
</div>
<div class="row">
<div class="col-4">ReturnDate:</div>
<div class="col-8">
<input type="date" id="returndate" name="returndate">
</div>
</div>
<div class="row">
<div class="col-4">Total:</div>
<div class="col-8"><input type="text" id="sum" name="sum" readonly /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Create" class="btn btn-primary" /></div>
</div>
</form>
<script>
$('#car').on('change', function ()
{
check();
});
$('#returndate').on('change', function () {
check();
});
function check()
{
var car = $('#car').val();
var date = $('#returndate').val();
if (car && date) {
$.ajax({
method: "POST",
url: "/Home/Calc",
data: { id: car, date: date },
success: function (result)
{
$("#sum").val(result);
}
});
};
}
</script>

View File

@ -0,0 +1,44 @@
@using RentalBusiness.Models.ViewModels
@model List<StorageViewModel>
@{
ViewData["Title"] = "Storage";
}
<div class="text-center">
<h1 class="display-4">Storage</h1>
</div>
<div class="text-center">
@{
<table class="table">
<thead>
<tr>
<th>
Car
</th>
<th>
Ratio
</th>
<th>
Status
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.CarInfo)
</td>
<td>
@Html.DisplayFor(modelItem => item.CarRatio)
</td>
<td>
@Html.DisplayFor(modelItem => item.CarStatus)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -0,0 +1,43 @@
@using RentalBusiness.Models.ViewModels
@model List<TopCarViewModel>
@{
ViewData["Title"] = "TopCars";
}
<div class="text-center">
<h2 class="display-4">The most profitable cars</h2>
</div>
<div class="text-center">
@{
<table class="table">
<thead>
<tr>
<th>
Car
</th>
<th>
TotalIncome
</th>
<th>
ContractsQuantity
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.CarInfo)
</td>
<td>
@Html.DisplayFor(modelItem => item.TotalIncome)
</td>
<td>
@Html.DisplayFor(modelItem => item.Quantity)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -3,27 +3,39 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RentalBusiness</title>
<title>@ViewData["Title"] - EmployeeApp</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RentalBusiness.styles.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/site.css" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">RentalBusiness</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bgwhite border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" aspaction="Index">Rental business</a>
<button class="navbar-toggler" type="button" datatoggle="collapse" data-target=".navbar-collapse" ariacontrols="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<div class="navbar-collapse collapse d-sm-inline-flex flex-smrow-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="TopCars">TOP CARS</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Storage">STORAGE</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Contracts">CONTRACTS</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Index">ADD CONTRACT</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Car">ADD BRAND/MODEL/CAR</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Customer">ADD CUSTOMER</a>
</li>
</ul>
</div>
@ -35,15 +47,6 @@
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2023 - RentalBusiness - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
<script src="~/js/site.js" asp-append-version="true"></script> @RenderSection("Scripts", required: false)
</body>
</html>

View File

@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
"ASPDB": "Host=localhost;Database=local;Username=postgres;Password=postgres"
}
}