From ef7ef2979c5c1fbdd624383f1c9a478fb806cc01 Mon Sep 17 00:00:00 2001 From: Erik Bergvall Date: Mon, 27 Jan 2025 13:15:10 +0100 Subject: [PATCH] Core exersice + Topping and DeliveryDriver Extensions --- exercise.pizzashopapi/DTO/CustomerPost.cs | 7 + exercise.pizzashopapi/DTO/OrderPost.cs | 9 + .../DTO/OrderToppingsPost.cs | 10 + exercise.pizzashopapi/DTO/PizzaPost.cs | 8 + exercise.pizzashopapi/DTO/ToppingPost.cs | 8 + exercise.pizzashopapi/Data/DataContext.cs | 8 +- exercise.pizzashopapi/Data/Seeder.cs | 30 ++- .../EndPoints/PizzaShopApi.cs | 197 +++++++++++++++++- .../20250127121042_Pizza.Designer.cs | 144 +++++++++++++ .../Migrations/20250127121042_Pizza.cs | 120 +++++++++++ .../Migrations/DataContextModelSnapshot.cs | 141 +++++++++++++ .../Models/DeliveryDriver.cs | 8 + exercise.pizzashopapi/Models/Order.cs | 5 +- exercise.pizzashopapi/Models/OrderDTO.cs | 14 ++ exercise.pizzashopapi/Models/OrderPut.cs | 7 + exercise.pizzashopapi/Models/OrderToppings.cs | 9 + exercise.pizzashopapi/Models/Topping.cs | 9 + .../Repository/IRepository.cs | 25 ++- .../Repository/Repository.cs | 122 ++++++++++- .../exercise.pizzashopapi.csproj | 12 +- 20 files changed, 874 insertions(+), 19 deletions(-) create mode 100644 exercise.pizzashopapi/DTO/CustomerPost.cs create mode 100644 exercise.pizzashopapi/DTO/OrderPost.cs create mode 100644 exercise.pizzashopapi/DTO/OrderToppingsPost.cs create mode 100644 exercise.pizzashopapi/DTO/PizzaPost.cs create mode 100644 exercise.pizzashopapi/DTO/ToppingPost.cs create mode 100644 exercise.pizzashopapi/Migrations/20250127121042_Pizza.Designer.cs create mode 100644 exercise.pizzashopapi/Migrations/20250127121042_Pizza.cs create mode 100644 exercise.pizzashopapi/Migrations/DataContextModelSnapshot.cs create mode 100644 exercise.pizzashopapi/Models/DeliveryDriver.cs create mode 100644 exercise.pizzashopapi/Models/OrderDTO.cs create mode 100644 exercise.pizzashopapi/Models/OrderPut.cs create mode 100644 exercise.pizzashopapi/Models/OrderToppings.cs create mode 100644 exercise.pizzashopapi/Models/Topping.cs diff --git a/exercise.pizzashopapi/DTO/CustomerPost.cs b/exercise.pizzashopapi/DTO/CustomerPost.cs new file mode 100644 index 0000000..7076926 --- /dev/null +++ b/exercise.pizzashopapi/DTO/CustomerPost.cs @@ -0,0 +1,7 @@ +namespace exercise.pizzashopapi.DTO +{ + public class CustomerPost + { + public string Name { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/OrderPost.cs b/exercise.pizzashopapi/DTO/OrderPost.cs new file mode 100644 index 0000000..beac158 --- /dev/null +++ b/exercise.pizzashopapi/DTO/OrderPost.cs @@ -0,0 +1,9 @@ +namespace exercise.pizzashopapi.DTO +{ + public class OrderPost + { + public int CustomerId { get; set; } + public int PizzaId { get; set; } + public int? DriverId { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/OrderToppingsPost.cs b/exercise.pizzashopapi/DTO/OrderToppingsPost.cs new file mode 100644 index 0000000..77a4ae0 --- /dev/null +++ b/exercise.pizzashopapi/DTO/OrderToppingsPost.cs @@ -0,0 +1,10 @@ +using exercise.pizzashopapi.Models; + +namespace exercise.pizzashopapi.DTO +{ + public class OrderToppingsPost + { + public int OrderId { get; set; } + public int ToppingId { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/PizzaPost.cs b/exercise.pizzashopapi/DTO/PizzaPost.cs new file mode 100644 index 0000000..329b91d --- /dev/null +++ b/exercise.pizzashopapi/DTO/PizzaPost.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.DTO +{ + public class PizzaPost + { + public string Name { get; set; } + public decimal Price { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/ToppingPost.cs b/exercise.pizzashopapi/DTO/ToppingPost.cs new file mode 100644 index 0000000..6d3c81e --- /dev/null +++ b/exercise.pizzashopapi/DTO/ToppingPost.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.DTO +{ + public class ToppingPost + { + public string Name { get; set; } + public decimal Price { get; set; } + } +} diff --git a/exercise.pizzashopapi/Data/DataContext.cs b/exercise.pizzashopapi/Data/DataContext.cs index 129199e..b0384ef 100644 --- a/exercise.pizzashopapi/Data/DataContext.cs +++ b/exercise.pizzashopapi/Data/DataContext.cs @@ -1,4 +1,5 @@ -using exercise.pizzashopapi.Models; +using System.Numerics; +using exercise.pizzashopapi.Models; using Microsoft.EntityFrameworkCore; namespace exercise.pizzashopapi.Data @@ -12,10 +13,10 @@ public DataContext() connectionString = configuration.GetValue("ConnectionStrings:DefaultConnectionString"); } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(connectionString); - //set primary of order? //seed data? @@ -24,5 +25,8 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) public DbSet Pizzas { get; set; } public DbSet Customers { get; set; } public DbSet Orders { get; set; } + public DbSet Toppings { get; set; } + public DbSet OrderToppings { get; set; } + public DbSet DeliveryDrivers { get; set; } } } diff --git a/exercise.pizzashopapi/Data/Seeder.cs b/exercise.pizzashopapi/Data/Seeder.cs index f87fbef..44b7c03 100644 --- a/exercise.pizzashopapi/Data/Seeder.cs +++ b/exercise.pizzashopapi/Data/Seeder.cs @@ -1,4 +1,5 @@ using exercise.pizzashopapi.Models; +using Microsoft.EntityFrameworkCore; namespace exercise.pizzashopapi.Data { @@ -10,22 +11,41 @@ public async static void SeedPizzaShopApi(this WebApplication app) { if(!db.Customers.Any()) { - db.Add(new Customer() { Name="Nigel" }); - db.Add(new Customer() { Name = "Dave" }); + db.Customers.Add(new Customer() { Name="Nigel" }); + db.Customers.Add(new Customer() { Name = "Dave" }); await db.SaveChangesAsync(); } if(!db.Pizzas.Any()) { - db.Add(new Pizza() { Name = "Cheese & Pineapple" }); - db.Add(new Pizza() { Name = "Vegan Cheese Tastic" }); + db.Pizzas.Add(new Pizza() { Name = "Cheese & Pineapple" }); + db.Pizzas.Add(new Pizza() { Name = "Vegan Cheese Tastic" }); await db.SaveChangesAsync(); } //order data - if(1==1) + if(!db.Orders.Any()) { + db.Orders.Add(new Order() { CustomerId=1, PizzaId=1 }); + db.Orders.Add(new Order() { CustomerId=2, PizzaId=2 }); + await db.SaveChangesAsync(); + } + + if (!db.Toppings.Any()) + { + db.Toppings.Add(new Topping() { Name = "Garlic", Price = 0.12m }); + await db.SaveChangesAsync(); + } + if (!db.OrderToppings.Any()) + { + db.OrderToppings.Add(new OrderToppings() { OrderId = 1, ToppingId = 1 }); + await db.SaveChangesAsync(); + } + + if (!db.DeliveryDrivers.Any()) + { + db.DeliveryDrivers.Add(new DeliveryDriver() { Name = "Vilgot" }); await db.SaveChangesAsync(); } } diff --git a/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs b/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs index f8be2b0..4c5ca21 100644 --- a/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs +++ b/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs @@ -1,5 +1,8 @@ -using exercise.pizzashopapi.Repository; +using exercise.pizzashopapi.DTO; +using exercise.pizzashopapi.Models; +using exercise.pizzashopapi.Repository; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; namespace exercise.pizzashopapi.EndPoints { @@ -7,9 +10,199 @@ public static class PizzaShopApi { public static void ConfigurePizzaShopApi(this WebApplication app) { + var pizzaGroup = app.MapGroup("pizzaShop"); + + pizzaGroup.MapGet("/pizzas", GetPizzas); + pizzaGroup.MapGet("/pizzas/{id}", GetPizza); + pizzaGroup.MapPost("/pizzas", AddPizza); + pizzaGroup.MapGet("/customers", GetCustomers); + pizzaGroup.MapGet("/customers/{id}", GetCustomer); + pizzaGroup.MapPost("/customers", AddCustomer); + pizzaGroup.MapGet("/orders", GetOrders); + pizzaGroup.MapGet("/orders/{id}", GetOrder); + pizzaGroup.MapGet("/ordersbycustomer/{id}", GetOrderByCustomer); + pizzaGroup.MapGet("/ordersbydriver/{id}", GetOrderByDriver); + pizzaGroup.MapPut("/orders/{id}", UpdateDriver); + pizzaGroup.MapPost("/orders", AddOrder); + pizzaGroup.MapGet("/toppings", GetToppings); + pizzaGroup.MapGet("/toppings/{id}", GetTopping); + pizzaGroup.MapPost("/toppings", AddTopping); + pizzaGroup.MapGet("/ordertoppings", GetOrderToppings); + pizzaGroup.MapGet("/ordertoppings/{id}", GetOrderTopping); + pizzaGroup.MapGet("/ordertoppingsbyorder/{id}", GetOrderToppingByOrder); + pizzaGroup.MapPost("/ordertoppings", AddOrderToppings); + } + + public static async Task GetPizzas(IRepository repository) + { + return TypedResults.Ok(await repository.GetPizzas()); + } + + public static async Task GetPizza(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetPizza(id)); + } + + public static async Task AddPizza(IRepository repository, PizzaPost model) + { + Pizza pizza = new Pizza + { + Price = model.Price, + Name = model.Name, + }; + var result = await repository.AddPizza(pizza); + return TypedResults.Created($"https://localhost:7138/pizzas/{result.Id}", result); + } + + public static async Task GetCustomers(IRepository repository) + { + return TypedResults.Ok(await repository.GetCustomers()); + } + + public static async Task GetCustomer(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetCustomer(id)); + } + + public static async Task AddCustomer(IRepository repository, CustomerPost model) + { + Customer customer = new Customer + { + Name = model.Name, + }; + var result = await repository.AddCustomer(customer); + return TypedResults.Created($"https://localhost:7138/customers/{result.Id}", result); + } + + public static async Task GetOrders(IRepository repository) + { + List orderDTOs = new List(); + var results = await repository.GetOrders(); + foreach (var order in results) + { + var customer = await repository.GetCustomer(order.CustomerId); + var pizza = await repository.GetPizza(order.PizzaId); + var driver = await repository.GetDriver(order.DriverId); + if (driver == null) + { + OrderDTO orderDTO = new OrderDTO + { + Id = order.Id, + CustomerId = customer.Id, + CustomerName = customer.Name, + PizzaId = pizza.Id, + PizzaName = pizza.Name, + }; + orderDTOs.Add(orderDTO); + } + else + { + OrderDTO orderDTO = new OrderDTO + { + Id = order.Id, + CustomerId = customer.Id, + CustomerName = customer.Name, + PizzaId = pizza.Id, + PizzaName = pizza.Name, + DriverId = driver.Id, + DriverName = driver.Name, + }; + orderDTOs.Add(orderDTO); + } + } + + return TypedResults.Ok(orderDTOs); + } + + public static async Task GetOrder(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetOrder(id)); + } + + public static async Task GetOrderByCustomer(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetOrdersByCustomer(id)); + } + + public static async Task GetOrderByDriver(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetOrdersByDriver(id)); + } + + public static async Task UpdateDriver(IRepository repository,int id, OrderPut model) + { + var target = await repository.GetOrder(id); + if (target == null) return TypedResults.NotFound("Order was not found"); + + if (model.DriverId != null) target.DriverId = model.DriverId.Value; + + var result = await repository.UpdateOrder(target); + + return TypedResults.Created($"https://localhost:7138/orders/{result.Id}", result); + + + } + + public static async Task AddOrder(IRepository repository, OrderPost model) + { + Order order = new Order + { + CustomerId = model.CustomerId, + PizzaId = model.PizzaId, + }; + var result = await repository.AddOrder(order); + return TypedResults.Created($"https://localhost:7138/orders/{result.Id}", result); + } + + public static async Task GetToppings(IRepository repository) + { + return TypedResults.Ok(await repository.GetToppings()); + } + + public static async Task GetTopping(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetTopping(id)); + } + + public static async Task AddTopping(IRepository repository, ToppingPost model) + { + Topping topping = new Topping + { + Name = model.Name, + Price = model.Price, + }; + var result = await repository.AddTopping(topping); + return TypedResults.Created($"https://localhost:7138/toppings/{result.Id}", result); + + } + + public static async Task GetOrderToppings(IRepository repository) + { + return TypedResults.Ok(await repository.GetOrderToppings()); + } + + public static async Task GetOrderTopping(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetOrderTopping(id)); + } + + public static async Task GetOrderToppingByOrder(IRepository repository, int id) + { + return TypedResults.Ok(await repository.GetOrderToppingsByOrder(id)); + } + + public static async Task AddOrderToppings(IRepository repository, OrderToppingsPost model) + { + OrderToppings orderToppings = new OrderToppings + { + OrderId = model.OrderId, + ToppingId = model.ToppingId, + }; + var result = await repository.AddOrderToppings(orderToppings); + return TypedResults.Created($"https://localhost:7138/ordertoppings/{result.Id}", result); + } - } } diff --git a/exercise.pizzashopapi/Migrations/20250127121042_Pizza.Designer.cs b/exercise.pizzashopapi/Migrations/20250127121042_Pizza.Designer.cs new file mode 100644 index 0000000..734937d --- /dev/null +++ b/exercise.pizzashopapi/Migrations/20250127121042_Pizza.Designer.cs @@ -0,0 +1,144 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using exercise.pizzashopapi.Data; + +#nullable disable + +namespace exercise.pizzashopapi.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20250127121042_Pizza")] + partial class Pizza + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.DeliveryDriver", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DeliveryDrivers"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DriverId") + .HasColumnType("integer"); + + b.Property("PizzaId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.OrderToppings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderId") + .HasColumnType("integer"); + + b.Property("ToppingId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("OrderToppings"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Pizza", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Pizzas"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Topping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Toppings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/exercise.pizzashopapi/Migrations/20250127121042_Pizza.cs b/exercise.pizzashopapi/Migrations/20250127121042_Pizza.cs new file mode 100644 index 0000000..2ee46b5 --- /dev/null +++ b/exercise.pizzashopapi/Migrations/20250127121042_Pizza.cs @@ -0,0 +1,120 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace exercise.pizzashopapi.Migrations +{ + /// + public partial class Pizza : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Customers", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Customers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "DeliveryDrivers", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DeliveryDrivers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CustomerId = table.Column(type: "integer", nullable: false), + PizzaId = table.Column(type: "integer", nullable: false), + DriverId = table.Column(type: "integer", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OrderToppings", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + OrderId = table.Column(type: "integer", nullable: false), + ToppingId = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OrderToppings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Pizzas", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: false), + Price = table.Column(type: "numeric", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Pizzas", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Toppings", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: false), + Price = table.Column(type: "numeric", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Toppings", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Customers"); + + migrationBuilder.DropTable( + name: "DeliveryDrivers"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "OrderToppings"); + + migrationBuilder.DropTable( + name: "Pizzas"); + + migrationBuilder.DropTable( + name: "Toppings"); + } + } +} diff --git a/exercise.pizzashopapi/Migrations/DataContextModelSnapshot.cs b/exercise.pizzashopapi/Migrations/DataContextModelSnapshot.cs new file mode 100644 index 0000000..d3a6531 --- /dev/null +++ b/exercise.pizzashopapi/Migrations/DataContextModelSnapshot.cs @@ -0,0 +1,141 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using exercise.pizzashopapi.Data; + +#nullable disable + +namespace exercise.pizzashopapi.Migrations +{ + [DbContext(typeof(DataContext))] + partial class DataContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.DeliveryDriver", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DeliveryDrivers"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DriverId") + .HasColumnType("integer"); + + b.Property("PizzaId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.OrderToppings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderId") + .HasColumnType("integer"); + + b.Property("ToppingId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("OrderToppings"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Pizza", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Pizzas"); + }); + + modelBuilder.Entity("exercise.pizzashopapi.Models.Topping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.ToTable("Toppings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/exercise.pizzashopapi/Models/DeliveryDriver.cs b/exercise.pizzashopapi/Models/DeliveryDriver.cs new file mode 100644 index 0000000..527b821 --- /dev/null +++ b/exercise.pizzashopapi/Models/DeliveryDriver.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.Models +{ + public class DeliveryDriver + { + public int Id { get; set; } + public string Name { get; set; } + } +} diff --git a/exercise.pizzashopapi/Models/Order.cs b/exercise.pizzashopapi/Models/Order.cs index fbe6113..fd8417c 100644 --- a/exercise.pizzashopapi/Models/Order.cs +++ b/exercise.pizzashopapi/Models/Order.cs @@ -4,7 +4,10 @@ namespace exercise.pizzashopapi.Models { public class Order { - + public int Id { get; set; } + public int CustomerId { get; set; } + public int PizzaId { get; set; } + public int? DriverId { get; set; } } } diff --git a/exercise.pizzashopapi/Models/OrderDTO.cs b/exercise.pizzashopapi/Models/OrderDTO.cs new file mode 100644 index 0000000..4bddf27 --- /dev/null +++ b/exercise.pizzashopapi/Models/OrderDTO.cs @@ -0,0 +1,14 @@ +namespace exercise.pizzashopapi.Models +{ + public class OrderDTO + { + public int Id { get; set; } + public int CustomerId { get; set; } + public string CustomerName { get; set; } + public int PizzaId { get; set; } + public string PizzaName { get; set; } + public int? DriverId { get; set; } + public string? DriverName { get; set; } + + } +} diff --git a/exercise.pizzashopapi/Models/OrderPut.cs b/exercise.pizzashopapi/Models/OrderPut.cs new file mode 100644 index 0000000..e8bcb19 --- /dev/null +++ b/exercise.pizzashopapi/Models/OrderPut.cs @@ -0,0 +1,7 @@ +namespace exercise.pizzashopapi.Models +{ + public class OrderPut + { + public int? DriverId { get; set; } + } +} diff --git a/exercise.pizzashopapi/Models/OrderToppings.cs b/exercise.pizzashopapi/Models/OrderToppings.cs new file mode 100644 index 0000000..d977180 --- /dev/null +++ b/exercise.pizzashopapi/Models/OrderToppings.cs @@ -0,0 +1,9 @@ +namespace exercise.pizzashopapi.Models +{ + public class OrderToppings + { + public int Id { get; set; } + public int OrderId { get; set; } + public int ToppingId { get; set; } + } +} diff --git a/exercise.pizzashopapi/Models/Topping.cs b/exercise.pizzashopapi/Models/Topping.cs new file mode 100644 index 0000000..525b149 --- /dev/null +++ b/exercise.pizzashopapi/Models/Topping.cs @@ -0,0 +1,9 @@ +namespace exercise.pizzashopapi.Models +{ + public class Topping + { + public int Id { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } + } +} diff --git a/exercise.pizzashopapi/Repository/IRepository.cs b/exercise.pizzashopapi/Repository/IRepository.cs index b114ea8..3c60883 100644 --- a/exercise.pizzashopapi/Repository/IRepository.cs +++ b/exercise.pizzashopapi/Repository/IRepository.cs @@ -4,8 +4,31 @@ namespace exercise.pizzashopapi.Repository { public interface IRepository { - Task> GetOrdersByCustomer(int id); + Task> GetPizzas(); + Task GetPizza(int id); + Task AddPizza(Pizza pizza); + + Task> GetCustomers(); + Task GetCustomer(int id); + Task AddCustomer(Customer customer); + Task> GetOrders(); + Task GetOrder(int id); + Task AddOrder(Order order); + Task UpdateOrder(Order order); + Task> GetOrdersByCustomer(int id); + Task> GetOrdersByDriver(int id); + + Task> GetOrderToppingsByOrder(int id); + Task GetOrderTopping(int id); + Task> GetOrderToppings(); + Task AddOrderToppings(OrderToppings orderToppings); + + Task GetTopping(int id); + Task AddTopping(Topping topping); + Task> GetToppings(); + + Task GetDriver(int? id); } } diff --git a/exercise.pizzashopapi/Repository/Repository.cs b/exercise.pizzashopapi/Repository/Repository.cs index e109fce..17c9e06 100644 --- a/exercise.pizzashopapi/Repository/Repository.cs +++ b/exercise.pizzashopapi/Repository/Repository.cs @@ -1,14 +1,132 @@ using exercise.pizzashopapi.Data; using exercise.pizzashopapi.Models; +using Microsoft.EntityFrameworkCore; namespace exercise.pizzashopapi.Repository { public class Repository : IRepository { private DataContext _db; - public Task> GetOrdersByCustomer(int id) + + public Repository(DataContext db) + { + _db = db; + } + + public async Task AddCustomer(Customer customer) + { + _db.Customers.Add(customer); + await _db.SaveChangesAsync(); + return customer; + } + + public async Task AddOrder(Order order) + { + _db.Orders.Add(order); + await _db.SaveChangesAsync(); + return order; + } + + public async Task AddOrderToppings(OrderToppings orderToppings) + { + _db.OrderToppings.Add(orderToppings); + await _db.SaveChangesAsync(); + return orderToppings; + } + + public async Task AddPizza(Pizza pizza) + { + _db.Pizzas.Add(pizza); + await _db.SaveChangesAsync(); + return pizza; + } + + public async Task AddTopping(Topping topping) + { + _db.Toppings.Add(topping); + await _db.SaveChangesAsync(); + return topping; + } + + public async Task GetCustomer(int id) + { + return await _db.Customers.FindAsync(id); + } + + public async Task> GetCustomers() + { + return await _db.Customers.ToListAsync(); + } + + public async Task GetOrder(int id) + { + return await _db.Orders.FindAsync(id); + } + + public async Task GetDriver(int? id) + { + return await _db.DeliveryDrivers.FindAsync(id); + } + + public async Task> GetOrders() + { + return await _db.Orders.ToListAsync(); + } + + public async Task> GetOrdersByCustomer(int id) + { + return await _db.Orders.Where(o => o.CustomerId == id).ToListAsync(); + } + + public async Task> GetOrdersByDriver(int id) + { + return await _db.Orders.Where(o => o.DriverId == id).ToListAsync(); + } + + public async Task UpdateOrder(Order order) + { + var target = await _db.Orders.FindAsync(order.Id); + _db.Orders.Remove(target); + await _db.SaveChangesAsync(); + + await _db.Orders.AddAsync(order); + await _db.SaveChangesAsync(); + return order; + } + + public async Task GetOrderTopping(int id) + { + return await _db.OrderToppings.FindAsync(id); + } + + public async Task> GetOrderToppings() + { + return await _db.OrderToppings.ToListAsync(); + } + + public async Task> GetOrderToppingsByOrder(int id) + { + return await _db.OrderToppings.Where(o => o.OrderId==id).ToListAsync(); + } + + public async Task GetPizza(int id) + { + return await _db.Pizzas.FindAsync(id); + } + + public async Task> GetPizzas() + { + return await _db.Pizzas.ToListAsync(); + } + + public async Task GetTopping(int id) + { + return await _db.Toppings.FindAsync(id); + } + + public async Task> GetToppings() { - throw new NotImplementedException(); + return await _db.Toppings.ToListAsync(); } } } diff --git a/exercise.pizzashopapi/exercise.pizzashopapi.csproj b/exercise.pizzashopapi/exercise.pizzashopapi.csproj index 624203b..e2c5efb 100644 --- a/exercise.pizzashopapi/exercise.pizzashopapi.csproj +++ b/exercise.pizzashopapi/exercise.pizzashopapi.csproj @@ -11,18 +11,18 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + +