From 47a33ddd05a4c5e00f311059a4a115899c7ce710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduard=20Tom=C3=A0s?= Date: Mon, 29 Jan 2018 15:58:08 +0000 Subject: [PATCH] BFF Purchase - WIP --- .dockerignore | 3 +- docker-compose.override.yml | 2 ++ src/BFFs/PurchaseBff/Config/UrlsConfig.cs | 23 ++++++++++++ .../Controllers/BasketController.cs | 32 +++++++++++++++-- .../PurchaseBff/Controllers/HomeController.cs | 18 ++++++++++ .../Models/AddBasketItemRequest.cs | 20 +++++++++++ src/BFFs/PurchaseBff/Models/BasketData.cs | 31 ++++++++++++++++ src/BFFs/PurchaseBff/Models/CatalogItem.cs | 20 +++++++++++ src/BFFs/PurchaseBff/Program.cs | 4 +++ src/BFFs/PurchaseBff/PurchaseBff.csproj | 4 +++ .../PurchaseBff/Services/BasketService.cs | 34 ++++++++++++++++++ .../PurchaseBff/Services/CatalogService.cs | 35 +++++++++++++++++++ .../PurchaseBff/Services/IBasketService.cs | 13 +++++++ .../PurchaseBff/Services/ICatalogService.cs | 13 +++++++ src/BFFs/PurchaseBff/Startup.cs | 11 ++++++ .../PurchaseBff/appsettings.Development.json | 10 ------ .../PurchaseBff/appsettings.localhost.json | 6 ++++ .../Basket.API/Properties/launchSettings.json | 4 +-- .../Properties/launchSettings.json | 3 +- .../Properties/launchSettings.json | 2 +- 20 files changed, 271 insertions(+), 17 deletions(-) create mode 100644 src/BFFs/PurchaseBff/Config/UrlsConfig.cs create mode 100644 src/BFFs/PurchaseBff/Controllers/HomeController.cs create mode 100644 src/BFFs/PurchaseBff/Models/AddBasketItemRequest.cs create mode 100644 src/BFFs/PurchaseBff/Models/BasketData.cs create mode 100644 src/BFFs/PurchaseBff/Models/CatalogItem.cs create mode 100644 src/BFFs/PurchaseBff/Services/BasketService.cs create mode 100644 src/BFFs/PurchaseBff/Services/CatalogService.cs create mode 100644 src/BFFs/PurchaseBff/Services/IBasketService.cs create mode 100644 src/BFFs/PurchaseBff/Services/ICatalogService.cs delete mode 100644 src/BFFs/PurchaseBff/appsettings.Development.json create mode 100644 src/BFFs/PurchaseBff/appsettings.localhost.json diff --git a/.dockerignore b/.dockerignore index b5e7cb4f3..4c8d57b9a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -29,4 +29,5 @@ cli-linux **/node_modules/ **/bower_components/ **/wwwroot/lib/ -global.json \ No newline at end of file +global.json +**/appsettings.localhost.json \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 93c9cde4b..c16d3d109 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -231,6 +231,8 @@ services: purchasebff: environment: - ASPNETCORE_ENVIRONMENT=Development + - urls__basket=http://basket.api + - urls__catalog=http://catalog.api ports: - "5120:80" diff --git a/src/BFFs/PurchaseBff/Config/UrlsConfig.cs b/src/BFFs/PurchaseBff/Config/UrlsConfig.cs new file mode 100644 index 000000000..5c43bdfa7 --- /dev/null +++ b/src/BFFs/PurchaseBff/Config/UrlsConfig.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Config +{ + public class UrlsConfig + { + public class CatalogOperations + { + public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; + } + + public class BasketOperations + { + public static string GetItemById(string id) => $"/api/v1/basket/{id}"; + } + + public string Basket { get; set; } + public string Catalog { get; set; } + } +} diff --git a/src/BFFs/PurchaseBff/Controllers/BasketController.cs b/src/BFFs/PurchaseBff/Controllers/BasketController.cs index 7c875c9c4..74d5bec66 100644 --- a/src/BFFs/PurchaseBff/Controllers/BasketController.cs +++ b/src/BFFs/PurchaseBff/Controllers/BasketController.cs @@ -1,4 +1,6 @@ using Microsoft.AspNetCore.Mvc; +using PurchaseBff.Models; +using PurchaseBff.Services; using System; using System.Collections.Generic; using System.Linq; @@ -9,12 +11,38 @@ namespace PurchaseBff.Controllers [Route("api/v1/[controller]")] public class BasketController : Controller { - [HttpPost("items/{catalogItemId}")] - public async Task AddBasketItem(int catalogItemId) + private readonly ICatalogService _catalog; + private readonly IBasketService _basket; + public BasketController(ICatalogService catalogService, IBasketService basketService) { + _catalog = catalogService; + _basket = basketService; + } + + [HttpPost("items")] + public async Task AddBasketItem([FromBody] AddBasketItemRequest data) + { + if (data == null || data.Quantity == 0) + { + return BadRequest("Invalid payload"); + } + // Step 1: Get the item from catalog + var item = await _catalog.GetCatalogItem(data.CatalogItemId); // Step 2: Get current basket status + var currentBasket = await _basket.GetById(data.BasketId); // Step 3: Merge current status with new product + currentBasket.Items.Add(new BasketDataItem() + { + OldUnitPrice = item.Price, + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id.ToString(), + ProductName = item.Name, + Quantity = data.Quantity, + Id = item.Id.ToString() + }); + // Step 4: Update basket return Ok(); diff --git a/src/BFFs/PurchaseBff/Controllers/HomeController.cs b/src/BFFs/PurchaseBff/Controllers/HomeController.cs new file mode 100644 index 000000000..f54ec94ad --- /dev/null +++ b/src/BFFs/PurchaseBff/Controllers/HomeController.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Controllers +{ + [Route("")] + public class HomeController : Controller + { + [HttpGet()] + public IActionResult Index() + { + return new RedirectResult("~/swagger"); + } + } +} diff --git a/src/BFFs/PurchaseBff/Models/AddBasketItemRequest.cs b/src/BFFs/PurchaseBff/Models/AddBasketItemRequest.cs new file mode 100644 index 000000000..7c589a233 --- /dev/null +++ b/src/BFFs/PurchaseBff/Models/AddBasketItemRequest.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Models +{ + public class AddBasketItemRequest + { + public int CatalogItemId { get; set; } + public string BasketId { get; set; } + + public int Quantity { get; set; } + + public AddBasketItemRequest() + { + Quantity = 1; + } + } +} diff --git a/src/BFFs/PurchaseBff/Models/BasketData.cs b/src/BFFs/PurchaseBff/Models/BasketData.cs new file mode 100644 index 000000000..3f14660a7 --- /dev/null +++ b/src/BFFs/PurchaseBff/Models/BasketData.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Models +{ + public class BasketData + { + public string BuyerId { get; set; } + public List Items { get; set; } + + public BasketData(string buyerId) + { + BuyerId = buyerId; + Items = new List(); + } + } + + public class BasketDataItem + { + public string Id { get; set; } + public string ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal OldUnitPrice { get; set; } + public int Quantity { get; set; } + public string PictureUrl { get; set; } + + } +} diff --git a/src/BFFs/PurchaseBff/Models/CatalogItem.cs b/src/BFFs/PurchaseBff/Models/CatalogItem.cs new file mode 100644 index 000000000..13b0a65c0 --- /dev/null +++ b/src/BFFs/PurchaseBff/Models/CatalogItem.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Models +{ + public class CatalogItem + { + public int Id { get; set; } + + public string Name { get; set; } + + public decimal Price { get; set; } + + + public string PictureUri { get; set; } + + } +} diff --git a/src/BFFs/PurchaseBff/Program.cs b/src/BFFs/PurchaseBff/Program.cs index fe7210968..1c5b19865 100644 --- a/src/BFFs/PurchaseBff/Program.cs +++ b/src/BFFs/PurchaseBff/Program.cs @@ -20,6 +20,10 @@ namespace PurchaseBff public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() + .ConfigureAppConfiguration(cb => + { + cb.AddJsonFile("appsettings.localhost.json", optional: true); + }) .Build(); } } diff --git a/src/BFFs/PurchaseBff/PurchaseBff.csproj b/src/BFFs/PurchaseBff/PurchaseBff.csproj index b986e743f..dd7a5909e 100644 --- a/src/BFFs/PurchaseBff/PurchaseBff.csproj +++ b/src/BFFs/PurchaseBff/PurchaseBff.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/src/BFFs/PurchaseBff/Services/BasketService.cs b/src/BFFs/PurchaseBff/Services/BasketService.cs new file mode 100644 index 000000000..023f587aa --- /dev/null +++ b/src/BFFs/PurchaseBff/Services/BasketService.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using PurchaseBff.Config; +using PurchaseBff.Models; + +namespace PurchaseBff.Services +{ + public class BasketService : IBasketService + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + public BasketService(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } + + public async Task GetById(string id) + { + var data = await _apiClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id)); + var basket = JsonConvert.DeserializeObject(data); + return basket; + } + } +} diff --git a/src/BFFs/PurchaseBff/Services/CatalogService.cs b/src/BFFs/PurchaseBff/Services/CatalogService.cs new file mode 100644 index 000000000..071c162b4 --- /dev/null +++ b/src/BFFs/PurchaseBff/Services/CatalogService.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using PurchaseBff.Config; +using PurchaseBff.Models; + +namespace PurchaseBff.Services +{ + public class CatalogService : ICatalogService + { + + private readonly IHttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; + + public CatalogService(IHttpClient httpClient, ILogger logger, IOptionsSnapshot config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } + + public async Task GetCatalogItem(int id) + { + var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id)); + var item = JsonConvert.DeserializeObject(data); + return item; + } + } +} diff --git a/src/BFFs/PurchaseBff/Services/IBasketService.cs b/src/BFFs/PurchaseBff/Services/IBasketService.cs new file mode 100644 index 000000000..b4bafc461 --- /dev/null +++ b/src/BFFs/PurchaseBff/Services/IBasketService.cs @@ -0,0 +1,13 @@ +using PurchaseBff.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Services +{ + public interface IBasketService + { + Task GetById(string id); + } +} diff --git a/src/BFFs/PurchaseBff/Services/ICatalogService.cs b/src/BFFs/PurchaseBff/Services/ICatalogService.cs new file mode 100644 index 000000000..f7caaf6e3 --- /dev/null +++ b/src/BFFs/PurchaseBff/Services/ICatalogService.cs @@ -0,0 +1,13 @@ +using PurchaseBff.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PurchaseBff.Services +{ + public interface ICatalogService + { + Task GetCatalogItem(int id); + } +} diff --git a/src/BFFs/PurchaseBff/Startup.cs b/src/BFFs/PurchaseBff/Startup.cs index e82ee91fd..689e2925e 100644 --- a/src/BFFs/PurchaseBff/Startup.cs +++ b/src/BFFs/PurchaseBff/Startup.cs @@ -5,11 +5,14 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using PurchaseBff.Config; using PurchaseBff.Filters.Basket.API.Infrastructure.Filters; +using PurchaseBff.Services; using Swashbuckle.AspNetCore.Swagger; namespace PurchaseBff @@ -26,6 +29,14 @@ namespace PurchaseBff // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + + services.AddOptions(); + services.Configure(Configuration.GetSection("urls")); + services.AddMvc(); services.AddSwaggerGen(options => diff --git a/src/BFFs/PurchaseBff/appsettings.Development.json b/src/BFFs/PurchaseBff/appsettings.Development.json deleted file mode 100644 index fa8ce71a9..000000000 --- a/src/BFFs/PurchaseBff/appsettings.Development.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - } -} diff --git a/src/BFFs/PurchaseBff/appsettings.localhost.json b/src/BFFs/PurchaseBff/appsettings.localhost.json new file mode 100644 index 000000000..8267075d7 --- /dev/null +++ b/src/BFFs/PurchaseBff/appsettings.localhost.json @@ -0,0 +1,6 @@ +{ + "urls": { + "basket": "http://localhost:55105", + "catalog": "http://localhost:55101" + } +} diff --git a/src/Services/Basket/Basket.API/Properties/launchSettings.json b/src/Services/Basket/Basket.API/Properties/launchSettings.json index a397c4eb3..13aaf431f 100644 --- a/src/Services/Basket/Basket.API/Properties/launchSettings.json +++ b/src/Services/Basket/Basket.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:63335/", + "applicationUrl": "http://localhost:55105/", "sslPort": 0 } }, @@ -19,7 +19,7 @@ "Microsoft.eShopOnContainers.Services.Basket.API": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "http://localhost:5000/swagger", + "launchUrl": "http://localhost:55105/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json index 1bf8eb1f3..0357943bb 100644 --- a/src/Services/Catalog/Catalog.API/Properties/launchSettings.json +++ b/src/Services/Catalog/Catalog.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5101", + "applicationUrl": "http://localhost:55101", "sslPort": 0 } }, @@ -19,6 +19,7 @@ "Microsoft.eShopOnContainers.Services.Catalog.API": { "commandName": "Project", "launchBrowser": true, + "launchUrl": "http://localhost:55101/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Services/Marketing/Marketing.API/Properties/launchSettings.json b/src/Services/Marketing/Marketing.API/Properties/launchSettings.json index e222e065d..dea046099 100644 --- a/src/Services/Marketing/Marketing.API/Properties/launchSettings.json +++ b/src/Services/Marketing/Marketing.API/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:5110", + "applicationUrl": "http://localhost:63455/", "sslPort": 0 } },