From 34414276e0fe8d739f6b261153a5fd1d4f42426e Mon Sep 17 00:00:00 2001 From: BabychMaksym Date: Sat, 18 May 2024 16:24:09 +0300 Subject: [PATCH 1/2] add HomeWork 32 --- HomeWork32/eShop-Sample3/.dockerignore | 25 ++ HomeWork32/eShop-Sample3/.editorconfig | 4 + HomeWork32/eShop-Sample3/.gitignore | 288 ++++++++++++++++++ .../Catalog/Catalog.Host/.dockerignore | 25 ++ .../Catalog/Catalog.Host/Catalog.Host.csproj | 37 +++ .../Catalog.Host/Catalog.Host.csproj.user | 12 + .../Configurations/CatalogConfig.cs | 9 + .../Controllers/CatalogBffController.cs | 58 ++++ .../Controllers/CatalogBrandController.cs | 38 +++ .../Controllers/CatalogItemController.cs | 59 ++++ .../Controllers/CatalogTypeController.cs | 40 +++ .../Catalog.Host/Data/ApplicationDbContext.cs | 25 ++ .../Catalog.Host/Data/DbInitializer.cs | 74 +++++ .../Data/Entities/CatalogBrand.cs | 9 + .../Catalog.Host/Data/Entities/CatalogItem.cs | 26 ++ .../Catalog.Host/Data/Entities/CatalogType.cs | 9 + .../CatalogBrandEntityTypeConfiguration.cs | 24 ++ .../CatalogItemEntityTypeConfiguration.cs | 36 +++ .../CatalogTypeEntityTypeConfiguration.cs | 25 ++ .../Catalog.Host/Data/PaginatedItems.cs | 8 + .../Catalog/Catalog.Host/Dockerfile | 14 + .../Mapping/CatalogItemPictureResolver.cs | 22 ++ .../Catalog.Host/Mapping/MappingProfile.cs | 20 ++ ...0220108225624_InitialMigration.Designer.cs | 133 ++++++++ .../20220108225624_InitialMigration.cs | 109 +++++++ .../ApplicationDbContextModelSnapshot.cs | 131 ++++++++ .../Models/Dtos/CatalogBrandDto.cs | 9 + .../Models/Dtos/CatalogItemDto.cs | 21 ++ .../Models/Dtos/CatalogTypeDto.cs | 9 + .../Models/Requests/CreateProductRequest.cs | 20 ++ .../Models/Requests/PaginatedItemsRequest.cs | 8 + .../Models/Response/AddItemResponse.cs | 6 + .../Models/Response/PaginatedItemsResponse.cs | 12 + .../Catalog/Catalog.Host/Program.cs | 68 +++++ .../Repositories/CatalogBrandRepository.cs | 60 ++++ .../Repositories/CatalogItemRepository.cs | 116 +++++++ .../Repositories/CatalogTypeRepository.cs | 61 ++++ .../Interfaces/ICatalogBrandRepositorycs.cs | 12 + .../Interfaces/ICatalogItemRepository.cs | 15 + .../Interfaces/ICatalogTypeRepository.cs | 12 + .../Catalog.Host/Services/BaseDataService.cs | 61 ++++ .../Services/CatalogBrandService.cs | 52 ++++ .../Services/CatalogItemService.cs | 104 +++++++ .../Catalog.Host/Services/CatalogService.cs | 41 +++ .../Services/CatalogTypeService.cs | 53 ++++ .../Catalog.Host/Services/DbContextWrapper.cs | 24 ++ .../Interfaces/ICatalogBrandService.cs | 11 + .../Interfaces/ICatalogItemService.cs | 13 + .../Services/Interfaces/ICatalogService.cs | 9 + .../Interfaces/ICatalogTypeService.cs | 11 + .../Services/Interfaces/IDbContextWrapper.cs | 11 + .../Catalog/Catalog.Host/appsettings.json | 12 + .../Infrastructure/ComponentDefaults.cs | 6 + .../Infrastructure/Infrastructure.csproj | 30 ++ HomeWork32/eShop-Sample3/README.md | 23 ++ HomeWork32/eShop-Sample3/docker-compose.yml | 47 +++ HomeWork32/eShop-Sample3/eShop.sln | 51 ++++ .../eShop-Sample3/eShop.sln.DotSettings | 2 + HomeWork32/eShop-Sample3/settings.ruleset | 160 ++++++++++ 59 files changed, 2410 insertions(+) create mode 100644 HomeWork32/eShop-Sample3/.dockerignore create mode 100644 HomeWork32/eShop-Sample3/.editorconfig create mode 100644 HomeWork32/eShop-Sample3/.gitignore create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/.dockerignore create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj.user create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Configurations/CatalogConfig.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBrandController.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogItemController.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogTypeController.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/ApplicationDbContext.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/DbInitializer.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogBrand.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogItem.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogType.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/PaginatedItems.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Dockerfile create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/CatalogItemPictureResolver.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/MappingProfile.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.Designer.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogBrandDto.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogItemDto.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogTypeDto.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/CreateProductRequest.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/PaginatedItemsRequest.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/AddItemResponse.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/PaginatedItemsResponse.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogBrandRepository.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogItemRepository.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogTypeRepository.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogBrandRepositorycs.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogItemRepository.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogTypeRepository.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/BaseDataService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogBrandService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogItemService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogTypeService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/DbContextWrapper.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogBrandService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogItemService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogTypeService.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/IDbContextWrapper.cs create mode 100644 HomeWork32/eShop-Sample3/Catalog/Catalog.Host/appsettings.json create mode 100644 HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/ComponentDefaults.cs create mode 100644 HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/Infrastructure.csproj create mode 100644 HomeWork32/eShop-Sample3/README.md create mode 100644 HomeWork32/eShop-Sample3/docker-compose.yml create mode 100644 HomeWork32/eShop-Sample3/eShop.sln create mode 100644 HomeWork32/eShop-Sample3/eShop.sln.DotSettings create mode 100644 HomeWork32/eShop-Sample3/settings.ruleset diff --git a/HomeWork32/eShop-Sample3/.dockerignore b/HomeWork32/eShop-Sample3/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/HomeWork32/eShop-Sample3/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/.editorconfig b/HomeWork32/eShop-Sample3/.editorconfig new file mode 100644 index 0000000..6a5b933 --- /dev/null +++ b/HomeWork32/eShop-Sample3/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# Default severity for analyzer diagnostics with category 'Usage' +dotnet_analyzer_diagnostic.category-Usage.severity = none diff --git a/HomeWork32/eShop-Sample3/.gitignore b/HomeWork32/eShop-Sample3/.gitignore new file mode 100644 index 0000000..a5dbce6 --- /dev/null +++ b/HomeWork32/eShop-Sample3/.gitignore @@ -0,0 +1,288 @@ +syntax glob + +[Bb]inaries + +# Build tools related files +[Tt]ools + +### VisualStudio ### + +# User-specific files +.suo +.user +.userosscache +.sln.docstates + +# Build results +[Dd]ebug +[Dd]ebugPublic +[Rr]elease +[Rr]eleases +x64 +x86 +build +bld +[Bb]in +[Oo]bj +msbuild.log + +# Visual Studio 2015 +.vs + +# Visual Studio 2015 Pre-CTP6 +.sln.ide +.ide + +# MSTest test Results +[Tt]est[Rr]esult +[Bb]uild[Ll]og. + +#NUNIT +.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS +[Rr]eleasePS +dlldata.c + +_i.c +_p.c +_i.h +.ilk +.meta +.obj +.pch +.pdb +.pgc +.pgd +.rsp +.sbr +.tlb +.tli +.tlh +.tmp +.tmp_proj +.log +.html +.vspscc +.vssscc +.builds +.pidb +.svclog +.scc + +# Chutzpah Test files +_Chutzpah + +# Visual C++ cache files +ipch +.aps +.ncb +.opensdf +.sdf +.cachefile + +# Visual Studio profiler +.psess +.vsp +.vspx + +# TFS 2012 Local Workspace +$tf + +# Guidance Automation Toolkit +.gpState + +# ReSharper is a .NET coding add-in +_ReSharper +.[Rr]e[Ss]harper +.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity + +# DotCover is a Code Coverage Tool +.dotCover + +# NCrunch +_NCrunch_ +.crunch.local.xml + +# MightyMoose +.mm. +AutoTest.Net + +# Web workbench (sass) +.sass-cache + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProjectbuildhelp +DocProjectHelp.HxT +DocProjectHelp.HxC +DocProjectHelp.hhc +DocProjectHelp.hhk +DocProjectHelp.hhp +DocProjectHelpHtml2 +DocProjectHelphtml + +# Click-Once directory +publish + +# Publish Web Output +.[Pp]ublish.xml +.azurePubxml +.pubxml +.publishproj + +# NuGet Packages +.nupkg +packages +project.lock.json + +# Windows Azure Build Output +csx +.build.csdef + +# Windows Store app package directory +AppPackages + +# Others +sql +.Cache +ClientBin +[Ss]tyle[Cc]op. +~$ +.dbmdl +.dbproj.schemaview +.pfx +.publishsettings +node_modules +.metaproj +.metaproj.tmp +.atom-build.json +tags +TAGS + +# RIASilverlight projects +Generated_Code + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files +Backup +UpgradeLog.XML +UpgradeLog.htm + +# SQL Server files +.mdf +.ldf + +# Business Intelligence projects +.rdl.data +.bim.layout +.bim_.settings + +# Microsoft Fakes +FakesAssemblies + +### MonoDevelop ### + +.pidb +.userprefs + +### Windows ### + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN + +# Windows Installer files +.cab +.msi +.msm +.msp + +# Windows shortcuts +.lnk + +# Common binary extensions on Windows +.exe +.dll +.lib + +### Linux ### + +~ +## + +# KDE directory preferences +.directory + +### OSX ### + +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two r +Icon + +# Thumbnails +._ + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# We have some checked in prebuilt generated files +!srcpalprebuiltidl_i.c + +# Valid 'debug' folder, that contains CLR debuggin code +!srcdebug + +# Ignore folders created by the test build +TestWrappers_x64_debug +TestWrappers_x64_checked +TestWrappers_x64_release + +Vagrantfile +.vagrant + +# CMake files +CMakeFiles +cmake_install.cmake +CMakeCache.txt +Makefile + +# Cross compilation +crossrootfs + +#python import files +.pyc + +.idea +.generated-resources +.terraform +terraform.tfstate +terraform.tfstate.backup \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/.dockerignore b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj new file mode 100644 index 0000000..7ef7825 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj @@ -0,0 +1,37 @@ + + + + net8.0 + enable + enable + Linux + ../../settings.ruleset + true + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj.user b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj.user new file mode 100644 index 0000000..46b1b35 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Catalog.Host.csproj.user @@ -0,0 +1,12 @@ + + + + ProjectDebugger + + + Catalog.Host + + + ProjectDebugger + + \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Configurations/CatalogConfig.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Configurations/CatalogConfig.cs new file mode 100644 index 0000000..36df229 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Configurations/CatalogConfig.cs @@ -0,0 +1,9 @@ +#pragma warning disable CS8618 +namespace Catalog.Host.Configurations; + +public class CatalogConfig +{ + public string Host { get; set; } + public string ImgUrl { get; set; } + public string ConnectionString { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs new file mode 100644 index 0000000..6dba0b7 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs @@ -0,0 +1,58 @@ +using System.Net; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Models.Requests; +using Catalog.Host.Models.Response; +using Catalog.Host.Services.Interfaces; +using Infrastructure; +using Microsoft.AspNetCore.Mvc; + +namespace Catalog.Host.Controllers; + +[ApiController] +[Route(ComponentDefaults.DefaultRoute)] +public class CatalogBffController : ControllerBase +{ + private readonly ILogger _logger; + private readonly ICatalogService _catalogService; + private readonly ICatalogItemService _catalogItemService; + public CatalogBffController( + ILogger logger, + ICatalogService catalogService, + ICatalogItemService catalogItemService) + { + _logger = logger; + _catalogService = catalogService; + _catalogItemService = catalogItemService; + + } + + [HttpPost] + [ProducesResponseType(typeof(PaginatedItemsResponse), (int)HttpStatusCode.OK)] + public async Task Items(PaginatedItemsRequest request) + { + var result = await _catalogService.GetCatalogItemsAsync(request.PageSize, request.PageIndex); + return Ok(result); + } + + [HttpGet] + public async Task GetById(int id) + { + var result = await _catalogItemService.GetCatalogItemsByIdAsync(id); + return result; + } + + [HttpGet] + public async Task> GetByBrand(int idBrand) + { + var result = await _catalogItemService.GetCatalogItemByBrandAsync(idBrand); + return result; + } + + [HttpGet] + public async Task> GetByType(int idType) + { + var result = await _catalogItemService.GetCatalogItemByTypeAsync(idType); + return result; + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBrandController.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBrandController.cs new file mode 100644 index 0000000..99e978e --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBrandController.cs @@ -0,0 +1,38 @@ +using Catalog.Host.Models.Dtos; +using Catalog.Host.Services.Interfaces; +using Infrastructure; +using Microsoft.AspNetCore.Mvc; + +namespace Catalog.Host.Controllers; + +[ApiController] +[Route(ComponentDefaults.DefaultRoute)] +public class CatalogBrandController : ControllerBase +{ + private readonly ILogger _logger; + private readonly ICatalogBrandService _service; + + public CatalogBrandController(ILogger logger, ICatalogBrandService catalogBrandService) + { + _logger = logger; + _service = catalogBrandService; + } + + [HttpPost] + public async Task AddBrand(string type) + { + return await _service.AddAsync(type); + } + + [HttpPut] + public async Task UpdateBrand(CatalogBrandDto catalogBrand) + { + return await _service.UpdateAsync(catalogBrand); + } + + [HttpDelete] + public async Task DeleteBrand(int id) + { + return await _service.DeleteAsync(id); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogItemController.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogItemController.cs new file mode 100644 index 0000000..1806a55 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogItemController.cs @@ -0,0 +1,59 @@ +using System.Net; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Models.Requests; +using Catalog.Host.Models.Response; +using Catalog.Host.Services.Interfaces; +using Infrastructure; +using Microsoft.AspNetCore.Mvc; + +namespace Catalog.Host.Controllers; + +[ApiController] +[Route(ComponentDefaults.DefaultRoute)] +public class CatalogItemController : ControllerBase +{ + private readonly ILogger _logger; + private readonly ICatalogItemService _catalogItemService; + + public CatalogItemController( + ILogger logger, + ICatalogItemService catalogItemService) + { + _logger = logger; + _catalogItemService = catalogItemService; + } + + [HttpPost] + [ProducesResponseType(typeof(AddItemResponse), (int)HttpStatusCode.OK)] + public async Task Add(CreateProductRequest request) + { + var result = await _catalogItemService.Add( + request.Name, + request.Description, + request.Price, + request.AvailableStock, + request.CatalogBrandId, + request.CatalogTypeId, + request.PictureFileName); + + return Ok(new AddItemResponse() { Id = result }); + } + + [HttpGet] + public async Task GetById(int id) + { + return await _catalogItemService.GetCatalogItemsByIdAsync(id); + } + + [HttpDelete] + public async Task Delete(int id) + { + return await _catalogItemService.DeleteAsync(id); + } + + [HttpPut] + public async Task Update(CatalogItemDto catalogItemDto) + { + return await _catalogItemService.UpdateAsync(catalogItemDto); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogTypeController.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogTypeController.cs new file mode 100644 index 0000000..04ff75c --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogTypeController.cs @@ -0,0 +1,40 @@ +using Catalog.Host.Models.Dtos; +using Catalog.Host.Services.Interfaces; +using Infrastructure; +using Microsoft.AspNetCore.Mvc; + +namespace Catalog.Host.Controllers; + +[ApiController] +[Route(ComponentDefaults.DefaultRoute)] +public class CatalogTypeController : ControllerBase +{ + private readonly ILogger _logger; + private readonly ICatalogTypeService _serivice; + + public CatalogTypeController( + ILogger logger, + ICatalogTypeService service) + { + _logger = logger; + _serivice = service; + } + + [HttpPost] + public async Task AddType(string type) + { + return await _serivice.AddType(type); + } + + [HttpPut] + public async Task UpdateType(CatalogTypeDto catalogType) + { + return await _serivice.UpdateType(catalogType); + } + + [HttpDelete] + public async Task DeleteType(int id) + { + return await _serivice.DeleteType(id); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/ApplicationDbContext.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/ApplicationDbContext.cs new file mode 100644 index 0000000..0e3750f --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/ApplicationDbContext.cs @@ -0,0 +1,25 @@ +#pragma warning disable CS8618 +using Catalog.Host.Data.Entities; +using Catalog.Host.Data.EntityConfigurations; +using Microsoft.EntityFrameworkCore; + +namespace Catalog.Host.Data; + +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) + : base(options) + { + } + + public DbSet CatalogItems { get; set; } + public DbSet CatalogBrands { get; set; } + public DbSet CatalogTypes { get; set; } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.ApplyConfiguration(new CatalogBrandEntityTypeConfiguration()); + builder.ApplyConfiguration(new CatalogTypeEntityTypeConfiguration()); + builder.ApplyConfiguration(new CatalogItemEntityTypeConfiguration()); + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/DbInitializer.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/DbInitializer.cs new file mode 100644 index 0000000..5f63250 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/DbInitializer.cs @@ -0,0 +1,74 @@ +using Catalog.Host.Data.Entities; + +namespace Catalog.Host.Data; + +public static class DbInitializer +{ + public static async Task Initialize(ApplicationDbContext context) + { + await context.Database.EnsureCreatedAsync(); + + if (!context.CatalogBrands.Any()) + { + await context.CatalogBrands.AddRangeAsync(GetPreconfiguredCatalogBrands()); + + await context.SaveChangesAsync(); + } + + if (!context.CatalogTypes.Any()) + { + await context.CatalogTypes.AddRangeAsync(GetPreconfiguredCatalogTypes()); + + await context.SaveChangesAsync(); + } + + if (!context.CatalogItems.Any()) + { + await context.CatalogItems.AddRangeAsync(GetPreconfiguredItems()); + + await context.SaveChangesAsync(); + } + } + + private static IEnumerable GetPreconfiguredCatalogBrands() + { + return new List() + { + new CatalogBrand() { Brand = "Azure" }, + new CatalogBrand() { Brand = ".NET" }, + new CatalogBrand() { Brand = "Visual Studio" }, + new CatalogBrand() { Brand = "SQL Server" }, + new CatalogBrand() { Brand = "Other" } + }; + } + + private static IEnumerable GetPreconfiguredCatalogTypes() + { + return new List() + { + new CatalogType() { Type = "Mug" }, + new CatalogType() { Type = "T-Shirt" }, + new CatalogType() { Type = "Sheet" }, + new CatalogType() { Type = "USB Memory Stick" } + }; + } + + private static IEnumerable GetPreconfiguredItems() + { + return new List() + { + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureFileName = "1.png" }, + new CatalogItem { CatalogTypeId = 1, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price = 8.50M, PictureFileName = "2.png" }, + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureFileName = "3.png" }, + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureFileName = "4.png" }, + new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureFileName = "5.png" }, + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureFileName = "6.png" }, + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureFileName = "7.png" }, + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureFileName = "8.png" }, + new CatalogItem { CatalogTypeId = 1, CatalogBrandId = 5, AvailableStock = 100, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureFileName = "9.png" }, + new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureFileName = "10.png" }, + new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureFileName = "11.png" }, + new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" }, + }; + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogBrand.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogBrand.cs new file mode 100644 index 0000000..9f63c1f --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogBrand.cs @@ -0,0 +1,9 @@ +#pragma warning disable CS8618 +namespace Catalog.Host.Data.Entities; + +public class CatalogBrand +{ + public int Id { get; set; } + + public string Brand { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogItem.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogItem.cs new file mode 100644 index 0000000..959f5c0 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogItem.cs @@ -0,0 +1,26 @@ +#pragma warning disable CS8618 + +namespace Catalog.Host.Data.Entities; + +public class CatalogItem +{ + public int Id { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } + + public decimal Price { get; set; } + + public string PictureFileName { get; set; } + + public int CatalogTypeId { get; set; } + + public CatalogType CatalogType { get; set; } + + public int CatalogBrandId { get; set; } + + public CatalogBrand CatalogBrand { get; set; } + + public int AvailableStock { get; set; } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogType.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogType.cs new file mode 100644 index 0000000..5eaddda --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/Entities/CatalogType.cs @@ -0,0 +1,9 @@ +#pragma warning disable CS8618 +namespace Catalog.Host.Data.Entities; + +public class CatalogType +{ + public int Id { get; set; } + + public string Type { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs new file mode 100644 index 0000000..2ea4be3 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs @@ -0,0 +1,24 @@ +using Catalog.Host.Data.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Catalog.Host.Data.EntityConfigurations; + +public class CatalogBrandEntityTypeConfiguration + : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("CatalogBrand"); + + builder.HasKey(ci => ci.Id); + + builder.Property(ci => ci.Id) + .UseHiLo("catalog_brand_hilo") + .IsRequired(); + + builder.Property(cb => cb.Brand) + .IsRequired() + .HasMaxLength(100); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs new file mode 100644 index 0000000..0fc6e91 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs @@ -0,0 +1,36 @@ +using Catalog.Host.Data.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Catalog.Host.Data.EntityConfigurations; + +public class CatalogItemEntityTypeConfiguration + : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Catalog"); + + builder.Property(ci => ci.Id) + .UseHiLo("catalog_hilo") + .IsRequired(); + + builder.Property(ci => ci.Name) + .IsRequired(true) + .HasMaxLength(50); + + builder.Property(ci => ci.Price) + .IsRequired(true); + + builder.Property(ci => ci.PictureFileName) + .IsRequired(false); + + builder.HasOne(ci => ci.CatalogBrand) + .WithMany() + .HasForeignKey(ci => ci.CatalogBrandId); + + builder.HasOne(ci => ci.CatalogType) + .WithMany() + .HasForeignKey(ci => ci.CatalogTypeId); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs new file mode 100644 index 0000000..1b92189 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs @@ -0,0 +1,25 @@ +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Catalog.Host.Data.EntityConfigurations; + +public class CatalogTypeEntityTypeConfiguration + : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("CatalogType"); + + builder.HasKey(ci => ci.Id); + + builder.Property(ci => ci.Id) + .UseHiLo("catalog_type_hilo") + .IsRequired(); + + builder.Property(cb => cb.Type) + .IsRequired() + .HasMaxLength(100); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/PaginatedItems.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/PaginatedItems.cs new file mode 100644 index 0000000..130e77c --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Data/PaginatedItems.cs @@ -0,0 +1,8 @@ +namespace Catalog.Host.Data; + +public class PaginatedItems +{ + public long TotalCount { get; init; } + + public IEnumerable Data { get; init; } = null!; +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Dockerfile b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Dockerfile new file mode 100644 index 0000000..9e09d15 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Dockerfile @@ -0,0 +1,14 @@ +# https://hub.docker.com/_/microsoft-dotnet +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +COPY . /src +WORKDIR /src/Catalog/Catalog.Host +RUN dotnet publish -c Release -o /app + + +# final stage/image +FROM mcr.microsoft.com/dotnet/aspnet:8.0 +WORKDIR /app +COPY --from=build /app ./ +ENTRYPOINT ["dotnet", "Catalog.Host.dll"] + + diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/CatalogItemPictureResolver.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/CatalogItemPictureResolver.cs new file mode 100644 index 0000000..4acb8a9 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/CatalogItemPictureResolver.cs @@ -0,0 +1,22 @@ +using AutoMapper; +using Catalog.Host.Configurations; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Microsoft.Extensions.Options; + +namespace Catalog.Host.Mapping; + +public class CatalogItemPictureResolver : IMemberValueResolver +{ + private readonly CatalogConfig _config; + + public CatalogItemPictureResolver(IOptionsSnapshot config) + { + _config = config.Value; + } + + public object Resolve(CatalogItem source, CatalogItemDto destination, string sourceMember, object destMember, ResolutionContext context) + { + return $"{_config.Host}/{_config.ImgUrl}/{sourceMember}"; + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/MappingProfile.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/MappingProfile.cs new file mode 100644 index 0000000..0adc55b --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Mapping/MappingProfile.cs @@ -0,0 +1,20 @@ +using AutoMapper; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; + +namespace Catalog.Host.Mapping; + +public class MappingProfile : Profile +{ + public MappingProfile() + { + CreateMap() + .ForMember("PictureUrl", opt + => opt.MapFrom(c => c.PictureFileName)) + .ReverseMap(); + + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.Designer.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.Designer.cs new file mode 100644 index 0000000..bcd1d1f --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.Designer.cs @@ -0,0 +1,133 @@ +// +using Catalog.Host.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Catalog.Host.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20220108225624_InitialMigration")] + partial class InitialMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.HasSequence("catalog_brand_hilo") + .IncrementsBy(10); + + modelBuilder.HasSequence("catalog_hilo") + .IncrementsBy(10); + + modelBuilder.HasSequence("catalog_type_hilo") + .IncrementsBy(10); + + modelBuilder.Entity("Catalog.Host.Data.Entities.CatalogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseHiLo(b.Property("Id"), "catalog_hilo"); + + b.Property("AvailableStock") + .HasColumnType("integer"); + + b.Property("CatalogBrandId") + .HasColumnType("integer"); + + b.Property("CatalogTypeId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PictureFileName") + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CatalogBrandId"); + + b.HasIndex("CatalogTypeId"); + + b.ToTable("Catalog", (string)null); + }); + + modelBuilder.Entity("Catalog.Host.Data.Enums.CatalogBrand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseHiLo(b.Property("Id"), "catalog_brand_hilo"); + + b.Property("Brand") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("CatalogBrand", (string)null); + }); + + modelBuilder.Entity("Catalog.Host.Data.Enums.CatalogType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseHiLo(b.Property("Id"), "catalog_type_hilo"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("CatalogType", (string)null); + }); + + modelBuilder.Entity("Catalog.Host.Data.Entities.CatalogItem", b => + { + b.HasOne("Catalog.Host.Data.Enums.CatalogBrand", "CatalogBrand") + .WithMany() + .HasForeignKey("CatalogBrandId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Catalog.Host.Data.Enums.CatalogType", "CatalogType") + .WithMany() + .HasForeignKey("CatalogTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CatalogBrand"); + + b.Navigation("CatalogType"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.cs new file mode 100644 index 0000000..df8f05e --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/20220108225624_InitialMigration.cs @@ -0,0 +1,109 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Catalog.Host.Migrations +{ + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateSequence( + name: "catalog_brand_hilo", + incrementBy: 10); + + migrationBuilder.CreateSequence( + name: "catalog_hilo", + incrementBy: 10); + + migrationBuilder.CreateSequence( + name: "catalog_type_hilo", + incrementBy: 10); + + migrationBuilder.CreateTable( + name: "CatalogBrand", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false), + Brand = table.Column(type: "character varying(100)", maxLength: 100, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CatalogBrand", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CatalogType", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false), + Type = table.Column(type: "character varying(100)", maxLength: 100, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CatalogType", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Catalog", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false), + Name = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + Description = table.Column(type: "text", nullable: false), + Price = table.Column(type: "numeric", nullable: false), + PictureFileName = table.Column(type: "text", nullable: true), + CatalogTypeId = table.Column(type: "integer", nullable: false), + CatalogBrandId = table.Column(type: "integer", nullable: false), + AvailableStock = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Catalog", x => x.Id); + table.ForeignKey( + name: "FK_Catalog_CatalogBrand_CatalogBrandId", + column: x => x.CatalogBrandId, + principalTable: "CatalogBrand", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Catalog_CatalogType_CatalogTypeId", + column: x => x.CatalogTypeId, + principalTable: "CatalogType", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Catalog_CatalogBrandId", + table: "Catalog", + column: "CatalogBrandId"); + + migrationBuilder.CreateIndex( + name: "IX_Catalog_CatalogTypeId", + table: "Catalog", + column: "CatalogTypeId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Catalog"); + + migrationBuilder.DropTable( + name: "CatalogBrand"); + + migrationBuilder.DropTable( + name: "CatalogType"); + + migrationBuilder.DropSequence( + name: "catalog_brand_hilo"); + + migrationBuilder.DropSequence( + name: "catalog_hilo"); + + migrationBuilder.DropSequence( + name: "catalog_type_hilo"); + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/ApplicationDbContextModelSnapshot.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..7298040 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,131 @@ +// +using Catalog.Host.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Catalog.Host.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.HasSequence("catalog_brand_hilo") + .IncrementsBy(10); + + modelBuilder.HasSequence("catalog_hilo") + .IncrementsBy(10); + + modelBuilder.HasSequence("catalog_type_hilo") + .IncrementsBy(10); + + modelBuilder.Entity("Catalog.Host.Data.Entities.CatalogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseHiLo(b.Property("Id"), "catalog_hilo"); + + b.Property("AvailableStock") + .HasColumnType("integer"); + + b.Property("CatalogBrandId") + .HasColumnType("integer"); + + b.Property("CatalogTypeId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PictureFileName") + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CatalogBrandId"); + + b.HasIndex("CatalogTypeId"); + + b.ToTable("Catalog", (string)null); + }); + + modelBuilder.Entity("Catalog.Host.Data.Enums.CatalogBrand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseHiLo(b.Property("Id"), "catalog_brand_hilo"); + + b.Property("Brand") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("CatalogBrand", (string)null); + }); + + modelBuilder.Entity("Catalog.Host.Data.Enums.CatalogType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseHiLo(b.Property("Id"), "catalog_type_hilo"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("CatalogType", (string)null); + }); + + modelBuilder.Entity("Catalog.Host.Data.Entities.CatalogItem", b => + { + b.HasOne("Catalog.Host.Data.Enums.CatalogBrand", "CatalogBrand") + .WithMany() + .HasForeignKey("CatalogBrandId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Catalog.Host.Data.Enums.CatalogType", "CatalogType") + .WithMany() + .HasForeignKey("CatalogTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CatalogBrand"); + + b.Navigation("CatalogType"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogBrandDto.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogBrandDto.cs new file mode 100644 index 0000000..8e4ad8f --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogBrandDto.cs @@ -0,0 +1,9 @@ +#pragma warning disable CS8618 +namespace Catalog.Host.Models.Dtos; + +public class CatalogBrandDto +{ + public int Id { get; set; } + + public string Brand { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogItemDto.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogItemDto.cs new file mode 100644 index 0000000..b8f4d3d --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogItemDto.cs @@ -0,0 +1,21 @@ +#pragma warning disable CS8618 +namespace Catalog.Host.Models.Dtos; + +public class CatalogItemDto +{ + public int Id { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } + + public decimal Price { get; set; } + + public string PictureUrl { get; set; } + + public CatalogTypeDto CatalogType { get; set; } + + public CatalogBrandDto CatalogBrand { get; set; } + + public int AvailableStock { get; set; } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogTypeDto.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogTypeDto.cs new file mode 100644 index 0000000..4e1d7b7 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Dtos/CatalogTypeDto.cs @@ -0,0 +1,9 @@ +#pragma warning disable CS8618 +namespace Catalog.Host.Models.Dtos; + +public class CatalogTypeDto +{ + public int Id { get; set; } + + public string Type { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/CreateProductRequest.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/CreateProductRequest.cs new file mode 100644 index 0000000..20de15b --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/CreateProductRequest.cs @@ -0,0 +1,20 @@ +using Catalog.Host.Data.Entities; + +namespace Catalog.Host.Models.Requests; + +public class CreateProductRequest +{ + public string Name { get; set; } = null!; + + public string Description { get; set; } = null!; + + public decimal Price { get; set; } + + public string PictureFileName { get; set; } = null!; + + public int CatalogTypeId { get; set; } + + public int CatalogBrandId { get; set; } + + public int AvailableStock { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/PaginatedItemsRequest.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/PaginatedItemsRequest.cs new file mode 100644 index 0000000..f296711 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Requests/PaginatedItemsRequest.cs @@ -0,0 +1,8 @@ +namespace Catalog.Host.Models.Requests; + +public class PaginatedItemsRequest +{ + public int PageIndex { get; set; } + + public int PageSize { get; set; } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/AddItemResponse.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/AddItemResponse.cs new file mode 100644 index 0000000..9e91f5a --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/AddItemResponse.cs @@ -0,0 +1,6 @@ +namespace Catalog.Host.Models.Response; + +public class AddItemResponse +{ + public T Id { get; set; } = default(T) !; +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/PaginatedItemsResponse.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/PaginatedItemsResponse.cs new file mode 100644 index 0000000..97683a2 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Models/Response/PaginatedItemsResponse.cs @@ -0,0 +1,12 @@ +namespace Catalog.Host.Models.Response; + +public class PaginatedItemsResponse +{ + public int PageIndex { get; init; } + + public int PageSize { get; init; } + + public long Count { get; init; } + + public IEnumerable Data { get; init; } = null!; +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs new file mode 100644 index 0000000..a6cf416 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs @@ -0,0 +1,68 @@ +using Catalog.Host.Configurations; +using Catalog.Host.Data; +using Catalog.Host.Repositories; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services; +using Catalog.Host.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +var configuration = GetConfiguration(); + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddControllers(); +builder.Services.Configure(configuration); +builder.Services.AddSwaggerGen(); +builder.Services.AddAutoMapper(typeof(Program)); + +builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); + +builder.Services.AddDbContextFactory(opts => opts.UseNpgsql(configuration["ConnectionString"]!)); +builder.Services.AddScoped, DbContextWrapper>(); + +var app = builder.Build(); + +app.UseSwagger(); +app.UseSwaggerUI(); +app.UseRouting(); + +app.UseEndpoints(endpoints => +{ + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); +}); + +CreateDbIfNotExists(app); +app.Run(); + +IConfiguration GetConfiguration() +{ + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddEnvironmentVariables(); + + return builder.Build(); +} + +void CreateDbIfNotExists(IHost host) +{ + using (var scope = host.Services.CreateScope()) + { + var services = scope.ServiceProvider; + try + { + var context = services.GetRequiredService(); + + DbInitializer.Initialize(context).Wait(); + } + catch (Exception ex) + { + var logger = services.GetRequiredService>(); + logger.LogError(ex, "An error occurred creating the DB."); + } + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogBrandRepository.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogBrandRepository.cs new file mode 100644 index 0000000..7af02ea --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogBrandRepository.cs @@ -0,0 +1,60 @@ +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services; +using Catalog.Host.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace Catalog.Host.Repositories +{ + public class CatalogBrandRepository : ICatalogBrandRepository + { + private readonly ApplicationDbContext _dbContext; + private readonly ILogger _logger; + + public CatalogBrandRepository(IDbContextWrapper contextWrapper, ILogger logger) + { + _dbContext = contextWrapper.DbContext; + _logger = logger; + } + + public async Task GetById(int id) + { + return await _dbContext.CatalogBrands + .FirstOrDefaultAsync(f => f.Id == id); + } + + public async Task AddAsync(string brand) + { + var entity = await _dbContext.CatalogBrands + .AddAsync(new CatalogBrand() + { + Brand = brand + }); + + await _dbContext.SaveChangesAsync(); + + return entity.Entity.Id; + } + + public async Task DeleteAsync(int id) + { + var entity = await GetById(id); + var message = _dbContext.CatalogBrands.Remove(entity!); + + await _dbContext.SaveChangesAsync(); + + return message.State.ToString(); + } + + public async Task UpdateAsync(CatalogBrand catalogBrand) + { + var entity = await GetById(catalogBrand.Id); + entity!.Brand = catalogBrand.Brand; + + await _dbContext.SaveChangesAsync(); + + return entity; + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogItemRepository.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogItemRepository.cs new file mode 100644 index 0000000..cca3d6e --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogItemRepository.cs @@ -0,0 +1,116 @@ +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace Catalog.Host.Repositories; + +public class CatalogItemRepository : ICatalogItemRepository +{ + private readonly ApplicationDbContext _dbContext; + private readonly ILogger _logger; + + public CatalogItemRepository( + IDbContextWrapper dbContextWrapper, + ILogger logger) + { + _dbContext = dbContextWrapper.DbContext; + _logger = logger; + } + + public async Task> GetByPageAsync(int pageIndex, int pageSize) + { + var totalItems = await _dbContext.CatalogItems + .LongCountAsync(); + + var itemsOnPage = await _dbContext.CatalogItems + .Include(i => i.CatalogBrand) + .Include(i => i.CatalogType) + .OrderBy(c => c.Name) + .Skip(pageSize * pageIndex) + .Take(pageSize) + .ToListAsync(); + + return new PaginatedItems() { TotalCount = totalItems, Data = itemsOnPage }; + } + + public async Task Add( + string name, + string description, + decimal price, + int availableStock, + int catalogBrandId, + int catalogTypeId, + string pictureFileName) + { + var item = await _dbContext.AddAsync(new CatalogItem + { + CatalogBrandId = catalogBrandId, + CatalogTypeId = catalogTypeId, + Description = description, + Name = name, + PictureFileName = pictureFileName, + Price = price + }); + + await _dbContext.SaveChangesAsync(); + + return item.Entity.Id; + } + + public async Task GetCatalogItemsByIdAsync(int idItem) + { + return await _dbContext.CatalogItems + .Include(i => i.CatalogType) + .Include(i=>i.CatalogBrand) + .FirstOrDefaultAsync(item => item.Id == idItem); + } + + public async Task> GetCatalogItemsByBrandAsync(int idBrand) + { + return await _dbContext.CatalogItems + .Include(i=>i.CatalogType) + .Include(i => i.CatalogBrand) + .Select(item => item) + .Where(item => item.CatalogBrand.Id == idBrand) + .ToListAsync(); + } + + public async Task> GetCatalogItemsByTypeAsync(int idType) + { + return await _dbContext.CatalogItems + .Include(i => i.CatalogBrand) + .Include(i => i.CatalogType) + .Select(item => item) + .Where(item => item.CatalogType.Id == idType) + .ToListAsync(); + } + + public async Task DeleteAsync(int id) + { + var item = await GetCatalogItemsByIdAsync(id); + var message = _dbContext.CatalogItems.Remove(item!); + await _dbContext.SaveChangesAsync(); + return message.State.ToString(); + } + + public async Task Update(CatalogItem catalogItem) + { + var item = await GetCatalogItemsByIdAsync(catalogItem.Id); + + item!.Price = catalogItem.Price; + item.Description = catalogItem.Description; + item.PictureFileName = catalogItem.PictureFileName; + item.Name = catalogItem.Name; + item.AvailableStock = catalogItem.AvailableStock; + item.CatalogBrandId = catalogItem.CatalogBrandId; + item.CatalogType = catalogItem.CatalogType; + item.CatalogTypeId = catalogItem.CatalogTypeId; + item.CatalogBrand = catalogItem.CatalogBrand; + + await _dbContext.SaveChangesAsync(); + + return item; + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogTypeRepository.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogTypeRepository.cs new file mode 100644 index 0000000..ff575dd --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/CatalogTypeRepository.cs @@ -0,0 +1,61 @@ +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace Catalog.Host.Repositories +{ + public class CatalogTypeRepository : ICatalogTypeRepository + { + private readonly ApplicationDbContext _dbContext; + private readonly ILogger _logger; + + public CatalogTypeRepository( + IDbContextWrapper dbContextWrapper, + ILogger logger) + { + _dbContext = dbContextWrapper.DbContext; + _logger = logger; + } + + public async Task GetById(int id) + { + return await _dbContext.CatalogTypes + .FirstOrDefaultAsync(f => f.Id == id); + } + + public async Task AddTypeAsync(string type) + { + var entity = await _dbContext.CatalogTypes.AddAsync(new CatalogType() + { + Type = type + }); + + await _dbContext.SaveChangesAsync(); + + return entity.Entity.Id; + } + + public async Task DeleteType(int id) + { + var entity = await GetById(id); + var message = _dbContext.CatalogTypes.Remove(entity!); + + await _dbContext.SaveChangesAsync(); + + return message.State.ToString(); + } + + public async Task Update(CatalogType catalogType) + { + var entity = await GetById(catalogType.Id); + entity!.Type = catalogType.Type; + + await _dbContext.SaveChangesAsync(); + + return entity; + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogBrandRepositorycs.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogBrandRepositorycs.cs new file mode 100644 index 0000000..1d2ed77 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogBrandRepositorycs.cs @@ -0,0 +1,12 @@ +using Catalog.Host.Data.Entities; + +namespace Catalog.Host.Repositories.Interfaces +{ + public interface ICatalogBrandRepository + { + Task GetById(int id); + Task AddAsync(string brand); + Task DeleteAsync(int id); + Task UpdateAsync(CatalogBrand catalogBrand); + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogItemRepository.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogItemRepository.cs new file mode 100644 index 0000000..fff7551 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogItemRepository.cs @@ -0,0 +1,15 @@ +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; + +namespace Catalog.Host.Repositories.Interfaces; + +public interface ICatalogItemRepository +{ + Task> GetByPageAsync(int pageIndex, int pageSize); + Task Add(string name, string description, decimal price, int availableStock, int catalogBrandId, int catalogTypeId, string pictureFileName); + Task GetCatalogItemsByIdAsync(int id); + Task> GetCatalogItemsByBrandAsync(int idBrand); + Task> GetCatalogItemsByTypeAsync(int idType); + Task DeleteAsync(int id); + Task Update(CatalogItem catalogItem); +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogTypeRepository.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogTypeRepository.cs new file mode 100644 index 0000000..c4631ec --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Repositories/Interfaces/ICatalogTypeRepository.cs @@ -0,0 +1,12 @@ +using Catalog.Host.Data.Entities; + +namespace Catalog.Host.Repositories.Interfaces +{ + public interface ICatalogTypeRepository + { + Task GetById(int id); + Task AddTypeAsync(string type); + Task DeleteType(int id); + Task Update(CatalogType catalogType); + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/BaseDataService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/BaseDataService.cs new file mode 100644 index 0000000..fd95c5c --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/BaseDataService.cs @@ -0,0 +1,61 @@ +using Catalog.Host.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace Catalog.Host.Services; + +public abstract class BaseDataService + where T : DbContext +{ + private readonly IDbContextWrapper _dbContextWrapper; + private readonly ILogger> _logger; + + protected BaseDataService( + IDbContextWrapper dbContextWrapper, + ILogger> logger) + { + _dbContextWrapper = dbContextWrapper; + _logger = logger; + } + + protected Task ExecuteSafeAsync(Func action, CancellationToken cancellationToken = default) => ExecuteSafeAsync(token => action(), cancellationToken); + + protected Task ExecuteSafeAsync(Func> action, CancellationToken cancellationToken = default) => ExecuteSafeAsync(token => action(), cancellationToken); + + private async Task ExecuteSafeAsync(Func action, CancellationToken cancellationToken = default) + { + await using var transaction = await _dbContextWrapper.BeginTransactionAsync(cancellationToken); + + try + { + await action(cancellationToken); + + await transaction.CommitAsync(cancellationToken); + } + catch (Exception ex) + { + await transaction.RollbackAsync(cancellationToken); + _logger.LogError(ex, $"transaction is rollbacked"); + } + } + + private async Task ExecuteSafeAsync(Func> action, CancellationToken cancellationToken = default) + { + await using var transaction = await _dbContextWrapper.BeginTransactionAsync(cancellationToken); + + try + { + var result = await action(cancellationToken); + + await transaction.CommitAsync(cancellationToken); + + return result; + } + catch (Exception ex) + { + await transaction.RollbackAsync(cancellationToken); + _logger.LogError(ex, $"transaction is rollbacked"); + } + + return default(TResult) !; + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogBrandService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogBrandService.cs new file mode 100644 index 0000000..13226ad --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogBrandService.cs @@ -0,0 +1,52 @@ +using AutoMapper; +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services.Interfaces; + +namespace Catalog.Host.Services +{ + public class CatalogBrandService : BaseDataService, ICatalogBrandService + { + private readonly ICatalogBrandRepository _repository; + private readonly IMapper _mapper; + public CatalogBrandService( + IDbContextWrapper dbContextWrapper, + ILogger logger, + ICatalogBrandRepository catalogBrandRepository, + IMapper mapper) + : base(dbContextWrapper, logger) + { + _repository = catalogBrandRepository; + _mapper = mapper; + } + + public async Task AddAsync(string type) + { + return await ExecuteSafeAsync(async () => + { + return await _repository.AddAsync(type); + }); + } + + public async Task DeleteAsync(int id) + { + return await ExecuteSafeAsync(async () => + { + return await _repository.DeleteAsync(id); + }); + } + + public async Task UpdateAsync(CatalogBrandDto typeDto) + { + return await ExecuteSafeAsync(async () => + { + var entity = _mapper.Map(typeDto); + var upentity = await _repository.UpdateAsync(entity); + var dto = _mapper.Map(upentity); + return dto; + }); + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogItemService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogItemService.cs new file mode 100644 index 0000000..10202c0 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogItemService.cs @@ -0,0 +1,104 @@ +using AutoMapper; +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services.Interfaces; + +namespace Catalog.Host.Services; + +public class CatalogItemService : BaseDataService, ICatalogItemService +{ + private readonly ICatalogItemRepository _catalogItemRepository; + private readonly IMapper _mapper; + + public CatalogItemService( + IDbContextWrapper dbContextWrapper, + ILogger> logger, + ICatalogItemRepository catalogItemRepository, + IMapper mapper) + : base(dbContextWrapper, logger) + { + _catalogItemRepository = catalogItemRepository; + _mapper = mapper; + } + + public Task Add( + string name, + string description, + decimal price, + int availableStock, + int catalogBrandId, + int catalogTypeId, + string pictureFileName) + { + return ExecuteSafeAsync(() => _catalogItemRepository.Add( + name, + description, + price, + availableStock, + catalogBrandId, + catalogTypeId, + pictureFileName)); + } + + public async Task GetCatalogItemsByIdAsync(int id) + { + return await ExecuteSafeAsync(async () => + { + var item = await _catalogItemRepository.GetCatalogItemsByIdAsync(id); + + return _mapper.Map(item); + }); + + } + + public async Task> GetCatalogItemByBrandAsync(int idBrand) + { + return await ExecuteSafeAsync(async () => + { + var itemColections = new List(); + + var items = await _catalogItemRepository.GetCatalogItemsByBrandAsync(idBrand); + + itemColections.AddRange( items.Select(i => _mapper.Map(i))); + + return itemColections; + }); + } + + public async Task> GetCatalogItemByTypeAsync(int idType) + { + return await ExecuteSafeAsync(async () => + { + var itemColections = new List(); + + var items = await _catalogItemRepository.GetCatalogItemsByTypeAsync(idType); + + itemColections.AddRange(items.Select(i => _mapper.Map(i))); + + return itemColections; + }); + } + + public async Task DeleteAsync(int id) + { + return await ExecuteSafeAsync(async () => + { + return await _catalogItemRepository.DeleteAsync(id); + }); + } + + public async Task UpdateAsync(CatalogItemDto catalogItemDto) + { + return await ExecuteSafeAsync(async () => + { + var item = _mapper.Map(catalogItemDto); + item = await _catalogItemRepository.Update(item); + var dto = _mapper.Map(item); + + return dto; + }); + } + +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogService.cs new file mode 100644 index 0000000..d284b94 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogService.cs @@ -0,0 +1,41 @@ +using AutoMapper; +using Catalog.Host.Configurations; +using Catalog.Host.Data; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Models.Response; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services.Interfaces; + +namespace Catalog.Host.Services; + +public class CatalogService : BaseDataService, ICatalogService +{ + private readonly ICatalogItemRepository _catalogItemRepository; + private readonly IMapper _mapper; + + public CatalogService( + IDbContextWrapper dbContextWrapper, + ILogger> logger, + ICatalogItemRepository catalogItemRepository, + IMapper mapper) + : base(dbContextWrapper, logger) + { + _catalogItemRepository = catalogItemRepository; + _mapper = mapper; + } + + public async Task> GetCatalogItemsAsync(int pageSize, int pageIndex) + { + return await ExecuteSafeAsync(async () => + { + var result = await _catalogItemRepository.GetByPageAsync(pageIndex, pageSize); + return new PaginatedItemsResponse() + { + Count = result.TotalCount, + Data = result.Data.Select(s => _mapper.Map(s)).ToList(), + PageIndex = pageIndex, + PageSize = pageSize + }; + }); + } +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogTypeService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogTypeService.cs new file mode 100644 index 0000000..02aa4f7 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/CatalogTypeService.cs @@ -0,0 +1,53 @@ +using AutoMapper; +using Catalog.Host.Data; +using Catalog.Host.Data.Entities; +using Catalog.Host.Models.Dtos; +using Catalog.Host.Repositories.Interfaces; +using Catalog.Host.Services.Interfaces; + +namespace Catalog.Host.Services +{ + public class CatalogTypeService : BaseDataService, ICatalogTypeService + { + private readonly ICatalogTypeRepository _repository; + private readonly IMapper _mapping; + + public CatalogTypeService( + ICatalogTypeRepository repository, + IMapper mapper, + IDbContextWrapper dbContextWrapper, + ILogger logger) + : base(dbContextWrapper, logger) + { + _repository = repository; + _mapping = mapper; + } + + public async Task AddType(string type) + { + return await ExecuteSafeAsync(async () => + { + return await _repository.AddTypeAsync(type); + }); + } + + public async Task DeleteType(int id) + { + return await ExecuteSafeAsync(async() => + { + return await _repository.DeleteType(id); + }); + } + + public async Task UpdateType(CatalogTypeDto typeDto) + { + return await ExecuteSafeAsync(async () => + { + var entity = _mapping.Map(typeDto); + var upentity = await _repository.Update(entity); + var dto = _mapping.Map(upentity); + return dto; + }); + } + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/DbContextWrapper.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/DbContextWrapper.cs new file mode 100644 index 0000000..90bb3e0 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/DbContextWrapper.cs @@ -0,0 +1,24 @@ +using Catalog.Host.Services.Interfaces; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Catalog.Host.Services; + +public class DbContextWrapper : IDbContextWrapper + where T : DbContext +{ + private readonly T _dbContext; + + public DbContextWrapper( + IDbContextFactory dbContextFactory) + { + _dbContext = dbContextFactory.CreateDbContext(); + } + + public T DbContext => _dbContext; + + public Task BeginTransactionAsync(CancellationToken cancellationToken) + { + return _dbContext.Database.BeginTransactionAsync(cancellationToken); + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogBrandService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogBrandService.cs new file mode 100644 index 0000000..3336b93 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogBrandService.cs @@ -0,0 +1,11 @@ +using Catalog.Host.Models.Dtos; + +namespace Catalog.Host.Services.Interfaces +{ + public interface ICatalogBrandService + { + Task AddAsync(string type); + Task DeleteAsync(int id); + Task UpdateAsync(CatalogBrandDto typeDto); + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogItemService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogItemService.cs new file mode 100644 index 0000000..9b91305 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogItemService.cs @@ -0,0 +1,13 @@ +using Catalog.Host.Models.Dtos; + +namespace Catalog.Host.Services.Interfaces; + +public interface ICatalogItemService +{ + Task Add(string name, string description, decimal price, int availableStock, int catalogBrandId, int catalogTypeId, string pictureFileName); + Task GetCatalogItemsByIdAsync(int id); + Task> GetCatalogItemByBrandAsync(int idBrand); + Task> GetCatalogItemByTypeAsync(int idType); + Task UpdateAsync(CatalogItemDto catalogItemDto); + Task DeleteAsync(int id); +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogService.cs new file mode 100644 index 0000000..2189d93 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogService.cs @@ -0,0 +1,9 @@ +using Catalog.Host.Models.Dtos; +using Catalog.Host.Models.Response; + +namespace Catalog.Host.Services.Interfaces; + +public interface ICatalogService +{ + Task> GetCatalogItemsAsync(int pageSize, int pageIndex); +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogTypeService.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogTypeService.cs new file mode 100644 index 0000000..5074132 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/ICatalogTypeService.cs @@ -0,0 +1,11 @@ +using Catalog.Host.Models.Dtos; + +namespace Catalog.Host.Services.Interfaces +{ + public interface ICatalogTypeService + { + Task UpdateType(CatalogTypeDto typeDto); + Task DeleteType(int id); + Task AddType(string type); + } +} diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/IDbContextWrapper.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/IDbContextWrapper.cs new file mode 100644 index 0000000..8044df5 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Services/Interfaces/IDbContextWrapper.cs @@ -0,0 +1,11 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Catalog.Host.Services.Interfaces; + +public interface IDbContextWrapper + where T : DbContext +{ + T DbContext { get; } + Task BeginTransactionAsync(CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/appsettings.json b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/appsettings.json new file mode 100644 index 0000000..4112043 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/appsettings.json @@ -0,0 +1,12 @@ +{ + "Host": "www.alevelwebsite.com", + "ImgUrl": "assets/img", + "ConnectionString": "server=www.alevelwebsite.com;port=5433;database=catalog;uid=postgres;password=postgres;", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/ComponentDefaults.cs b/HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/ComponentDefaults.cs new file mode 100644 index 0000000..677b560 --- /dev/null +++ b/HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/ComponentDefaults.cs @@ -0,0 +1,6 @@ +namespace Infrastructure; + +public static class ComponentDefaults +{ + public const string DefaultRoute = "api/v1/[controller]/[action]"; +} diff --git a/HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/Infrastructure.csproj b/HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/Infrastructure.csproj new file mode 100644 index 0000000..8db8f0b --- /dev/null +++ b/HomeWork32/eShop-Sample3/Infrastructure/Infrastructure/Infrastructure.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + Infrastructure + Infrastructure + + + + + ..\..\..\..\..\..\usr\local\share\dotnet\shared\Microsoft.AspNetCore.App\6.0.1\Microsoft.Extensions.Configuration.Abstractions.dll + + + ..\..\..\..\..\..\usr\local\share\dotnet\shared\Microsoft.AspNetCore.App\6.0.1\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/HomeWork32/eShop-Sample3/README.md b/HomeWork32/eShop-Sample3/README.md new file mode 100644 index 0000000..a16d68b --- /dev/null +++ b/HomeWork32/eShop-Sample3/README.md @@ -0,0 +1,23 @@ +#!!!!!SETUP STEPS!!!!! +Update host file on your PC + like this instruction https://www.nublue.co.uk/guides/edit-hosts-file/#:~:text=In%20Windows%2010%20the%20hosts,%5CDrivers%5Cetc%5Chosts. + +Need to path these lines + + 127.0.0.1 www.alevelwebsite.com + 0.0.0.0 www.alevelwebsite.com + 192.168.0.4 www.alevelwebsite.com + +#docker +docker-compose build --no-cache + +docker-compose up + +#Add-Migration +dotnet ef --startup-project Catalog/Catalog.Host migrations add InitialMigration --project Catalog/Catalog.Host + +#Update-Migration +dotnet ef --startup-project Catalog/Catalog.Host database update InitialMigration --project Catalog/Catalog.Host + +#Remove-Migration +dotnet ef --startup-project Catalog/Catalog.Host migrations remove --project Catalog/Catalog.Host -f \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/docker-compose.yml b/HomeWork32/eShop-Sample3/docker-compose.yml new file mode 100644 index 0000000..40607bb --- /dev/null +++ b/HomeWork32/eShop-Sample3/docker-compose.yml @@ -0,0 +1,47 @@ +version: '3.8' + +services: + catalog.api: + container_name: lde.catalog.api + build: + context: . + dockerfile: Catalog/Catalog.Host/Dockerfile + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://+:5000 + depends_on: + - postgres + ports: + - 5000:5000 + nginx: + image: nginx + container_name: lde.nginx + ports: + - 80:80 + pgadmin4: + image: dpage/pgadmin4 + container_name: lde.pgadmin4 + environment: + PGADMIN_DEFAULT_EMAIL: user@domain.com + PGADMIN_DEFAULT_PASSWORD: postgres + depends_on: + - postgres + ports: + - 8001:80 + postgres: + image: postgres + container_name: lde.postgres + environment: + POSTGRES_PASSWORD: postgres + ports: + - 5433:5432 +networks: + default: + driver: bridge + internal: false + attachable: true + ipam: + driver: default + config: + - subnet: 192.168.0.0/24 + gateway: 192.168.0.1 \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/eShop.sln b/HomeWork32/eShop-Sample3/eShop.sln new file mode 100644 index 0000000..27ae592 --- /dev/null +++ b/HomeWork32/eShop-Sample3/eShop.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34525.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{E769E2A0-66AF-44D6-9300-C45D3889E06A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Catalog.Host", "Catalog\Catalog.Host\Catalog.Host.csproj", "{6A8E9683-762E-4E83-BD60-75822AC8265D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{DCFFDCA1-598D-4EA6-AAF6-4BE647B27C32}" + ProjectSection(SolutionItems) = preProject + docker-compose.yml = docker-compose.yml + README.md = README.md + settings.ruleset = settings.ruleset + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{A6C7B2CD-2199-497C-9EF5-32274390D2D7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "Infrastructure\Infrastructure\Infrastructure.csproj", "{C877F308-7870-433C-AA13-DE7DBC3675B9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE1C6FA0-60FF-41BF-BA2C-7200F868E922}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6A8E9683-762E-4E83-BD60-75822AC8265D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A8E9683-762E-4E83-BD60-75822AC8265D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A8E9683-762E-4E83-BD60-75822AC8265D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A8E9683-762E-4E83-BD60-75822AC8265D}.Release|Any CPU.Build.0 = Release|Any CPU + {C877F308-7870-433C-AA13-DE7DBC3675B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C877F308-7870-433C-AA13-DE7DBC3675B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C877F308-7870-433C-AA13-DE7DBC3675B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C877F308-7870-433C-AA13-DE7DBC3675B9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {6A8E9683-762E-4E83-BD60-75822AC8265D} = {E769E2A0-66AF-44D6-9300-C45D3889E06A} + {C877F308-7870-433C-AA13-DE7DBC3675B9} = {A6C7B2CD-2199-497C-9EF5-32274390D2D7} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ACE14773-8677-4216-9C1E-C1423562D84A} + EndGlobalSection +EndGlobal diff --git a/HomeWork32/eShop-Sample3/eShop.sln.DotSettings b/HomeWork32/eShop-Sample3/eShop.sln.DotSettings new file mode 100644 index 0000000..06b71d5 --- /dev/null +++ b/HomeWork32/eShop-Sample3/eShop.sln.DotSettings @@ -0,0 +1,2 @@ + + False \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/settings.ruleset b/HomeWork32/eShop-Sample3/settings.ruleset new file mode 100644 index 0000000..fe6f504 --- /dev/null +++ b/HomeWork32/eShop-Sample3/settings.ruleset @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From a6f57752782edef51f5260133ba9211879ba6271 Mon Sep 17 00:00:00 2001 From: BabychMaksym Date: Sat, 18 May 2024 16:51:09 +0300 Subject: [PATCH 2/2] some change --- .../Controllers/CatalogBffController.cs | 21 +++++++++++-------- .../Catalog/Catalog.Host/Program.cs | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs index 6dba0b7..07a82e4 100644 --- a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Controllers/CatalogBffController.cs @@ -35,24 +35,27 @@ public async Task Items(PaginatedItemsRequest request) return Ok(result); } - [HttpGet] - public async Task GetById(int id) + [HttpPost] + [ProducesResponseType(typeof(PaginatedItemsResponse), (int)HttpStatusCode.OK)] + public async Task GetById(int id) { var result = await _catalogItemService.GetCatalogItemsByIdAsync(id); - return result; + return Ok(result); } - [HttpGet] - public async Task> GetByBrand(int idBrand) + [HttpPost] + [ProducesResponseType(typeof(PaginatedItemsResponse), (int)HttpStatusCode.OK)] + public async Task GetByBrand(int idBrand) { var result = await _catalogItemService.GetCatalogItemByBrandAsync(idBrand); - return result; + return Ok(result); } - [HttpGet] - public async Task> GetByType(int idType) + [HttpPost] + [ProducesResponseType(typeof(PaginatedItemsResponse), (int)HttpStatusCode.OK)] + public async Task GetByType(int idType) { var result = await _catalogItemService.GetCatalogItemByTypeAsync(idType); - return result; + return Ok(result); } } \ No newline at end of file diff --git a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs index a6cf416..2498c0b 100644 --- a/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs +++ b/HomeWork32/eShop-Sample3/Catalog/Catalog.Host/Program.cs @@ -19,6 +19,8 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddDbContextFactory(opts => opts.UseNpgsql(configuration["ConnectionString"]!)); builder.Services.AddScoped, DbContextWrapper>();