diff --git a/BreweryAPI/BreweryAPI schema.PNG b/BreweryAPI/BreweryAPI schema.PNG
new file mode 100644
index 0000000..5fd29da
Binary files /dev/null and b/BreweryAPI/BreweryAPI schema.PNG differ
diff --git a/BreweryAPI/BreweryAPI.sln b/BreweryAPI/BreweryAPI.sln
new file mode 100644
index 0000000..749fa3a
--- /dev/null
+++ b/BreweryAPI/BreweryAPI.sln
@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34009.444
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BreweryAPI", "BreweryAPI\BreweryAPI.csproj", "{2776268A-0281-4010-9B3A-1DCBA2B86F37}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "IntegrationTests\IntegrationTests.csproj", "{3DF4EAFA-2635-47BA-A626-0662DC447DA6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BreweryMaui", "BreweryMaui\BreweryMaui.csproj", "{23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2776268A-0281-4010-9B3A-1DCBA2B86F37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2776268A-0281-4010-9B3A-1DCBA2B86F37}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2776268A-0281-4010-9B3A-1DCBA2B86F37}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2776268A-0281-4010-9B3A-1DCBA2B86F37}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3DF4EAFA-2635-47BA-A626-0662DC447DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3DF4EAFA-2635-47BA-A626-0662DC447DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3DF4EAFA-2635-47BA-A626-0662DC447DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3DF4EAFA-2635-47BA-A626-0662DC447DA6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23C06012-5E13-4AD4-9AB1-4FB8B75B3F8C}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {ACB2614C-8CD0-4665-BAB7-E03D00321141}
+ EndGlobalSection
+EndGlobal
diff --git a/BreweryAPI/BreweryAPI/BreweryAPI.csproj b/BreweryAPI/BreweryAPI/BreweryAPI.csproj
new file mode 100644
index 0000000..c83fb52
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/BreweryAPI.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
diff --git a/BreweryAPI/BreweryAPI/Context.cs b/BreweryAPI/BreweryAPI/Context.cs
new file mode 100644
index 0000000..f7e6ec4
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Context.cs
@@ -0,0 +1,19 @@
+using BreweryAPI.Models;
+using Microsoft.EntityFrameworkCore;
+
+namespace BreweryAPI
+{
+ public class Context : DbContext
+ {
+ public DbSet Breweries { get; set; }
+ public DbSet Beers { get; set; }
+ public DbSet BrewerySales { get; set; }
+ public DbSet Wholesalers { get; set; }
+ public DbSet WholesalerInventories { get; set; }
+ public DbSet WholesalerQuotes { get; set; }
+
+ public Context (DbContextOptions options) : base (options)
+ {
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Controllers/BeerController.cs b/BreweryAPI/BreweryAPI/Controllers/BeerController.cs
new file mode 100644
index 0000000..9ff0684
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Controllers/BeerController.cs
@@ -0,0 +1,156 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BreweryAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class BeerController : Controller
+ {
+ private readonly IBeerRepository _beerRepository;
+ private readonly IBreweryRepository _breweryRepository;
+ private readonly IMapper _mapper;
+
+ public BeerController(IBeerRepository beerRepository, IBreweryRepository breweryRepository, IMapper mapper)
+ {
+ _breweryRepository = breweryRepository;
+ _beerRepository = beerRepository;
+ _mapper = mapper;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ public IActionResult GetBeers()
+ {
+ var beers = _mapper.Map>(_beerRepository.GetBeers());
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(beers);
+ }
+
+ [HttpGet("singular/{beerId}")]
+ [ProducesResponseType(200, Type = typeof(BeerModel))]
+ [ProducesResponseType(400)]
+ public IActionResult GetBeer(int beerId)
+ {
+ if (!_beerRepository.BeerExists(beerId))
+ return NotFound();
+
+ var beer = _mapper.Map(_beerRepository.GetBeer(beerId));
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(beer);
+ }
+
+ [HttpGet("{breweryId}")]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ [ProducesResponseType(400)]
+ public IActionResult GetBeersByBrewery(int breweryId)
+ {
+ if (!_breweryRepository.BreweryExists(breweryId))
+ return NotFound();
+
+ var beersByBrewery = _mapper.Map>(_beerRepository.GetBeersByBrewery(breweryId));
+
+ if(beersByBrewery.Count == 0)
+ return NotFound();
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(beersByBrewery);
+ }
+
+ [HttpPost]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(400)]
+ public IActionResult CreateBeer([FromBody] BeerDTO beerCreate)
+ {
+ if (beerCreate == null)
+ return BadRequest(ModelState);
+
+ var beer = _beerRepository.GetBeers()
+ .Where(b => b.BeerName.Trim().ToUpper() == beerCreate.BeerName.TrimEnd().ToUpper())
+ .FirstOrDefault();
+
+ if (beer != null)
+ {
+ ModelState.AddModelError("", "Beer already exists");
+ return StatusCode(422, ModelState);
+ }
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ var beerMap = _mapper.Map(beerCreate);
+
+ if (!_beerRepository.CreateBeer(beerMap))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ return Ok("Succesfully created");
+ }
+
+ [HttpPut("{beerId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult UpdateBeer(int beerId, [FromBody] BeerDTO updatedBeer)
+ {
+ if (updatedBeer == null)
+ return BadRequest(ModelState);
+
+ if (beerId != updatedBeer.BeerId)
+ return BadRequest(ModelState);
+
+ if (!_beerRepository.BeerExists(beerId))
+ return NotFound();
+
+ if (!ModelState.IsValid)
+ return BadRequest();
+
+ var beerMap = _mapper.Map(updatedBeer);
+
+ if (!_beerRepository.UpdateBeer(beerMap))
+ {
+ ModelState.AddModelError("", "Something went wrong updating beer");
+ return StatusCode(500, ModelState);
+ }
+
+ return NoContent();
+ }
+
+ [HttpDelete("{beerId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult DeleteBeer(int beerId)
+ {
+ if (!_beerRepository.BeerExists(beerId))
+ {
+ return NotFound();
+ }
+
+ var beerToDelete = _beerRepository.GetBeer(beerId);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ if (!_beerRepository.DeleteBeer(beerToDelete))
+ {
+ ModelState.AddModelError("", "Something went wrong deleting beer");
+ }
+
+ return NoContent();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Controllers/BreweryController.cs b/BreweryAPI/BreweryAPI/Controllers/BreweryController.cs
new file mode 100644
index 0000000..ee56dde
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Controllers/BreweryController.cs
@@ -0,0 +1,135 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BreweryAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class BreweryController : Controller
+ {
+ private readonly IBreweryRepository _breweryRepository;
+ private readonly IMapper _mapper;
+
+ public BreweryController(IBreweryRepository breweryRepository, IMapper mapper)
+ {
+ _breweryRepository = breweryRepository;
+ _mapper = mapper;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ public IActionResult GetBreweries()
+ {
+ var breweries = _mapper.Map>(_breweryRepository.GetBreweries());
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(breweries);
+ }
+
+ [HttpGet("{breweryId}")]
+ [ProducesResponseType(200, Type = typeof(BreweryModel))]
+ [ProducesResponseType(400)]
+ public IActionResult GetBrewery(int breweryId)
+ {
+ if (!_breweryRepository.BreweryExists(breweryId))
+ return NotFound();
+
+ var brewery = _mapper.Map(_breweryRepository.GetBrewery(breweryId));
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(brewery);
+ }
+
+ [HttpPost]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(400)]
+ public IActionResult CreateBrewery([FromBody] BreweryDTO breweryCreate)
+ {
+ if (breweryCreate == null)
+ return BadRequest(ModelState);
+
+ var brewery = _breweryRepository.GetBreweries()
+ .Where(b => b.BreweryName.Trim().ToUpper() == breweryCreate.BreweryName.TrimEnd().ToUpper())
+ .FirstOrDefault();
+
+ if (brewery != null)
+ {
+ ModelState.AddModelError("", "Brewery already exists");
+ return StatusCode(422, ModelState);
+ }
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ var breweryMap = _mapper.Map(breweryCreate);
+
+ if (!_breweryRepository.CreateBrewery(breweryMap))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ return Ok("Succesfully created");
+ }
+
+ [HttpPut("{breweryId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult UpdateBrewery(int breweryId, [FromBody] BreweryDTO updatedBrewery)
+ {
+ if (updatedBrewery == null)
+ return BadRequest(ModelState);
+
+ if (breweryId != updatedBrewery.BreweryId)
+ return BadRequest(ModelState);
+
+ if (!_breweryRepository.BreweryExists(breweryId))
+ return NotFound();
+
+ if (!ModelState.IsValid)
+ return BadRequest();
+
+ var breweryMap = _mapper.Map(updatedBrewery);
+
+ if (!_breweryRepository.UpdateBrewery(breweryMap))
+ {
+ ModelState.AddModelError("", "Something went wrong updating brewery");
+ return StatusCode(500, ModelState);
+ }
+
+ return NoContent();
+ }
+
+ [HttpDelete("{breweryId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult DeleteBrewery(int breweryId)
+ {
+ if (!_breweryRepository.BreweryExists(breweryId))
+ {
+ return NotFound();
+ }
+
+ var breweryToDelete = _breweryRepository.GetBrewery(breweryId);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ if (!_breweryRepository.DeleteBrewery(breweryToDelete))
+ {
+ ModelState.AddModelError("", "Something went wrong deleting brewery");
+ }
+
+ return NoContent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryAPI/Controllers/BrewerySalesController.cs b/BreweryAPI/BreweryAPI/Controllers/BrewerySalesController.cs
new file mode 100644
index 0000000..a84b25f
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Controllers/BrewerySalesController.cs
@@ -0,0 +1,171 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BreweryAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class BrewerySalesController: Controller
+ {
+ private readonly IBrewerySalesRepository _brewerySalesRepository;
+ private readonly IBeerRepository _beerRepository;
+ private readonly IWholesalerInventoryRepository _wholesalerInventoryRepository;
+ private readonly IMapper _mapper;
+ public BrewerySalesController(IWholesalerInventoryRepository wholesalerInventoryRepository, IBrewerySalesRepository brewerySalesRepository, IBeerRepository beerRepository, IMapper mapper)
+ {
+ _wholesalerInventoryRepository = wholesalerInventoryRepository;
+ _beerRepository = beerRepository;
+ _brewerySalesRepository = brewerySalesRepository;
+ _mapper = mapper;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ public IActionResult GetBrewerySales()
+ {
+ var brewerySales = _mapper.Map>(_brewerySalesRepository.GetBrewerySales());
+
+ if(!ModelState.IsValid)
+ {
+ return BadRequest(ModelState);
+ }
+
+ return Ok(brewerySales);
+ }
+
+
+ [HttpGet("{brewerySalesId}")]
+ [ProducesResponseType(200, Type = typeof(BrewerySalesModel))]
+ [ProducesResponseType(400)]
+ public IActionResult GetBrewerySale(int brewerySalesId)
+ {
+ if (!_brewerySalesRepository.BrewerySaleExists(brewerySalesId))
+ return NotFound();
+
+ var brewerySalesMap = _mapper.Map(_brewerySalesRepository.GetBrewerySale(brewerySalesId));
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(brewerySalesMap);
+ }
+
+ [HttpPost]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(400)]
+ public IActionResult CreateBrewerySale([FromBody] BrewerySalesDTO brewerySaleCreate)
+ {
+ if (brewerySaleCreate == null)
+ return BadRequest(ModelState);
+
+ var beer = _mapper.Map(_beerRepository.GetBeer(brewerySaleCreate.BeerId));
+
+ if(beer == null)
+ return BadRequest(ModelState);
+
+ if(brewerySaleCreate.TotalPrice != beer.Price * brewerySaleCreate.Quantity)
+ return BadRequest(ModelState);
+
+ //Update wholesaler inventory with the quantity of the sale
+ var wholesalerInventory = _wholesalerInventoryRepository.SelectRecord(brewerySaleCreate.WholeSalerId, brewerySaleCreate.BeerId);
+
+ if(wholesalerInventory != null)
+ {
+ wholesalerInventory.Quantity = wholesalerInventory.Quantity + brewerySaleCreate.Quantity;
+ _wholesalerInventoryRepository.UpdateWholesalerInventory(wholesalerInventory);
+ }
+ else
+ {
+ //if the wholesaler buying beer does not have any items to update in their inventory, this will create a new item upon purchase.
+ WholesalerInventoryDTO newInventoryRecord = new WholesalerInventoryDTO
+ {
+ WholesalerId = brewerySaleCreate.WholeSalerId,
+ BeerId = brewerySaleCreate.BeerId,
+ Quantity = brewerySaleCreate.Quantity
+ };
+
+ var InventoryRecordToAdd = _mapper.Map(newInventoryRecord);
+
+ _wholesalerInventoryRepository.CreateWholesalerInventory(InventoryRecordToAdd);
+ }
+
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ var brewerySaleMap = _mapper.Map(brewerySaleCreate);
+
+ if (!_brewerySalesRepository.CreateBrewerySale(brewerySaleMap))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ return Ok("Succesfully created");
+ }
+
+ [HttpPut("{brewerySaleId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult UpdateBrewerySale(int brewerySaleId, [FromBody] BrewerySalesDTO updatedBrewerySale)
+ {
+ if (updatedBrewerySale == null)
+ return BadRequest(ModelState);
+
+ if (brewerySaleId != updatedBrewerySale.SalesId)
+ return BadRequest(ModelState);
+
+ var beer = _mapper.Map(_beerRepository.GetBeer(updatedBrewerySale.BeerId));
+
+ if (beer == null)
+ return BadRequest(ModelState);
+
+ if (updatedBrewerySale.TotalPrice != beer.Price * updatedBrewerySale.Quantity)
+ return BadRequest(ModelState);
+
+ if (!_brewerySalesRepository.BrewerySaleExists(brewerySaleId))
+ return NotFound();
+
+ if (!ModelState.IsValid)
+ return BadRequest();
+
+ var brewerySaleMap = _mapper.Map(updatedBrewerySale);
+
+ if (!_brewerySalesRepository.UpdateBrewerySales(brewerySaleMap))
+ {
+ ModelState.AddModelError("", "Something went wrong updating brewerySale");
+ return StatusCode(500, ModelState);
+ }
+
+ return NoContent();
+ }
+
+ [HttpDelete("{brewerySaleId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult DeleteBrewerySale(int brewerySaleId)
+ {
+ if (!_brewerySalesRepository.BrewerySaleExists(brewerySaleId))
+ {
+ return NotFound();
+ }
+
+ var brewerySaleToDelete = _brewerySalesRepository.GetBrewerySale (brewerySaleId);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ if (!_brewerySalesRepository.DeleteBrewerySales(brewerySaleToDelete))
+ {
+ ModelState.AddModelError("", "Something went wrong deleting brewery");
+ }
+
+ return NoContent();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Controllers/WholesalerController.cs b/BreweryAPI/BreweryAPI/Controllers/WholesalerController.cs
new file mode 100644
index 0000000..2b960ff
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Controllers/WholesalerController.cs
@@ -0,0 +1,134 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BreweryAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class WholesalerController: Controller
+ {
+ private readonly IWholesalerRepository _wholesalerRepository;
+ private readonly IMapper _mapper;
+ public WholesalerController(IWholesalerRepository wholesalerRepository, IMapper mapper)
+ {
+ _wholesalerRepository = wholesalerRepository;
+ _mapper = mapper;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ public IActionResult GetWholesalers()
+ {
+ var wholesalers = _mapper.Map>(_wholesalerRepository.GetWholesalers());
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(wholesalers);
+ }
+
+ [HttpGet("{wholesalerId}")]
+ [ProducesResponseType(200, Type = typeof(WholesalerModel))]
+ [ProducesResponseType(400)]
+ public IActionResult GetWholesaler(int wholesalerId)
+ {
+ if (!_wholesalerRepository.WholesalerExists(wholesalerId))
+ return NotFound();
+
+ var wholesaler = _mapper.Map(_wholesalerRepository.GetWholesaler(wholesalerId));
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(wholesaler);
+ }
+
+ [HttpPost]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(400)]
+ public IActionResult CreateWholesaler([FromBody] WholesalerDTO wholesalerCreate)
+ {
+ if (wholesalerCreate == null)
+ return BadRequest(ModelState);
+
+ var wholesaler = _wholesalerRepository.GetWholesalers()
+ .Where(b => b.WholesalerName.Trim().ToUpper() == wholesalerCreate.WholesalerName.TrimEnd().ToUpper())
+ .FirstOrDefault();
+
+ if (wholesaler != null)
+ {
+ ModelState.AddModelError("", "Wholesaler already exists");
+ return StatusCode(422, ModelState);
+ }
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ var wholesalerMap = _mapper.Map(wholesalerCreate);
+
+ if (!_wholesalerRepository.CreateWholesaler(wholesalerMap))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ return Ok("Succesfully created");
+ }
+
+ [HttpPut("{wholesalerId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult UpdateWholesaler(int wholesalerId, [FromBody] WholesalerDTO updateWholesaler)
+ {
+ if (updateWholesaler == null)
+ return BadRequest(ModelState);
+
+ if (wholesalerId != updateWholesaler.WholesalerID)
+ return BadRequest(ModelState);
+
+ if (!_wholesalerRepository.WholesalerExists(wholesalerId))
+ return NotFound();
+
+ if (!ModelState.IsValid)
+ return BadRequest();
+
+ var wholesalerMap = _mapper.Map(updateWholesaler);
+
+ if (!_wholesalerRepository.UpdateWholesaler(wholesalerMap))
+ {
+ ModelState.AddModelError("", "Something went wrong updating wholesaler");
+ return StatusCode(500, ModelState);
+ }
+
+ return NoContent();
+ }
+
+ [HttpDelete("{wholesalerId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult DeleteWholesaler(int wholesalerId)
+ {
+ if (!_wholesalerRepository.WholesalerExists(wholesalerId))
+ {
+ return NotFound();
+ }
+
+ var wholesalerToDelete = _wholesalerRepository.GetWholesaler(wholesalerId);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ if (!_wholesalerRepository.DeleteWholesaler(wholesalerToDelete))
+ {
+ ModelState.AddModelError("", "Something went wrong deleting wholesaler");
+ }
+
+ return NoContent();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Controllers/WholesalerInventoryController.cs b/BreweryAPI/BreweryAPI/Controllers/WholesalerInventoryController.cs
new file mode 100644
index 0000000..29bc32f
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Controllers/WholesalerInventoryController.cs
@@ -0,0 +1,142 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BreweryAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class WholesalerInventoryController: Controller
+ {
+ private readonly IWholesalerInventoryRepository _wholesalerInventoryRepository;
+ private readonly IBeerRepository _beerRepository;
+ private readonly IMapper _mapper;
+ public WholesalerInventoryController(IWholesalerInventoryRepository wholesalerInventoryRepository, IBeerRepository beerRepository, IMapper mapper)
+ {
+ _wholesalerInventoryRepository = wholesalerInventoryRepository;
+ _beerRepository = beerRepository;
+ _mapper = mapper;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ public IActionResult GetWholesalerInventories()
+ {
+ var wholesalerInventories = _mapper.Map>(_wholesalerInventoryRepository.GetWholesalerInventories());
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(wholesalerInventories);
+ }
+
+ [HttpGet("{wholesalerInventoryId}")]
+ [ProducesResponseType(200, Type = typeof(WholesalerInventory))]
+ [ProducesResponseType(400)]
+ public IActionResult GetWholesalerInventory(int wholesalerInventoryId)
+ {
+ if (!_wholesalerInventoryRepository.WholesalerInventoryExists(wholesalerInventoryId))
+ return NotFound();
+
+ var wholesaler = _mapper.Map(_wholesalerInventoryRepository.GetWholesalerInventory(wholesalerInventoryId));
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(wholesaler);
+ }
+
+ [HttpPost]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(400)]
+ public IActionResult createWholesalerInventory([FromBody] WholesalerInventoryDTO wholesalerInventoryCreate)
+ {
+ if (wholesalerInventoryCreate == null)
+ return BadRequest(ModelState);
+
+ var beer = _mapper.Map(_beerRepository.GetBeer(wholesalerInventoryCreate.BeerId));
+
+ if (beer == null)
+ return BadRequest(ModelState);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ var wholesalerInventoryMap = _mapper.Map(wholesalerInventoryCreate);
+
+ if (_wholesalerInventoryRepository.IsUniqueRecord(wholesalerInventoryMap))
+ {
+ ModelState.AddModelError("", "Record already exists");
+ return StatusCode(422, ModelState);
+ }
+
+ if (!_wholesalerInventoryRepository.CreateWholesalerInventory(wholesalerInventoryMap))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ return Ok("Succesfully created");
+ }
+
+ [HttpPut("{wholesaleInventoryId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult updateWholesalerInventory(int wholesaleInventoryId, [FromBody] WholesalerInventoryDTO updateWholesaleInventory)
+ {
+ if (updateWholesaleInventory == null)
+ return BadRequest(ModelState);
+
+ if (wholesaleInventoryId != updateWholesaleInventory.ItemId)
+ return BadRequest(ModelState);
+
+ var beer = _mapper.Map(_beerRepository.GetBeer(updateWholesaleInventory.BeerId));
+
+ if (beer == null)
+ return BadRequest(ModelState);
+
+ if (!_wholesalerInventoryRepository.WholesalerInventoryExists(wholesaleInventoryId))
+ return NotFound();
+
+ if (!ModelState.IsValid)
+ return BadRequest();
+
+ var wholesaleInventoryMap = _mapper.Map(updateWholesaleInventory);
+
+ if (!_wholesalerInventoryRepository.UpdateWholesalerInventory(wholesaleInventoryMap))
+ {
+ ModelState.AddModelError("", "Something went wrong updating wholesaleInventory");
+ return StatusCode(500, ModelState);
+ }
+
+ return NoContent();
+ }
+
+ [HttpDelete("{wholesaleInventoryId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult DeleteWholesaleInventory(int wholesaleInventoryId)
+ {
+ if (!_wholesalerInventoryRepository.WholesalerInventoryExists(wholesaleInventoryId))
+ {
+ return NotFound();
+ }
+
+ var wholesaleInventoryModel = _wholesalerInventoryRepository.GetWholesalerInventory(wholesaleInventoryId);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ if (!_wholesalerInventoryRepository.DeleteWholesalerInventory(wholesaleInventoryModel))
+ {
+ ModelState.AddModelError("", "Something went wrong deleting wholesaleInventory");
+ }
+
+ return NoContent();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Controllers/WholesalerQuoteController.cs b/BreweryAPI/BreweryAPI/Controllers/WholesalerQuoteController.cs
new file mode 100644
index 0000000..86b1aba
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Controllers/WholesalerQuoteController.cs
@@ -0,0 +1,128 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace BreweryAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class WholesalerQuoteController: Controller
+ {
+ private readonly IWholesalerInventoryRepository _wholesalerInventoryRepository;
+ private readonly IWholesalerQuoteRepository _wholesalerQuoteRepository;
+ private readonly IMapper _mapper;
+
+ public WholesalerQuoteController(IWholesalerInventoryRepository wholesalerInventoryRepository, IWholesalerQuoteRepository wholesalerQuoteRepository, IMapper mapper)
+ {
+ _wholesalerInventoryRepository = wholesalerInventoryRepository;
+ _wholesalerQuoteRepository = wholesalerQuoteRepository;
+ _mapper = mapper;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(200, Type = typeof(IEnumerable))]
+ public IActionResult GetWholesalerQuotes()
+ {
+ var wholesalerQuotes = _mapper.Map>(_wholesalerQuoteRepository.GetWholesalerQuotes());
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(wholesalerQuotes);
+ }
+
+
+ [HttpGet("{wholesalerQuoteId}")]
+ [ProducesResponseType(200, Type = typeof(WholesalerQuoteModel))]
+ [ProducesResponseType(400)]
+ public IActionResult GetWholesalerQuote(int wholesalerQuoteId)
+ {
+ if (!_wholesalerQuoteRepository.WholesalerQuoteExists(wholesalerQuoteId))
+ return NotFound();
+
+ var wholesalerQuoteMap = _mapper.Map(_wholesalerQuoteRepository.GetWholesalerQuote(wholesalerQuoteId));
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ return Ok(wholesalerQuoteMap);
+ }
+
+ [HttpPost]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(400)]
+ public IActionResult CreateWholesalerQuote([FromBody] WholesalerQuoteDTO wholesalerQuoteCreate)
+ {
+ if (wholesalerQuoteCreate == null)
+ return BadRequest(ModelState);
+
+ var wholesalerInventoryRecord = _mapper.Map(_wholesalerInventoryRepository.SelectRecord(wholesalerQuoteCreate.WholesalerId, wholesalerQuoteCreate.BeerId));
+
+ if (wholesalerInventoryRecord == null)
+ return BadRequest(ModelState);
+
+ if(wholesalerQuoteCreate.Quantity > wholesalerInventoryRecord.Quantity)
+ {
+ return BadRequest(ModelState);
+ }
+ else
+ {
+ wholesalerInventoryRecord.Quantity = wholesalerInventoryRecord.Quantity - wholesalerQuoteCreate.Quantity;
+ }
+
+ if(wholesalerQuoteCreate.Quantity > 10)
+ {
+ wholesalerQuoteCreate.TotalPrice = wholesalerQuoteCreate.TotalPrice * 90;
+ }
+ else if (wholesalerQuoteCreate.Quantity > 20)
+ {
+ wholesalerQuoteCreate.TotalPrice = wholesalerQuoteCreate.TotalPrice * 80;
+ }
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ var wholesalerQuoteMap = _mapper.Map(wholesalerQuoteCreate);
+
+ if (!_wholesalerQuoteRepository.CreateWholesalerQuote(wholesalerQuoteMap))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ if (!_wholesalerInventoryRepository.UpdateWholesalerInventory(wholesalerInventoryRecord))
+ {
+ ModelState.AddModelError("", "something went wrong while saving");
+ return StatusCode(500, ModelState);
+ }
+
+ return Ok("Succesfully created");
+ }
+
+ [HttpDelete("{wholesalerQuoteId}")]
+ [ProducesResponseType(400)]
+ [ProducesResponseType(204)]
+ [ProducesResponseType(404)]
+ public IActionResult DeleteWholesalerQuote(int wholesalerQuoteId)
+ {
+ if (!_wholesalerQuoteRepository.WholesalerQuoteExists(wholesalerQuoteId))
+ {
+ return NotFound();
+ }
+
+ var wholesalerQuoteToDelete = _wholesalerQuoteRepository.GetWholesalerQuote(wholesalerQuoteId);
+
+ if (!ModelState.IsValid)
+ return BadRequest(ModelState);
+
+ if (!_wholesalerQuoteRepository.DeleteWholesalerQuote(wholesalerQuoteToDelete))
+ {
+ ModelState.AddModelError("", "Something went wrong deleting wholesaler");
+ }
+
+ return NoContent();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/DTOs/BeerDTO.cs b/BreweryAPI/BreweryAPI/DTOs/BeerDTO.cs
new file mode 100644
index 0000000..19c39c1
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/DTOs/BeerDTO.cs
@@ -0,0 +1,10 @@
+namespace BreweryAPI.DTOs
+{
+ public class BeerDTO
+ {
+ public int BeerId { get; set; }
+ public string BeerName { get; set; }
+ public decimal Price { get; set; }
+ public int BreweryId { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/DTOs/BreweryDTO.cs b/BreweryAPI/BreweryAPI/DTOs/BreweryDTO.cs
new file mode 100644
index 0000000..849fbf8
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/DTOs/BreweryDTO.cs
@@ -0,0 +1,9 @@
+namespace BreweryAPI.DTOs
+{
+ public class BreweryDTO
+ {
+ public int BreweryId { get; set; }
+ public string BreweryName { get; set; }
+ public string BreweryLocation { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/DTOs/BrewerySalesDTO.cs b/BreweryAPI/BreweryAPI/DTOs/BrewerySalesDTO.cs
new file mode 100644
index 0000000..5969ba9
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/DTOs/BrewerySalesDTO.cs
@@ -0,0 +1,11 @@
+namespace BreweryAPI.DTOs
+{
+ public class BrewerySalesDTO
+ {
+ public int SalesId { get; set; }
+ public int WholeSalerId { get; set; }
+ public int BeerId { get; set; }
+ public int Quantity { get; set; }
+ public decimal TotalPrice { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/DTOs/WholesalerDTO.cs b/BreweryAPI/BreweryAPI/DTOs/WholesalerDTO.cs
new file mode 100644
index 0000000..4cef0d6
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/DTOs/WholesalerDTO.cs
@@ -0,0 +1,9 @@
+namespace BreweryAPI.DTOs
+{
+ public class WholesalerDTO
+ {
+ public int WholesalerID { get; set; }
+ public string WholesalerName { get; set; }
+ public string WholesalerLocation { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/DTOs/WholesalerInventoryDTO.cs b/BreweryAPI/BreweryAPI/DTOs/WholesalerInventoryDTO.cs
new file mode 100644
index 0000000..2227893
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/DTOs/WholesalerInventoryDTO.cs
@@ -0,0 +1,10 @@
+namespace BreweryAPI.DTOs
+{
+ public class WholesalerInventoryDTO
+ {
+ public int ItemId { get; set; }
+ public int WholesalerId { get; set; }
+ public int BeerId { get; set; }
+ public int Quantity { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/DTOs/WholesalerQuoteDTO.cs b/BreweryAPI/BreweryAPI/DTOs/WholesalerQuoteDTO.cs
new file mode 100644
index 0000000..b9a188c
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/DTOs/WholesalerQuoteDTO.cs
@@ -0,0 +1,12 @@
+namespace BreweryAPI.DTOs
+{
+ public class WholesalerQuoteDTO
+ {
+ public int QuoteId { get; set; }
+ public string ClientName { get; set; }
+ public int WholesalerId { get; set; }
+ public int BeerId { get; set; }
+ public int Quantity { get; set; }
+ public decimal TotalPrice { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Helpers/MappingProfiles.cs b/BreweryAPI/BreweryAPI/Helpers/MappingProfiles.cs
new file mode 100644
index 0000000..1ac51a5
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Helpers/MappingProfiles.cs
@@ -0,0 +1,25 @@
+using AutoMapper;
+using BreweryAPI.DTOs;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Helpers
+{
+ public class MappingProfiles : Profile
+ {
+ public MappingProfiles()
+ {
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ CreateMap();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Interface/IBeerRepository.cs b/BreweryAPI/BreweryAPI/Interface/IBeerRepository.cs
new file mode 100644
index 0000000..c2e99cb
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Interface/IBeerRepository.cs
@@ -0,0 +1,16 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Interface
+{
+ public interface IBeerRepository
+ {
+ ICollection GetBeers();
+ BeerModel GetBeer(int id);
+ bool CreateBeer(BeerModel beerModel);
+ bool UpdateBeer(BeerModel beerModel);
+ bool DeleteBeer(BeerModel beerModel);
+ public ICollection GetBeersByBrewery(int breweryId);
+ bool BeerExists(int id);
+ bool Save();
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Interface/IBreweryRepository.cs b/BreweryAPI/BreweryAPI/Interface/IBreweryRepository.cs
new file mode 100644
index 0000000..2589acb
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Interface/IBreweryRepository.cs
@@ -0,0 +1,15 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Interface
+{
+ public interface IBreweryRepository
+ {
+ ICollection GetBreweries();
+ BreweryModel GetBrewery(int id);
+ bool CreateBrewery(BreweryModel breweryModel);
+ bool UpdateBrewery(BreweryModel breweryModel);
+ bool DeleteBrewery(BreweryModel breweryModel);
+ bool BreweryExists(int id);
+ bool Save();
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Interface/IBrewerySalesRepository.cs b/BreweryAPI/BreweryAPI/Interface/IBrewerySalesRepository.cs
new file mode 100644
index 0000000..37f74c2
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Interface/IBrewerySalesRepository.cs
@@ -0,0 +1,15 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Interface
+{
+ public interface IBrewerySalesRepository
+ {
+ ICollection GetBrewerySales();
+ BrewerySalesModel GetBrewerySale(int id);
+ bool CreateBrewerySale(BrewerySalesModel brewerySalesModel);
+ bool UpdateBrewerySales(BrewerySalesModel brewerySalesModel);
+ bool DeleteBrewerySales(BrewerySalesModel brewerySalesModel);
+ bool BrewerySaleExists(int id);
+ bool Save();
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Interface/IWholesalerInventoryRepository.cs b/BreweryAPI/BreweryAPI/Interface/IWholesalerInventoryRepository.cs
new file mode 100644
index 0000000..cd42fcb
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Interface/IWholesalerInventoryRepository.cs
@@ -0,0 +1,17 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Interface
+{
+ public interface IWholesalerInventoryRepository
+ {
+ ICollection GetWholesalerInventories();
+ WholesalerInventory GetWholesalerInventory(int id);
+ bool CreateWholesalerInventory(WholesalerInventory wholesalerInventory);
+ bool UpdateWholesalerInventory(WholesalerInventory wholesalerInventory);
+ bool DeleteWholesalerInventory(WholesalerInventory wholesalerInventory);
+ bool WholesalerInventoryExists(int id);
+ bool Save();
+ public bool IsUniqueRecord(WholesalerInventory wholesalerInventory);
+ public WholesalerInventory SelectRecord(int wholesalerId, int beerId);
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Interface/IWholesalerQuoteRepository.cs b/BreweryAPI/BreweryAPI/Interface/IWholesalerQuoteRepository.cs
new file mode 100644
index 0000000..aeda2dc
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Interface/IWholesalerQuoteRepository.cs
@@ -0,0 +1,15 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Interface
+{
+ public interface IWholesalerQuoteRepository
+ {
+ ICollection GetWholesalerQuotes();
+ WholesalerQuoteModel GetWholesalerQuote(int id);
+ bool CreateWholesalerQuote(WholesalerQuoteModel wholesalerQuote);
+ bool UpdateWholesalerQuote(WholesalerQuoteModel wholesalerQuote);
+ bool DeleteWholesalerQuote(WholesalerQuoteModel wholesalerQuote);
+ bool WholesalerQuoteExists(int id);
+ bool Save();
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Interface/IWholesalerRepository.cs b/BreweryAPI/BreweryAPI/Interface/IWholesalerRepository.cs
new file mode 100644
index 0000000..3c4cc87
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Interface/IWholesalerRepository.cs
@@ -0,0 +1,15 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Interface
+{
+ public interface IWholesalerRepository
+ {
+ ICollection GetWholesalers();
+ WholesalerModel GetWholesaler(int id);
+ bool CreateWholesaler(WholesalerModel wholesalerModel);
+ bool UpdateWholesaler(WholesalerModel wholesalerModel);
+ bool DeleteWholesaler(WholesalerModel wholesalerModel);
+ bool WholesalerExists(int id);
+ bool Save();
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Models/BeerModel.cs b/BreweryAPI/BreweryAPI/Models/BeerModel.cs
new file mode 100644
index 0000000..4ac6067
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Models/BeerModel.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace BreweryAPI.Models
+{
+ public class BeerModel
+ {
+ [Key]
+ public int BeerId { get; set; }
+ public string BeerName { get; set; }
+ public decimal Price { get; set; }
+ public int BreweryId { get; set; }
+
+ public BreweryModel Brewery { get; set; }
+ public ICollection WholesalerInventories { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Models/BreweryModel.cs b/BreweryAPI/BreweryAPI/Models/BreweryModel.cs
new file mode 100644
index 0000000..65a7262
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Models/BreweryModel.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace BreweryAPI.Models
+{
+ public class BreweryModel
+ {
+ [Key]
+ public int BreweryId { get; set; }
+ public string BreweryName { get; set; }
+ public string BreweryLocation { get; set; }
+
+ public ICollection Beers{get; set;}
+ }
+}
+
diff --git a/BreweryAPI/BreweryAPI/Models/BrewerySalesModel.cs b/BreweryAPI/BreweryAPI/Models/BrewerySalesModel.cs
new file mode 100644
index 0000000..4d5c723
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Models/BrewerySalesModel.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace BreweryAPI.Models
+{
+ public class BrewerySalesModel
+ {
+ [Key]
+ public int SalesId { get; set; }
+ public int WholeSalerId { get; set; }
+ public int BeerId { get; set; }
+ public int Quantity { get; set; }
+ public decimal TotalPrice { get; set; }
+
+ public WholesalerModel Wholesaler { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Models/WholesalerInventory.cs b/BreweryAPI/BreweryAPI/Models/WholesalerInventory.cs
new file mode 100644
index 0000000..0e5aea8
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Models/WholesalerInventory.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace BreweryAPI.Models
+{
+ public class WholesalerInventory
+ {
+ [Key]
+ public int ItemId { get; set; }
+ public int WholesalerId { get; set; }
+ public int BeerId { get; set; }
+ public int Quantity { get; set; }
+
+ public WholesalerModel Wholesaler { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Models/WholesalerModel.cs b/BreweryAPI/BreweryAPI/Models/WholesalerModel.cs
new file mode 100644
index 0000000..39c0077
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Models/WholesalerModel.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace BreweryAPI.Models
+{
+ public class WholesalerModel
+ {
+ [Key]
+ public int WholesalerID { get; set; }
+ public string WholesalerName { get;set; }
+ public string WholesalerLocation { get; set; }
+
+ public ICollection WholesalerInventories { get; set; } // One-to-many relationship to Inventories
+ public ICollection WholesalerQuote { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Models/WholesalerQuoteModel.cs b/BreweryAPI/BreweryAPI/Models/WholesalerQuoteModel.cs
new file mode 100644
index 0000000..fd4a8a8
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Models/WholesalerQuoteModel.cs
@@ -0,0 +1,17 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace BreweryAPI.Models
+{
+ public class WholesalerQuoteModel
+ {
+ [Key]
+ public int QuoteId { get; set; }
+ public string ClientName { get; set; }
+ public int WholesalerId { get; set; }
+ public int BeerId { get; set; }
+ public int Quantity { get; set; }
+ public decimal TotalPrice { get; set; }
+
+ public WholesalerModel Wholesaler { get; set; }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Program.cs b/BreweryAPI/BreweryAPI/Program.cs
new file mode 100644
index 0000000..178984d
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Program.cs
@@ -0,0 +1,71 @@
+using BreweryAPI;
+
+using BreweryAPI.Interface;
+using BreweryAPI.Repositories;
+
+using Microsoft.EntityFrameworkCore;
+
+public class Program
+{
+ private static void Main(string[] args)
+ {
+ Context context;
+ bool isTestEnvironment = Environment.GetEnvironmentVariable("TEST_ENVIRONMENT")?.Equals("true", StringComparison.OrdinalIgnoreCase) ?? false;
+
+ var builder = WebApplication.CreateBuilder(args);
+
+ builder.Services.AddControllers();
+ builder.Services.AddScoped();
+ builder.Services.AddScoped();
+ builder.Services.AddScoped();
+ builder.Services.AddScoped();
+ builder.Services.AddScoped();
+ builder.Services.AddScoped();
+ builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
+ builder.Services.AddEndpointsApiExplorer();
+ builder.Services.AddSwaggerGen();
+ builder.Services.AddDbContext(options =>
+ {
+ options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
+ });
+
+ var app = builder.Build();
+
+ using (var scope = app.Services.CreateScope())
+ {
+ context = scope.ServiceProvider.GetService();
+
+ try
+ {
+ if(!isTestEnvironment)
+ {
+ SeedData seedData = new SeedData(context);
+ seedData.SeedDataContext();
+ }
+
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Database creation error: {ex.Message}");
+ }
+ }
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseSwagger();
+ app.UseSwaggerUI();
+ }
+
+ app.UseHttpsRedirection();
+
+ app.UseAuthorization();
+
+ app.MapControllers();
+
+ app.Run();
+ }
+
+ private static bool IsTestEnvironment(string[] args)
+ {
+ return args.Contains("--test-environment");
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryAPI/Properties/launchSettings.json b/BreweryAPI/BreweryAPI/Properties/launchSettings.json
new file mode 100644
index 0000000..05f6552
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:48553",
+ "sslPort": 44355
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "http://localhost:5124",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7256;http://localhost:5124",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Repositories/BeerRepository.cs b/BreweryAPI/BreweryAPI/Repositories/BeerRepository.cs
new file mode 100644
index 0000000..6ac8be2
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Repositories/BeerRepository.cs
@@ -0,0 +1,58 @@
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Repositories
+{
+ public class BeerRepository : IBeerRepository
+ {
+ private readonly Context _context;
+ public BeerRepository(Context context)
+ {
+ _context = context;
+ }
+
+ public bool BeerExists(int id)
+ {
+ return _context.Beers.Any(b => b.BeerId == id);
+ }
+
+ public bool CreateBeer(BeerModel beerModel)
+ {
+ _context.Add(beerModel);
+ return Save();
+ }
+
+ public bool DeleteBeer(BeerModel beerModel)
+ {
+ _context.Remove(beerModel);
+ return Save();
+ }
+
+ public BeerModel GetBeer(int id)
+ {
+ return _context.Beers.Where(b => b.BeerId == id).FirstOrDefault();
+ }
+
+ public ICollection GetBeers()
+ {
+ return _context.Beers.ToList();
+ }
+
+ public ICollection GetBeersByBrewery(int breweryId)
+ {
+ return _context.Beers.Where(b => b.BreweryId == breweryId).ToList();
+ }
+
+ public bool Save()
+ {
+ var saved = _context.SaveChanges();
+ return saved > 0 ? true : false;
+ }
+
+ public bool UpdateBeer(BeerModel beerModel)
+ {
+ _context.Update(beerModel);
+ return Save();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Repositories/BreweryRepository.cs b/BreweryAPI/BreweryAPI/Repositories/BreweryRepository.cs
new file mode 100644
index 0000000..cca8edd
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Repositories/BreweryRepository.cs
@@ -0,0 +1,53 @@
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Repositories
+{
+ public class BreweryRepository : IBreweryRepository
+ {
+ private readonly Context _context;
+ public BreweryRepository(Context context)
+ {
+ _context = context;
+ }
+
+ public bool BreweryExists(int id)
+ {
+ return _context.Breweries.Any(c => c.BreweryId == id);
+ }
+
+ public bool CreateBrewery(BreweryModel breweryModel)
+ {
+ _context.Add(breweryModel);
+ return Save();
+ }
+
+ public bool DeleteBrewery(BreweryModel breweryModel)
+ {
+ _context.Remove(breweryModel);
+ return Save();
+ }
+
+ public BreweryModel GetBrewery(int id)
+ {
+ return _context.Breweries.Where(b => b.BreweryId == id).FirstOrDefault();
+ }
+
+ public bool Save()
+ {
+ var saved = _context.SaveChanges();
+ return saved > 0 ? true : false;
+ }
+
+ public bool UpdateBrewery(BreweryModel breweryModel)
+ {
+ _context.Update(breweryModel);
+ return Save();
+ }
+
+ ICollection IBreweryRepository.GetBreweries()
+ {
+ return _context.Breweries.ToList();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Repositories/BrewerySalesRepository.cs b/BreweryAPI/BreweryAPI/Repositories/BrewerySalesRepository.cs
new file mode 100644
index 0000000..8697a1e
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Repositories/BrewerySalesRepository.cs
@@ -0,0 +1,53 @@
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Repositories
+{
+ public class BrewerySalesRepository : IBrewerySalesRepository
+ {
+ private readonly Context _context;
+ public BrewerySalesRepository(Context context)
+ {
+ _context = context;
+ }
+
+ public bool BrewerySaleExists(int id)
+ {
+ return _context.BrewerySales.Any(bs => bs.SalesId == id);
+ }
+
+ public bool CreateBrewerySale(BrewerySalesModel brewerySalesModel)
+ {
+ _context.Add(brewerySalesModel);
+ return Save();
+ }
+
+ public bool DeleteBrewerySales(BrewerySalesModel brewerySalesModel)
+ {
+ _context.Remove(brewerySalesModel);
+ return Save();
+ }
+
+ public BrewerySalesModel GetBrewerySale(int id)
+ {
+ return _context.BrewerySales.Where(bs => bs.SalesId == id).FirstOrDefault();
+ }
+
+ public ICollection GetBrewerySales()
+ {
+ return _context.BrewerySales.ToList();
+ }
+
+ public bool Save()
+ {
+ var saved = _context.SaveChanges();
+ return saved > 0 ? true : false;
+ }
+
+ public bool UpdateBrewerySales(BrewerySalesModel brewerySalesModel)
+ {
+ _context.Update(brewerySalesModel);
+ return Save();
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Repositories/WholesalerInventoryRepository.cs b/BreweryAPI/BreweryAPI/Repositories/WholesalerInventoryRepository.cs
new file mode 100644
index 0000000..8f3106b
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Repositories/WholesalerInventoryRepository.cs
@@ -0,0 +1,63 @@
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Repositories
+{
+ public class WholesalerInventoryRepository : IWholesalerInventoryRepository
+ {
+ private readonly Context _context;
+ public WholesalerInventoryRepository(Context context)
+ {
+ _context = context;
+ }
+ public bool CreateWholesalerInventory(WholesalerInventory wholesalerInventory)
+ {
+ _context.Add(wholesalerInventory);
+ return Save();
+ }
+
+ public bool DeleteWholesalerInventory(WholesalerInventory wholesalerInventory)
+ {
+ _context.Remove(wholesalerInventory);
+ return Save();
+ }
+
+ public ICollection GetWholesalerInventories()
+ {
+ return _context.WholesalerInventories.ToList();
+ }
+
+ public WholesalerInventory GetWholesalerInventory(int id)
+ {
+ return _context.WholesalerInventories.Where(wi => wi.ItemId == id).FirstOrDefault();
+ }
+
+ public bool Save()
+ {
+ var saved = _context.SaveChanges();
+ return saved > 0 ? true : false;
+ }
+
+ public bool UpdateWholesalerInventory(WholesalerInventory wholesalerInventory)
+ {
+ _context.Update(wholesalerInventory);
+ return Save();
+ }
+
+ public bool WholesalerInventoryExists(int id)
+ {
+ return _context.WholesalerInventories.Any(wi => wi.ItemId == id);
+ }
+
+ public WholesalerInventory SelectRecord(int wholesalerId, int beerId)
+ {
+ return _context.WholesalerInventories.Where(wi => wi.WholesalerId == wholesalerId)
+ .Where(wi => wi.BeerId == beerId).FirstOrDefault();
+ }
+ public bool IsUniqueRecord(WholesalerInventory wholesalerInventory)
+ {
+ return _context.WholesalerInventories.Where(wi => wi.WholesalerId == wholesalerInventory.WholesalerId)
+ .Any(wi => wi.BeerId == wholesalerInventory.BeerId);
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Repositories/WholesalerQuoteRepository.cs b/BreweryAPI/BreweryAPI/Repositories/WholesalerQuoteRepository.cs
new file mode 100644
index 0000000..e216555
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Repositories/WholesalerQuoteRepository.cs
@@ -0,0 +1,53 @@
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Repositories
+{
+ public class WholesalerQuoteRepository : IWholesalerQuoteRepository
+ {
+ private readonly Context _context;
+ public WholesalerQuoteRepository(Context context)
+ {
+ _context = context;
+ }
+
+ public bool CreateWholesalerQuote(WholesalerQuoteModel wholesalerQuote)
+ {
+ _context.Add(wholesalerQuote);
+ return Save();
+ }
+
+ public bool DeleteWholesalerQuote(WholesalerQuoteModel wholesalerQuote)
+ {
+ _context.Remove(wholesalerQuote);
+ return Save();
+ }
+
+ public bool UpdateWholesalerQuote(WholesalerQuoteModel wholesalerQuote)
+ {
+ _context.Update(wholesalerQuote);
+ return Save();
+ }
+
+ public WholesalerQuoteModel GetWholesalerQuote(int id)
+ {
+ return _context.WholesalerQuotes.Where(wq => wq.QuoteId == id).FirstOrDefault();
+ }
+
+ public ICollection GetWholesalerQuotes()
+ {
+ return _context.WholesalerQuotes.ToList();
+ }
+
+ public bool Save()
+ {
+ var saved = _context.SaveChanges();
+ return saved > 0 ? true : false;
+ }
+
+ public bool WholesalerQuoteExists(int id)
+ {
+ return _context.WholesalerQuotes.Any(wq => wq.QuoteId == id);
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/Repositories/WholesalerRepository.cs b/BreweryAPI/BreweryAPI/Repositories/WholesalerRepository.cs
new file mode 100644
index 0000000..78bfa72
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/Repositories/WholesalerRepository.cs
@@ -0,0 +1,54 @@
+using BreweryAPI.Interface;
+using BreweryAPI.Models;
+
+namespace BreweryAPI.Repositories
+{
+ public class WholesalerRepository : IWholesalerRepository
+ {
+ private readonly Context _context
+ ;
+ public WholesalerRepository(Context context
+ )
+ {
+ _context = context;
+ }
+ public bool CreateWholesaler(WholesalerModel wholesalerModel)
+ {
+ _context.Add(wholesalerModel );
+ return Save();
+ }
+
+ public bool DeleteWholesaler(WholesalerModel wholesalerModel)
+ {
+ _context.Remove(wholesalerModel);
+ return Save();
+ }
+
+ public WholesalerModel GetWholesaler(int id)
+ {
+ return _context.Wholesalers.Where(w => w.WholesalerID == id).FirstOrDefault();
+ }
+
+ public ICollection GetWholesalers()
+ {
+ return _context.Wholesalers.ToList();
+ }
+
+ public bool Save()
+ {
+ var saved = _context.SaveChanges();
+ return saved > 0 ? true : false;
+ }
+
+ public bool UpdateWholesaler(WholesalerModel wholesalerModel)
+ {
+ _context.Update(wholesalerModel);
+ return Save();
+ }
+
+ public bool WholesalerExists(int id)
+ {
+ return _context.Wholesalers.Any(w => w.WholesalerID ==id);
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/SeedData.cs b/BreweryAPI/BreweryAPI/SeedData.cs
new file mode 100644
index 0000000..b08a6c3
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/SeedData.cs
@@ -0,0 +1,149 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI
+{
+ public class SeedData
+ {
+ private readonly Context _context;
+
+ public SeedData(Context context)
+ {
+ _context = context;
+ }
+
+ public void SeedDataContext()
+ {
+ _context.Database.EnsureCreated();
+
+ if(!_context.Breweries.Any())
+ {
+ var brewery1 = new BreweryModel
+ {
+ BreweryName = "SuperBock Casa da Cerveja",
+ BreweryLocation = "Porto"
+ };
+ var brewery2 = new BreweryModel
+ {
+ BreweryName = "Sagres",
+ BreweryLocation = "Algarve"
+ };
+
+ _context.Breweries.AddRange(brewery1, brewery2);
+ _context.SaveChanges();
+ }
+
+ if(!_context.Beers.Any())
+ {
+ var beer1 = new BeerModel
+ {
+ BeerName = "SuperBock",
+ Price = 1,
+ BreweryId = 1,
+ };
+ var beer2 = new BeerModel
+ {
+ BeerName = "Abadia",
+ Price = 2,
+ BreweryId = 1,
+ };
+ var beer3 = new BeerModel
+ {
+ BeerName = "Stout",
+ Price = 1,
+ BreweryId = 1,
+ };
+ var beer4 = new BeerModel
+ {
+ BeerName = "Original",
+ Price = 1,
+ BreweryId = 2,
+ };
+ var beer5 = new BeerModel
+ {
+ BeerName = "Bohemia",
+ Price = 3,
+ BreweryId = 2,
+ };
+
+ _context.Beers.AddRange(beer1, beer2, beer3, beer4, beer5);
+ _context.SaveChanges();
+ }
+
+ if (!_context.Wholesalers.Any())
+ {
+ var wholesaler1 = new WholesalerModel
+ {
+ WholesalerName = "Solbel",
+ WholesalerLocation = "Lisboa"
+ };
+ var wholesaler2 = new WholesalerModel
+ {
+ WholesalerName = "KBE",
+ WholesalerLocation = "Algarve"
+ };
+ _context.Wholesalers.AddRange(wholesaler1, wholesaler2);
+ _context.SaveChanges();
+ }
+
+ if (!_context.BrewerySales.Any())
+ {
+ var brewerySale1 = new BrewerySalesModel
+ {
+ WholeSalerId = 1,
+ BeerId = 1,
+ Quantity = 10,
+ TotalPrice = 10
+ };
+ var brewerySale2 = new BrewerySalesModel
+ {
+ WholeSalerId = 2,
+ BeerId = 2,
+ Quantity = 10,
+ TotalPrice = 30
+ };
+ _context.BrewerySales.AddRange(brewerySale1, brewerySale2);
+ _context.SaveChanges();
+ }
+
+ if (!_context.WholesalerInventories.Any())
+ {
+ var wholesalerInventory1 = new WholesalerInventory
+ {
+ WholesalerId = 1,
+ BeerId = 1,
+ Quantity = 10,
+ };
+ var wholesalerInventory2 = new WholesalerInventory
+ {
+ WholesalerId = 2,
+ BeerId = 2,
+ Quantity = 10,
+ };
+ _context.WholesalerInventories.AddRange(wholesalerInventory1, wholesalerInventory2);
+ _context.SaveChanges();
+ }
+
+ if (!_context.WholesalerQuotes.Any())
+ {
+ var wholesalerQuote1 = new WholesalerQuoteModel
+ {
+ ClientName = "Cervejeria Lima",
+ WholesalerId = 1,
+ BeerId = 1,
+ Quantity = 10,
+ TotalPrice = 10
+ };
+ var wholesalerQuote2 = new WholesalerQuoteModel
+ {
+ ClientName = "Bar Fritos",
+ WholesalerId = 2,
+ BeerId = 2,
+ Quantity = 10,
+ TotalPrice = 30
+ };
+ _context.WholesalerQuotes.AddRange(wholesalerQuote1, wholesalerQuote2);
+ _context.SaveChanges();
+ }
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/appsettings.Development.json b/BreweryAPI/BreweryAPI/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/BreweryAPI/BreweryAPI/appsettings.json b/BreweryAPI/BreweryAPI/appsettings.json
new file mode 100644
index 0000000..2b6e344
--- /dev/null
+++ b/BreweryAPI/BreweryAPI/appsettings.json
@@ -0,0 +1,13 @@
+{
+ "ConnectionStrings": {
+ "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=BreweryDb;Trusted_connection=True;",
+ "TestConnection": "Server=(localdb)\\MSSQLLocalDB;Database=TestBreweryDb;Trusted_connection=True;",
+ },
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/BreweryAPI/BreweryMaui/App.xaml b/BreweryAPI/BreweryMaui/App.xaml
new file mode 100644
index 0000000..de7c2b1
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/App.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BreweryAPI/BreweryMaui/App.xaml.cs b/BreweryAPI/BreweryMaui/App.xaml.cs
new file mode 100644
index 0000000..3ee963e
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/App.xaml.cs
@@ -0,0 +1,12 @@
+namespace BreweryMaui
+{
+ public partial class App : Application
+ {
+ public App()
+ {
+ InitializeComponent();
+
+ MainPage = new AppShell();
+ }
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/AppShell.xaml b/BreweryAPI/BreweryMaui/AppShell.xaml
new file mode 100644
index 0000000..0ef6964
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/AppShell.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/BreweryAPI/BreweryMaui/AppShell.xaml.cs b/BreweryAPI/BreweryMaui/AppShell.xaml.cs
new file mode 100644
index 0000000..df058a1
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/AppShell.xaml.cs
@@ -0,0 +1,10 @@
+namespace BreweryMaui
+{
+ public partial class AppShell : Shell
+ {
+ public AppShell()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/BreweryMaui.csproj b/BreweryAPI/BreweryMaui/BreweryMaui.csproj
new file mode 100644
index 0000000..800160b
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/BreweryMaui.csproj
@@ -0,0 +1,73 @@
+
+
+
+
+ $(TargetFrameworks);net7.0-windows10.0.19041.0
+
+
+ Exe
+ BreweryMaui
+ true
+ true
+ enable
+
+
+ BreweryMaui
+
+
+ com.companyname.brewerymaui
+ ecd6b752-e1fe-41da-8bc6-1b60255d003e
+
+
+ 1.0
+ 1
+
+
+ 10.0.17763.0
+ 10.0.17763.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\BreweryAPI\bin\Debug\net7.0\BreweryAPI.dll
+
+
+
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+
+
diff --git a/BreweryAPI/BreweryMaui/MauiProgram.cs b/BreweryAPI/BreweryMaui/MauiProgram.cs
new file mode 100644
index 0000000..6e4439e
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/MauiProgram.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.Logging;
+
+namespace BreweryMaui
+{
+ public static class MauiProgram
+ {
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("CroissantOne-Regular.ttf", "CroissantOneRegular");
+ });
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ return builder.Build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/BreweryMainPage.xaml b/BreweryAPI/BreweryMaui/Pages/BreweryMainPage.xaml
new file mode 100644
index 0000000..a1e1be2
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/BreweryMainPage.xaml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/BreweryMainPage.xaml.cs b/BreweryAPI/BreweryMaui/Pages/BreweryMainPage.xaml.cs
new file mode 100644
index 0000000..0912e7e
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/BreweryMainPage.xaml.cs
@@ -0,0 +1,169 @@
+using BreweryAPI.DTOs;
+using BreweryMaui.Pages;
+using System.Net.Http.Json;
+
+namespace BreweryMaui;
+
+public partial class BreweryMainPage : ContentPage
+{
+ private readonly HttpClient _httpClient;
+ private readonly string _baseUrl = "https://localhost:7256";
+ public BreweryMainPage(HttpClient httpClient)
+ {
+ _httpClient = httpClient;
+
+ InitializeComponent();
+ }
+
+ private async void ResetLabels()
+ {
+ CreateBreweryNameInput.Text = "Brewery Name";
+ CreateBreweryLocationInput.Text = "BreweryLocation";
+ SelectBreweryByNameInput.Text = "Brewery Name";
+ BreweryWarningLabel.Text = string.Empty;
+
+ BreweriesListView.IsVisible = false;
+ ShowBreweriesButton.Text = "Show breweries List";
+ }
+
+ private async void OnShowBreweries(object sender, EventArgs e)
+ {
+ List breweries = await GetAllBreweries();
+
+ if (BreweriesListView.IsVisible == false)
+ {
+ BreweriesListView.IsVisible = true;
+ ShowBreweriesButton.Text = "Hide breweries List";
+ }
+ else
+ {
+ BreweriesListView.IsVisible = false;
+ ShowBreweriesButton.Text = "Show breweries List";
+ }
+ BreweriesListView.ItemsSource = breweries;
+ }
+
+ private async Task> GetAllBreweries()
+ {
+ List breweries = null;
+
+ try
+ {
+ breweries = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/Brewery");
+ }
+ catch
+ {
+ BreweryWarningLabel.Text = "Error ocorred! Check connection to BreweryAPI!";
+ }
+
+ return breweries;
+ }
+
+ private async Task BreweryExists(string breweryName)
+ {
+ bool breweryExists = false;
+ var breweries = await GetAllBreweries();
+
+ if(breweries != null)
+ {
+ foreach (var brewery in breweries)
+ {
+ if (breweryName.Trim().ToLower() == brewery.BreweryName.Trim().ToLower())
+ {
+ breweryExists = true;
+ }
+ }
+ }
+
+ return breweryExists;
+ }
+
+ private async Task SelectActiveUserBrewery(string breweryName)
+ {
+ BreweryDTO activeBrewery = null;
+
+ var breweries = await GetAllBreweries();
+
+ foreach (var brewery in breweries)
+ {
+ if (breweryName.Trim().ToLower() == brewery.BreweryName.Trim().ToLower())
+ {
+ activeBrewery = brewery;
+ }
+ }
+
+ return activeBrewery;
+ }
+
+ private async void OnBreweryCreate(object sender, EventArgs e)
+ {
+ string breweryName = CreateBreweryNameInput.Text;
+ string breweryLocation = CreateBreweryLocationInput.Text;
+
+ bool breweryExists = await BreweryExists(breweryName);
+
+ if (breweryExists == false)
+ {
+ if (!String.IsNullOrEmpty(breweryLocation) && !String.IsNullOrEmpty(breweryName))
+ {
+ try
+ {
+ var breweryToCreate = new BreweryDTO { BreweryName = breweryName, BreweryLocation = breweryLocation };
+ await _httpClient.PostAsJsonAsync(_baseUrl + "/api/Brewery", breweryToCreate);
+
+ Thread.Sleep(1000);
+ BreweryWarningLabel.Text = "Brewery succesfuly registered";
+
+
+ BreweryDTO activeUserBrewery = await SelectActiveUserBrewery(breweryName);
+ GoToBreweryUserPage(activeUserBrewery);
+ }
+ catch
+ {
+ BreweryWarningLabel.Text = "Error ocorred while registering new brewery! Check connection to BreweryAPI!";
+ }
+
+ }
+ else
+ {
+ BreweryWarningLabel.Text = "Brewery name and brewery location cannot be empty!";
+ }
+ }
+ else
+ {
+ BreweryWarningLabel.Text = "Failed to register new brewery. Brewery name already exists!";
+ }
+ }
+
+ private async void OnBrewerySelect(object sender, EventArgs e)
+ {
+ string breweryName = SelectBreweryByNameInput.Text;
+
+ bool breweryExists = await BreweryExists(breweryName);
+
+ if (breweryExists == false)
+ {
+ BreweryWarningLabel.Text = "Failed to select brewery. Brewery name does not exist or bad connection to BreweryAPI!";
+ }
+ else
+ {
+ try
+ {
+ BreweryWarningLabel.Text = "Brewery succesfuly selected";
+
+ BreweryDTO activeUserBrewery = await SelectActiveUserBrewery(breweryName);
+ GoToBreweryUserPage(activeUserBrewery);
+ }
+ catch
+ {
+ BreweryWarningLabel.Text = "Failed to select a brewery. Check connection to BreweryAPI!";
+ }
+ }
+ }
+
+ private void GoToBreweryUserPage(BreweryDTO activeUserBrewery)
+ {
+ Navigation.PushAsync(new BreweryUserPage(activeUserBrewery, _httpClient));
+ ResetLabels();
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/BreweryUserPage.xaml b/BreweryAPI/BreweryMaui/Pages/BreweryUserPage.xaml
new file mode 100644
index 0000000..f217108
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/BreweryUserPage.xaml
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/BreweryUserPage.xaml.cs b/BreweryAPI/BreweryMaui/Pages/BreweryUserPage.xaml.cs
new file mode 100644
index 0000000..49817ad
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/BreweryUserPage.xaml.cs
@@ -0,0 +1,287 @@
+using BreweryAPI.DTOs;
+using System.Net.Http.Json;
+
+namespace BreweryMaui.Pages;
+
+public partial class BreweryUserPage : ContentPage
+{
+ private readonly HttpClient _httpClient;
+ private BreweryDTO _activeUserBrewery;
+ private readonly string _baseUrl = "https://localhost:7256";
+
+
+ public BreweryUserPage(BreweryDTO activeUserBrewery, HttpClient httpClient)
+ {
+ InitializeComponent();
+ _httpClient = httpClient;
+ _activeUserBrewery = activeUserBrewery;
+
+ DefineHeadlineBreweryLabels();
+ }
+
+ public async void DefineHeadlineBreweryLabels()
+ {
+ tagBreweryName.Text = "Brewery Name: " + _activeUserBrewery.BreweryName;
+ tagBreweryLocation.Text = "Brewery Location: " + _activeUserBrewery.BreweryLocation;
+ }
+
+ public async void OnBreweryUpdate(object sender, EventArgs e)
+ {
+ ResetCreateBeerVisualElements();
+ ResetDeleteBreweryVisualElements();
+ ResetShowBeersVisualElements();
+
+ if (updateBreweryBtn.Text == "Update Brewery")
+ {
+ UpdateBreweryNameInput.IsVisible = true;
+ UpdateBreweryLocationInput.IsVisible = true;
+ updateBreweryBtn.Text = "Submit to update";
+ }
+ else if(updateBreweryBtn.Text == "Submit to update")
+ {
+ if(!String.IsNullOrEmpty(UpdateBreweryNameInput.Text) && !String.IsNullOrEmpty(UpdateBreweryLocationInput.Text))
+ {
+ int breweryId = _activeUserBrewery.BreweryId;
+ BreweryDTO breweryToUpdate = await ConstructBreweryToUpdate();
+
+ await _httpClient.PutAsJsonAsync(_baseUrl + $"/api/Brewery/{breweryId}", breweryToUpdate);
+
+ ResetUpdateBreweryVisualElements();
+
+ _activeUserBrewery = breweryToUpdate;
+ DefineHeadlineBreweryLabels();
+ BreweryWarningLabel.Text = null;
+ }
+ else
+ {
+ BreweryWarningLabel.Text = "Failed to update brewery. Check connection to breweryAPI";
+ }
+ }
+ }
+
+ public async void OnBreweryDelete(object sender, EventArgs e)
+ {
+ ResetUpdateBreweryVisualElements();
+ ResetCreateBeerVisualElements();
+ ResetShowBeersVisualElements();
+
+
+ if (deleteBreweryBtn.IsVisible == true)
+ {
+ deleteBreweryBtn.IsVisible = false;
+ deleteBreweryQuestion.IsVisible = true;
+ deleteBreweryYesBtn.IsVisible = true;
+ deleteBreweryNoBtn.IsVisible = true;
+ }
+ }
+
+ public async void OnBreweryAbortDelete(object sender, EventArgs e)
+ {
+ ResetDeleteBreweryVisualElements();
+ }
+
+ public async void OnBreweryConfirmDelete(object sender, EventArgs e)
+ {
+ int breweryId = _activeUserBrewery.BreweryId;
+
+ try
+ {
+ await _httpClient.DeleteAsync(_baseUrl + $"/api/Brewery/{breweryId}");
+ RetreatToMainBreweryPage();
+
+ ResetDeleteBreweryVisualElements();
+ }
+ catch
+ {
+ BreweryWarningLabel.Text = "Unable to delete brewery.Check connection to breweryAPI!";
+ }
+ }
+
+ public async void OnShowBeers(object sender, EventArgs e)
+ {
+ if(showBeers.Text == "Show Beers")
+ {
+ ResetUpdateBreweryVisualElements();
+ ResetDeleteBreweryVisualElements();
+
+ showBeers.Text = "Hide Beers";
+ beersListHeader.IsVisible = true;
+
+ beersListData.ItemsSource = await GetBeersByBreweryId();
+ beersListData.IsVisible = true;
+ }
+ else if(showBeers.Text == "Hide Beers")
+ {
+ ResetCreateBeerVisualElements();
+ ResetShowBeersVisualElements();
+ }
+ }
+
+ private async void OnEntryChanged(object sender, EventArgs e)
+ {
+ BeerDTO beerToUpdate = await GetBeerByContext(sender);
+ decimal price;
+ string priceString = beerToUpdate.Price.ToString();
+ bool isDecimal = decimal.TryParse(priceString, out price);
+
+
+ if(!string.IsNullOrEmpty(beerToUpdate.BeerName) && isDecimal == true && price > 0)
+ {
+ int beerId = beerToUpdate.BeerId;
+
+ await _httpClient.PutAsJsonAsync(_baseUrl + $"/api/Beer/{beerId}", beerToUpdate);
+ BreweryWarningLabel.Text = null;
+ }
+ else
+ {
+ BreweryWarningLabel.Text = "To update record beer name can´t be empty and price must be a positive number!";
+ }
+ }
+
+ private async void OnCreateBeer(object sender, EventArgs e)
+ {
+ if(CreateBeerBtn.Text == "Create a new beer")
+ {
+ ResetUpdateBreweryVisualElements();
+ ResetDeleteBreweryVisualElements();
+
+ CreateBeerBtn.Text = "Confirm";
+
+ BeerNameInput.IsVisible = true;
+ BeerPriceInput.IsVisible = true;
+ }
+ else if(CreateBeerBtn.Text == "Confirm")
+ {
+ string beerName = BeerNameInput.Text;
+ decimal price;
+ bool isDecimal = decimal.TryParse(BeerPriceInput.Text, out price);
+
+ if (!string.IsNullOrEmpty(beerName) && !string.IsNullOrEmpty(BeerPriceInput.Text) && isDecimal == true)
+ {
+ var beerToCreate = new BeerDTO {BeerName = beerName, Price = price, BreweryId = _activeUserBrewery.BreweryId };
+ await _httpClient.PostAsJsonAsync(_baseUrl + "/api/Beer", beerToCreate);
+
+ ResetCreateBeerVisualElements();
+
+ if (showBeers.Text == "Hide Beers")
+ {
+ beersListData.ItemsSource = await GetBeersByBreweryId();
+ }
+ }
+ else
+ {
+ BreweryWarningLabel.Text = "Beer name and beer price must not be empty. And beer price must be numeric!";
+ }
+ }
+ }
+
+ private async void OnDeleteBeer(object sender, EventArgs e)
+ {
+ BeerDTO beerToDelete = await GetBeerByContext(sender);
+ int beerId = beerToDelete.BeerId;
+
+ await _httpClient.DeleteAsync(_baseUrl + $"/api/Beer/{beerId}");
+ beersListData.ItemsSource = await GetBeersByBreweryId();
+ }
+
+ private async Task> GetBeersByBreweryId()
+ {
+ List beersByBrewery = null;
+
+ try
+ {
+ int breweryId = _activeUserBrewery.BreweryId;
+ beersByBrewery = await _httpClient.GetFromJsonAsync>(_baseUrl + $"/api/Beer/{breweryId}");
+ }
+ catch
+ {
+ BreweryWarningLabel.Text = "Error getting beers list. Check connection to breweryAPI!";
+ }
+
+ return beersByBrewery;
+ }
+
+ private void RetreatToMainBreweryPage()
+ {
+ BreweryWarningLabel.Text = null;
+ Navigation.PushAsync(new BreweryMainPage(_httpClient));
+ }
+
+ private void ResetUpdateBreweryVisualElements()
+ {
+ BreweryWarningLabel.Text = null;
+ updateBreweryBtn.Text = "Update Brewery";
+ UpdateBreweryNameInput.IsVisible = false;
+ UpdateBreweryNameInput.Text = "Brewery Name";
+ UpdateBreweryLocationInput.IsVisible = false;
+ UpdateBreweryLocationInput.Text = "Brewery Location";
+ }
+
+ private void ResetDeleteBreweryVisualElements()
+ {
+ BreweryWarningLabel.Text = null;
+ deleteBreweryBtn.IsVisible = true;
+ deleteBreweryQuestion.IsVisible = false;
+ deleteBreweryYesBtn.IsVisible = false;
+ deleteBreweryNoBtn.IsVisible = false;
+ }
+
+ private void ResetCreateBeerVisualElements()
+ {
+ BreweryWarningLabel.Text = null;
+ CreateBeerBtn.Text = "Create a new beer";
+ BeerNameInput.IsVisible = false;
+ BeerNameInput.Text = "New Beer Name";
+ BeerPriceInput.IsVisible = false;
+ BeerPriceInput.Text = "New beer Price";
+ }
+
+ private void ResetShowBeersVisualElements()
+ {
+ BreweryWarningLabel.Text = null;
+ showBeers.Text = "Show Beers";
+ beersListHeader.IsVisible = false;
+ beersListData.IsVisible = false;
+ }
+
+ private async void OnLogOut(object sender, EventArgs e)
+ {
+ BreweryWarningLabel.Text = null;
+ Navigation.PushAsync(new MainPage());
+ }
+
+ public async Task ConstructBreweryToUpdate()
+ {
+ BreweryDTO breweryToUpdate = new BreweryDTO
+ {
+ BreweryId = _activeUserBrewery.BreweryId,
+ BreweryName = UpdateBreweryNameInput.Text,
+ BreweryLocation = UpdateBreweryLocationInput.Text
+ };
+
+ return breweryToUpdate;
+ }
+
+ private async Task GetBeerByContext(object sender)
+ {
+ BeerDTO beerToUpdate = null;
+
+ if (sender is Entry entry)
+ {
+ if (entry.BindingContext is BeerDTO beer)
+ {
+ beerToUpdate = beer;
+ }
+ }
+
+ if (sender is Button button)
+ {
+ if (button.BindingContext is BeerDTO beer)
+ {
+ beerToUpdate = beer;
+ }
+ }
+
+ return beerToUpdate;
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/MainPage.xaml b/BreweryAPI/BreweryMaui/Pages/MainPage.xaml
new file mode 100644
index 0000000..3715c69
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/MainPage.xaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BreweryAPI/BreweryMaui/Pages/MainPage.xaml.cs b/BreweryAPI/BreweryMaui/Pages/MainPage.xaml.cs
new file mode 100644
index 0000000..d93107a
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/MainPage.xaml.cs
@@ -0,0 +1,23 @@
+using BreweryMaui.Pages;
+
+namespace BreweryMaui
+{
+ public partial class MainPage : ContentPage
+ {
+ private readonly HttpClient _httpClient = new HttpClient();
+ public MainPage()
+ {
+ InitializeComponent();
+ }
+
+ private void OnBreweryPage(object sender, EventArgs e)
+ {
+ Navigation.PushAsync(new BreweryMainPage(_httpClient));
+ }
+
+ private void OnWholesalerPage(object sender, EventArgs e)
+ {
+ Navigation.PushAsync(new WholesalerMainPage(_httpClient));
+ }
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/WholesalerMainPage.xaml b/BreweryAPI/BreweryMaui/Pages/WholesalerMainPage.xaml
new file mode 100644
index 0000000..010a0af
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/WholesalerMainPage.xaml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/WholesalerMainPage.xaml.cs b/BreweryAPI/BreweryMaui/Pages/WholesalerMainPage.xaml.cs
new file mode 100644
index 0000000..4f6b58f
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/WholesalerMainPage.xaml.cs
@@ -0,0 +1,167 @@
+using BreweryAPI.DTOs;
+using System.Net.Http.Json;
+
+namespace BreweryMaui.Pages;
+
+public partial class WholesalerMainPage : ContentPage
+{
+ private readonly HttpClient _httpClient;
+ private readonly string _baseUrl = "https://localhost:7256";
+
+ public WholesalerMainPage(HttpClient httpClient)
+ {
+ _httpClient = httpClient;
+ InitializeComponent();
+ }
+
+ private async void OnWholesalerCreate(object sender, EventArgs e)
+ {
+ string wholesalerName = CreateWholesalerNameInput.Text;
+ string wholesalerLocation = CreateWholesalerLocationInput.Text;
+
+ bool breweryExists = await WholesalerExists(wholesalerName);
+
+ if (breweryExists == false)
+ {
+ if (!String.IsNullOrEmpty(wholesalerLocation) && !String.IsNullOrEmpty(wholesalerName))
+ {
+ try
+ {
+ var breweryToCreate = new WholesalerDTO { WholesalerName = wholesalerName, WholesalerLocation = wholesalerLocation };
+ await _httpClient.PostAsJsonAsync(_baseUrl + "/api/Wholesaler", breweryToCreate);
+
+ Thread.Sleep(1000);
+ WholesalerWarningLabel.Text = "Wholesaler succesfuly registered";
+
+ WholesalerDTO activeUserWholesaler = await SelectActiveUserWholesaler(wholesalerName);
+ GoToWholesalerUserPage(activeUserWholesaler);
+ }
+ catch
+ {
+ WholesalerWarningLabel.Text = "Error ocorred while registering new brewery! Check connection to WholesalerAPI!";
+ }
+ }
+ else
+ {
+ WholesalerWarningLabel.Text = "Wholesaler location cannot be empty!";
+ }
+ }
+ else
+ {
+ WholesalerWarningLabel.Text = "Failed to register new brewery. Wholesaler name already exists!";
+ }
+ }
+
+ private async void OnWholesalerSelect(object sender, EventArgs e)
+ {
+ string breweryName = SelectWholesalerByNameInput.Text;
+
+ bool breweryExists = await WholesalerExists(breweryName);
+
+ if (breweryExists == false)
+ {
+ WholesalerWarningLabel.Text = "Failed to select brewery. Wholesaler name does not exist or bad connection to WholesalerAPI!";
+ }
+ else
+ {
+ try
+ {
+ WholesalerWarningLabel.Text = "Wholesaler succesfuly selected";
+
+ WholesalerDTO activeUserWholesaler = await SelectActiveUserWholesaler(breweryName);
+ GoToWholesalerUserPage(activeUserWholesaler);
+ }
+ catch
+ {
+ WholesalerWarningLabel.Text = "Failed to select a brewery. Check connection to WholesalerAPI!";
+ }
+ }
+ }
+
+ private async void OnShowWholesalers(object sender, EventArgs e)
+ {
+ List breweries = await GetAllWholesalers();
+
+ if (WholesalersListView.IsVisible == false)
+ {
+ WholesalersListView.IsVisible = true;
+ ShowWholesalersButton.Text = "Hide wholesalers List";
+ }
+ else
+ {
+ WholesalersListView.IsVisible = false;
+ ShowWholesalersButton.Text = "Show wholesalers List";
+ }
+
+ WholesalersListView.ItemsSource = breweries;
+ }
+
+ private async Task> GetAllWholesalers()
+ {
+ List wholesalers = null;
+
+ try
+ {
+ wholesalers = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/Wholesaler");
+ }
+ catch
+ {
+ WholesalerWarningLabel.Text = "Error ocorred! Check connection to WholesalerAPI!";
+ }
+
+ return wholesalers;
+ }
+
+ private async Task WholesalerExists(string wholesalerName)
+ {
+ bool wholesalerExists = false;
+ var wholesalers = await GetAllWholesalers();
+
+ if (wholesalers != null)
+ {
+ foreach (var wholesaler in wholesalers)
+ {
+ if (wholesalerName.Trim().ToLower() == wholesaler.WholesalerName.Trim().ToLower())
+ {
+ wholesalerExists = true;
+ }
+ }
+ }
+
+ return wholesalerExists;
+ }
+
+ private async Task SelectActiveUserWholesaler(string breweryName)
+ {
+ WholesalerDTO activeWholesaler = null;
+
+ var breweries = await GetAllWholesalers();
+
+ foreach (var brewery in breweries)
+ {
+ if (breweryName.Trim().ToLower() == brewery.WholesalerName.Trim().ToLower())
+ {
+ activeWholesaler = brewery;
+ }
+ }
+
+ return activeWholesaler;
+ }
+
+ private async void ResetLabels()
+ {
+ CreateWholesalerNameInput.Text = "Wholesaler Name";
+ CreateWholesalerLocationInput.Text = "WholesalerLocation";
+ SelectWholesalerByNameInput.Text = "Wholesaler Name";
+ WholesalerWarningLabel.Text = string.Empty;
+
+ WholesalersListView.IsVisible = false;
+ ShowWholesalersButton.Text = "Show Wholesalers List";
+ }
+
+ private void GoToWholesalerUserPage(WholesalerDTO activeUserWholesaler)
+ {
+ Navigation.PushAsync(new WholesallerUserPage(activeUserWholesaler, _httpClient));
+ ResetLabels();
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/WholesallerUserPage.xaml b/BreweryAPI/BreweryMaui/Pages/WholesallerUserPage.xaml
new file mode 100644
index 0000000..452e8ec
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/WholesallerUserPage.xaml
@@ -0,0 +1,399 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Pages/WholesallerUserPage.xaml.cs b/BreweryAPI/BreweryMaui/Pages/WholesallerUserPage.xaml.cs
new file mode 100644
index 0000000..7c95352
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Pages/WholesallerUserPage.xaml.cs
@@ -0,0 +1,538 @@
+using BreweryAPI.DTOs;
+using System.Net.Http.Json;
+
+namespace BreweryMaui.Pages;
+
+public partial class WholesallerUserPage : ContentPage
+{
+ private readonly HttpClient _httpClient;
+ private WholesalerDTO _activeWholesalerUser;
+ private readonly string _baseUrl = "https://localhost:7256";
+ BrewerySalesDTO saleTobeMade = new BrewerySalesDTO();
+ WholesalerQuoteDTO quoteToCreate = new WholesalerQuoteDTO();
+ BeerDTO beerToOrder;
+
+ public WholesallerUserPage(WholesalerDTO activeWholesalerUser, HttpClient httpClient)
+ {
+ _httpClient = httpClient;
+ _activeWholesalerUser = activeWholesalerUser;
+ InitializeComponent();
+
+ tagWholesalerName.Text = "Wholesaler: " + _activeWholesalerUser.WholesalerName;
+ tagWholesalerLocation.Text = "Location: " + _activeWholesalerUser.WholesalerLocation;
+ }
+
+ //UpdateWholesaler
+ private async void OnUpdateWholesaler(object sender, EventArgs e)
+ {
+ if(updateWholesaleryBtn.Text == "Update Wholesaler")
+ {
+ UpdateWholesalerNameEntry.IsVisible = true;
+ UpdateWholesalerLocationEntry.IsVisible = true;
+ updateWholesaleryBtn.Text = "Confirm Update";
+ }
+ else if(updateWholesaleryBtn.Text == "Confirm Update")
+ {
+ _activeWholesalerUser.WholesalerName = UpdateWholesalerNameEntry.Text;
+ _activeWholesalerUser.WholesalerLocation = UpdateWholesalerLocationEntry.Text;
+
+ if(String.IsNullOrEmpty(_activeWholesalerUser.WholesalerName) || String.IsNullOrEmpty(_activeWholesalerUser.WholesalerName))
+ {
+ WholesalerWarningLabel.Text = "The name or location of the wholesaler can't be empty!";
+ }
+ else
+ {
+ int wholesalerId = _activeWholesalerUser.WholesalerID;
+ await _httpClient.PutAsJsonAsync(_baseUrl + $"/api/Wholesaler/{wholesalerId}", _activeWholesalerUser);
+
+ WholesalerWarningLabel.Text = null;
+ ResetUpdateWholesalerButtonVisualElements();
+ ResetTags();
+ }
+ }
+ }
+
+ //DeleteWholesaler
+ private async void OnDeleteWholesaler(object sender, EventArgs e)
+ {
+ deleteWholesalerBtn.IsVisible = false;
+ deleteWholesalerQuestionLabel.IsVisible = true;
+ deleteWholesalerYesBtn.IsVisible = true;
+ deleteWholesalerNoBtn.IsVisible = true;
+ }
+
+ private async void OnWholesalerConfirmDelete(object sender, EventArgs e)
+ {
+ ResetDeleteWholesalerButtonVisualElements();
+
+ int wholesalerId = _activeWholesalerUser.WholesalerID;
+ _httpClient.DeleteAsync(_baseUrl + $"/api/Wholesaler/{wholesalerId}");
+
+ RetreatToMainWholesalerPage();
+ }
+
+ private async void OnWholesalerAbortDelete(object sender, EventArgs e)
+ {
+ ResetDeleteWholesalerButtonVisualElements();
+ }
+
+ //Order Shipment of Beer
+ private async void OnShowBeersToOrder(object sender, EventArgs e)
+ {
+ ResetUpdateWholesalerButtonVisualElements();
+ ResetDeleteWholesalerButtonVisualElements();
+ ResetShowBeerShipmentButtonVisualElements();
+ ResetShowInventoryButtonVisualElements();
+ ResetShowQuotesButtonVisualElements();
+ ResetCreateQuoteButtonVisualElements();
+
+
+ if (OrderBeerShipment.Text == "Order Shipment of Beer")
+ {
+ OrderBeerShipment.Text = "Cancel Shipment of Beer";
+ List allBeers = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/Beer");
+
+ AllBeersListHeader.IsVisible = true;
+ AllBeersListData.IsVisible = true;
+ AllBeersListData.ItemsSource = allBeers;
+ }
+ else if (OrderBeerShipment.Text == "Cancel Shipment of Beer")
+ {
+ ResetOrderShipmentButtonVisualElements();
+ }
+ }
+
+ private async void OnOrderBeer(object sender, EventArgs e)
+ {
+ beerToOrder = await GetBeerByContext(sender);
+
+ saleTobeMade.BeerId = beerToOrder.BeerId;
+ saleTobeMade.WholeSalerId = _activeWholesalerUser.WholesalerID;
+
+ BeerIdOfBeerToOrder.Text = (beerToOrder.BeerId).ToString();
+ WolesalerIdOfOrder.Text = (_activeWholesalerUser.WholesalerID).ToString();
+ QuantityOfOrder.Text = "Quantity?";
+ TotalPriceOfOrder.Text = "?";
+
+ ShipmentToCreateGrid.IsVisible = true;
+ }
+
+ private async void AdjustBeerTotalPrice(object sender, EventArgs e)
+ {
+ int quantity;
+ bool quantityIsInt = Int32.TryParse(QuantityOfOrder.Text, out quantity);
+
+ if (quantityIsInt == true && quantity > 0)
+ {
+ decimal totalPrice = (decimal)quantity * beerToOrder.Price;
+ TotalPriceOfOrder.Text = totalPrice.ToString();
+
+ saleTobeMade.Quantity = quantity;
+ saleTobeMade.TotalPrice = totalPrice; //For some reason, the app does not start if i try to put a decimal to TotalPrice. Its very weird.
+
+ WholesalerWarningLabel.Text = null;
+ ConfirmOrderButton.IsEnabled = true;
+ }
+ else
+ {
+ WholesalerWarningLabel.Text = "Quantity must be a numeric value!";
+ ConfirmOrderButton.IsEnabled = false;
+ }
+ }
+
+ private async void OnConfirmOrder(object sender, EventArgs e)
+ {
+ await _httpClient.PostAsJsonAsync(_baseUrl + "/api/BrewerySales", saleTobeMade);
+
+ ShipmentToCreateGrid.IsVisible = false;
+ }
+
+ private async void OnCancelOrder(object sender, EventArgs e)
+ {
+ ShipmentToCreateGrid.IsVisible = false;
+ }
+
+ //Show Beer Shipments
+ private async void OnShowBeersShipments(object sender, EventArgs e)
+ {
+ ResetUpdateWholesalerButtonVisualElements();
+ ResetDeleteWholesalerButtonVisualElements();
+ ResetOrderShipmentButtonVisualElements();
+ ResetShowInventoryButtonVisualElements();
+ ResetShowQuotesButtonVisualElements();
+ ResetCreateQuoteButtonVisualElements();
+
+ List allOrders;
+ List orders;
+
+ if (ShowBeerShipments.Text == "Show Beer Shipments")
+ {
+ ShowBeerShipments.Text = "Hide Beer Shipments";
+ BeerOrdersListHeader.IsVisible = true;
+ BeerOrdersListData.IsVisible = true;
+
+ allOrders = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/BrewerySales");
+ orders = allOrders.Where(b => b.WholeSalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ BeerOrdersListData.ItemsSource = orders;
+ }
+ else if (ShowBeerShipments.Text == "Hide Beer Shipments")
+ {
+ ResetShowBeerShipmentButtonVisualElements();
+ allOrders = null;
+ orders = null;
+ }
+ }
+
+ //Show Inventory
+ private async void OnShowInventory(object sender, EventArgs e)
+ {
+ ResetUpdateWholesalerButtonVisualElements();
+ ResetDeleteWholesalerButtonVisualElements();
+ ResetOrderShipmentButtonVisualElements();
+ ResetShowBeerShipmentButtonVisualElements();
+ ResetShowQuotesButtonVisualElements();
+ ResetCreateQuoteButtonVisualElements();
+
+ List allInventories;
+ List inventory;
+
+ if (ShowInventoryBtn.Text == "Show Inventory")
+ {
+ ShowInventoryBtn.Text = "Hide Inventory";
+ WholesalerInventoryHeaderGrid.IsVisible = true;
+ WholesalerInventoryDataGrid.IsVisible = true;
+
+ allInventories = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/WholesalerInventory");
+ inventory = allInventories.Where(i => i.WholesalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ WholesalerInventoryDataGrid.ItemsSource = inventory;
+ }
+ else if (ShowInventoryBtn.Text == "Hide Inventory")
+ {
+ ResetShowInventoryButtonVisualElements();
+
+ allInventories = null;
+ inventory = null;
+ }
+ }
+
+ private async void OnInventoryRecordDelete(object sender, EventArgs e)
+ {
+ List allInventories;
+ List inventory;
+
+ WholesalerInventoryDTO inventoryRecordToDelete = await GetInventoryRecordByContext(sender);
+
+ int inventoryRecordIdToDelete = inventoryRecordToDelete.ItemId;
+
+ await _httpClient.DeleteAsync(_baseUrl + $"/api/WholesalerInventory/{inventoryRecordIdToDelete}");
+
+ allInventories = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/WholesalerInventory");
+ inventory = allInventories.Where(i => i.WholesalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ WholesalerInventoryDataGrid.ItemsSource = inventory;
+ }
+
+ private async void OnUpdateInventoryQuantity(object sender, EventArgs e)
+ {
+ int quantity;
+
+ WholesalerInventoryDTO inventoryRecordToUpdate = await GetInventoryRecordByContext(sender);
+ int recordId = inventoryRecordToUpdate.ItemId;
+
+ if (inventoryRecordToUpdate.Quantity > 0)
+ {
+ await _httpClient.PutAsJsonAsync(_baseUrl + $"/api/WholesalerInventory/{recordId}", inventoryRecordToUpdate);
+ WholesalerWarningLabel.Text = "";
+ }
+ else
+ {
+ WholesalerWarningLabel.Text = $"To update the item {recordId}, quantity must be a positive numeric value!";
+ }
+ }
+
+ //Show Quotes
+ private async void OnShowQuotes(object sender, EventArgs e)
+ {
+ ResetUpdateWholesalerButtonVisualElements();
+ ResetDeleteWholesalerButtonVisualElements();
+ ResetShowBeerShipmentButtonVisualElements();
+ ResetOrderShipmentButtonVisualElements();
+ ResetShowInventoryButtonVisualElements();
+ ResetCreateQuoteButtonVisualElements();
+
+ if (ShowQuotesBtn.Text == "Show Quotes")
+ {
+ ShowQuotesBtn.Text = "Hide Quotes";
+
+ List allQuotes = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/WholesalerQuote");
+ List quotes = allQuotes.Where(q => q.WholesalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ QuoteDataGrid.ItemsSource = quotes;
+
+ QuoteHeaderGrid.IsVisible = true;
+ QuoteDataGrid.IsVisible = true;
+ }
+ else if(ShowQuotesBtn.Text == "Hide Quotes")
+ {
+ ResetShowQuotesButtonVisualElements();
+ }
+ }
+
+ private async void OnQuoteDelete(object sender, EventArgs e)
+ {
+ WholesalerQuoteDTO quoteToDelete = await GetQuoteByContext(sender);
+
+ int quoteId = quoteToDelete.QuoteId;
+ await _httpClient.DeleteAsync(_baseUrl + $"/api/WholesalerQuote/{quoteId}");
+
+ List allQuotes = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/WholesalerQuote");
+ List quotes = allQuotes.Where(q => q.WholesalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ QuoteDataGrid.ItemsSource = quotes;
+ }
+
+ //Create Quote
+ private async void OnCreateQuote(object sender, EventArgs e)
+ {
+ ResetUpdateWholesalerButtonVisualElements();
+ ResetDeleteWholesalerButtonVisualElements();
+ ResetOrderShipmentButtonVisualElements();
+ ResetShowBeerShipmentButtonVisualElements();
+ ResetShowInventoryButtonVisualElements();
+ ResetShowQuotesButtonVisualElements();
+
+ List allInventories;
+ List inventory;
+
+ if (CreateQuoteBtn.Text == "Create Quote")
+ {
+ CreateQuoteBtn.Text = "Cancel creating Quote";
+
+ WholesalerInventoryHeaderGrid.IsVisible = true;
+ InventoryForQuoteDataGrid.IsVisible = true;
+
+ allInventories = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/WholesalerInventory");
+ inventory = allInventories.Where(i => i.WholesalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ InventoryForQuoteDataGrid.ItemsSource = inventory;
+ }
+ else if(CreateQuoteBtn.Text == "Cancel creating Quote")
+ {
+ ResetCreateQuoteButtonVisualElements();
+ }
+ }
+
+ private async void OnInventoryRecordSelect(object sender, EventArgs e)
+ {
+ QuoteToCreateGrid.IsVisible = true;
+
+ WholesalerInventoryDTO inventoryRecordSelected = await GetInventoryRecordByContext(sender);
+ int beedIdSelected = inventoryRecordSelected.BeerId;
+ BeerDTO beerSelected = await _httpClient.GetFromJsonAsync(_baseUrl + $"/api/Beer/singular/{beedIdSelected}");
+
+ quoteToCreate.WholesalerId = _activeWholesalerUser.WholesalerID;
+ quoteToCreate.BeerId = beedIdSelected;
+ quoteToCreate.Quantity = 1;
+ quoteToCreate.TotalPrice = beerSelected.Price;
+
+ ClientNameEntry.Text = "";
+ WholesalerIdLabel.Text = _activeWholesalerUser.WholesalerID.ToString();
+ BeerIdLabel.Text = beerSelected.BeerId.ToString();
+ QuantityEntry.Text = "1";
+ TotalPriceLabel.Text = beerSelected.Price.ToString();
+ }
+
+ private async void OnCancelQuote(object sender, EventArgs e)
+ {
+ QuoteToCreateGrid.IsVisible = false;
+
+ WholesalerIdLabel.Text = "";
+ BeerIdLabel.Text = "";
+ TotalPriceLabel.Text = "";
+ }
+
+ private async void OnConfirmQuote(object sender, EventArgs e)
+ {
+ int quantity;
+ List allInventories;
+ List inventory;
+
+ bool quantityIsInt = Int32.TryParse(QuantityEntry.Text, out quantity);
+ decimal beerPrice = quoteToCreate.TotalPrice;
+
+
+ if(!String.IsNullOrEmpty(ClientNameEntry.Text) && quantityIsInt == true && quantity > 0)
+ {
+ quoteToCreate.ClientName = ClientNameEntry.Text;
+ quoteToCreate.Quantity = quantity;
+ quoteToCreate.TotalPrice = (decimal)quantity * beerPrice;
+
+ await _httpClient.PostAsJsonAsync(_baseUrl + "/api/WholesalerQuote", quoteToCreate);
+
+ QuoteToCreateGrid.IsVisible = false;
+
+ allInventories = await _httpClient.GetFromJsonAsync>(_baseUrl + "/api/WholesalerInventory");
+ inventory = allInventories.Where(i => i.WholesalerId == _activeWholesalerUser.WholesalerID).ToList();
+
+ InventoryForQuoteDataGrid.ItemsSource = inventory;
+
+ WholesalerWarningLabel.Text = "";
+ }
+ else
+ {
+ WholesalerWarningLabel.Text = "Client name must not be empty and quantity must be a positive number!";
+ }
+ }
+
+ //Visual elements reset methods
+ private void ResetUpdateWholesalerButtonVisualElements()
+ {
+ UpdateWholesalerNameEntry.IsVisible = false;
+ UpdateWholesalerLocationEntry.IsVisible = false;
+ updateWholesaleryBtn.Text = "Update Wholesaler";
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetDeleteWholesalerButtonVisualElements()
+ {
+ deleteWholesalerBtn.IsVisible = true;
+ deleteWholesalerQuestionLabel.IsVisible = false;
+ deleteWholesalerYesBtn.IsVisible = false;
+ deleteWholesalerNoBtn.IsVisible = false;
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetOrderShipmentButtonVisualElements()
+ {
+ OrderBeerShipment.Text = "Order Shipment of Beer";
+ AllBeersListHeader.IsVisible = false;
+ AllBeersListData.IsVisible = false;
+ ShipmentToCreateGrid.IsVisible = false;
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetShowBeerShipmentButtonVisualElements()
+ {
+ ShowBeerShipments.Text = "Show Beer Shipments";
+ BeerOrdersListHeader.IsVisible = false;
+ BeerOrdersListData.IsVisible = false;
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetShowInventoryButtonVisualElements()
+ {
+ ShowInventoryBtn.Text = "Show Inventory";
+ WholesalerInventoryHeaderGrid.IsVisible = false;
+ WholesalerInventoryDataGrid.IsVisible = false;
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetShowQuotesButtonVisualElements()
+ {
+ ShowQuotesBtn.Text = "Show Quotes";
+ QuoteHeaderGrid.IsVisible = false;
+ QuoteDataGrid.IsVisible = false;
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetCreateQuoteButtonVisualElements()
+ {
+ CreateQuoteBtn.Text = "Create Quote";
+ WholesalerInventoryHeaderGrid.IsVisible = false;
+ InventoryForQuoteDataGrid.IsVisible = false;
+ QuoteToCreateGrid.IsVisible= false;
+ WholesalerWarningLabel.Text = null;
+ }
+
+ private void ResetTags()
+ {
+ tagWholesalerName.Text = "Wholesaler: " + _activeWholesalerUser.WholesalerName;
+ tagWholesalerLocation.Text = "Location: " + _activeWholesalerUser.WholesalerLocation;
+ UpdateWholesalerNameEntry.Text = "Wholesaler Name";
+ UpdateWholesalerLocationEntry.Text = "Wholesaler Location";
+ }
+
+ //Get Context methods
+ private async Task GetInventoryRecordByContext(object sender)
+ {
+ WholesalerInventoryDTO inventoryRecordToUpdate = null;
+
+ if (sender is Entry entry)
+ {
+ if (entry.BindingContext is WholesalerInventoryDTO record)
+ {
+ inventoryRecordToUpdate = record;
+ }
+ }
+
+ if (sender is Button button)
+ {
+ if (button.BindingContext is WholesalerInventoryDTO record)
+ {
+ inventoryRecordToUpdate = record;
+ }
+ }
+
+ return inventoryRecordToUpdate;
+ }
+
+ private async Task GetQuoteByContext(object sender)
+ {
+ WholesalerQuoteDTO quoteToUpdate = null;
+
+ if (sender is Entry entry)
+ {
+ if (entry.BindingContext is WholesalerQuoteDTO quote)
+ {
+ quoteToUpdate = quote;
+ }
+ }
+
+ if (sender is Button button)
+ {
+ if (button.BindingContext is WholesalerQuoteDTO quote)
+ {
+ quoteToUpdate = quote;
+ }
+ }
+
+ return quoteToUpdate;
+ }
+
+ private async Task GetBeerByContext(object sender)
+ {
+ BeerDTO beerToUpdate = null;
+
+ if (sender is Entry entry)
+ {
+ if (entry.BindingContext is BeerDTO beer)
+ {
+ beerToUpdate = beer;
+ }
+ }
+
+ if (sender is Button button)
+ {
+ if (button.BindingContext is BeerDTO beer)
+ {
+ beerToUpdate = beer;
+ }
+ }
+
+ return beerToUpdate;
+ }
+
+ //navigation methods
+ private async void OnLogOut(object sender, EventArgs e)
+ {
+ WholesalerWarningLabel.Text = null;
+ Navigation.PushAsync(new MainPage());
+ }
+
+ private void RetreatToMainWholesalerPage()
+ {
+ Navigation.PushAsync(new WholesalerMainPage(_httpClient));
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Platforms/Windows/App.xaml b/BreweryAPI/BreweryMaui/Platforms/Windows/App.xaml
new file mode 100644
index 0000000..9764294
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Platforms/Windows/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/BreweryAPI/BreweryMaui/Platforms/Windows/App.xaml.cs b/BreweryAPI/BreweryMaui/Platforms/Windows/App.xaml.cs
new file mode 100644
index 0000000..5d2a632
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,24 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace BreweryMaui.WinUI
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public partial class App : MauiWinUIApplication
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Platforms/Windows/Package.appxmanifest b/BreweryAPI/BreweryMaui/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 0000000..9c07617
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BreweryAPI/BreweryMaui/Platforms/Windows/app.manifest b/BreweryAPI/BreweryMaui/Platforms/Windows/app.manifest
new file mode 100644
index 0000000..a8b65c4
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Platforms/Windows/app.manifest
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
diff --git a/BreweryAPI/BreweryMaui/Properties/launchSettings.json b/BreweryAPI/BreweryMaui/Properties/launchSettings.json
new file mode 100644
index 0000000..edf8aad
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Windows Machine": {
+ "commandName": "MsixPackage",
+ "nativeDebugging": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Resources/AppIcon/appicon.svg b/BreweryAPI/BreweryMaui/Resources/AppIcon/appicon.svg
new file mode 100644
index 0000000..9d63b65
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Resources/AppIcon/appiconfg.svg b/BreweryAPI/BreweryMaui/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Resources/Fonts/CroissantOne-Regular.ttf b/BreweryAPI/BreweryMaui/Resources/Fonts/CroissantOne-Regular.ttf
new file mode 100644
index 0000000..6b0d123
Binary files /dev/null and b/BreweryAPI/BreweryMaui/Resources/Fonts/CroissantOne-Regular.ttf differ
diff --git a/BreweryAPI/BreweryMaui/Resources/Fonts/OpenSans-Regular.ttf b/BreweryAPI/BreweryMaui/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000..1e57f67
Binary files /dev/null and b/BreweryAPI/BreweryMaui/Resources/Fonts/OpenSans-Regular.ttf differ
diff --git a/BreweryAPI/BreweryMaui/Resources/Images/beerbackground.jpg b/BreweryAPI/BreweryMaui/Resources/Images/beerbackground.jpg
new file mode 100644
index 0000000..23e95b0
Binary files /dev/null and b/BreweryAPI/BreweryMaui/Resources/Images/beerbackground.jpg differ
diff --git a/BreweryAPI/BreweryMaui/Resources/Raw/AboutAssets.txt b/BreweryAPI/BreweryMaui/Resources/Raw/AboutAssets.txt
new file mode 100644
index 0000000..15d6244
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,15 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with you package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
diff --git a/BreweryAPI/BreweryMaui/Resources/Splash/splash.svg b/BreweryAPI/BreweryMaui/Resources/Splash/splash.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Resources/Splash/splash.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Resources/Styles/Colors.xaml b/BreweryAPI/BreweryMaui/Resources/Styles/Colors.xaml
new file mode 100644
index 0000000..245758b
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Resources/Styles/Colors.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+ #512BD4
+ #DFD8F7
+ #2B0B98
+ White
+ Black
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #F7B548
+ #FFD590
+ #FFE5B9
+ #28C2D1
+ #7BDDEF
+ #C3F2F4
+ #3E8EED
+ #72ACF1
+ #A7CBF6
+
+
\ No newline at end of file
diff --git a/BreweryAPI/BreweryMaui/Resources/Styles/Styles.xaml b/BreweryAPI/BreweryMaui/Resources/Styles/Styles.xaml
new file mode 100644
index 0000000..52b6e16
--- /dev/null
+++ b/BreweryAPI/BreweryMaui/Resources/Styles/Styles.xaml
@@ -0,0 +1,405 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BreweryAPI/IntegrationTests/Controllers/BeerTests.cs b/BreweryAPI/IntegrationTests/Controllers/BeerTests.cs
new file mode 100644
index 0000000..af4d666
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Controllers/BeerTests.cs
@@ -0,0 +1,172 @@
+using BreweryAPI.Models;
+using BreweryAPI;
+using FluentAssertions;
+using IntegrationTests.Helpers;
+using System.Net.Http.Json;
+using Newtonsoft.Json;
+using System.Text;
+
+namespace IntegrationTests.Controllers;
+
+public class BeerTests
+{
+ [Fact]
+ public async Task Get_Always_GetBeers()
+ {
+ string connectionString = "TestGetBeers";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("/api/Beer");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(5);
+ results[0].BeerName.Should().Be("TestBeer1");
+ results[0].Price.Should().Be(1);
+ results[0].BreweryId.Should().Be(1);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetBeer()
+ {
+ string connectionString = "TestGetSingBeer";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int beerId = 1;
+
+ var response = await client.GetAsync($"/api/Beer/Singular/{beerId}");
+ var results = await response.Content.ReadFromJsonAsync();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.BeerName.Should().Be("TestBeer2");
+ results.Price.Should().Be(2);
+ results.BreweryId.Should().Be(1);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetBeersByBrewery()
+ {
+ string connectionString = "TestGetBeersByBrewery";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int breweryId = 1;
+
+ var response = await client.GetAsync($"/api/Beer/{breweryId}");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(3);
+ results[1].BeerName.Should().Be("TestBeer2");
+ results[1].Price.Should().Be(2);
+ results[1].BreweryId.Should().Be(1);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnAddBeer_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestAddBeer";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ var newBeer = new BreweryAPI.Models.BeerModel()
+ {
+ BeerName = "NewBeer",
+ Price = 10,
+ BreweryId = 1
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newBeer), Encoding.UTF8, "application/json");
+ var request = await client.PostAsync("/api/Beer", httpContent);
+
+ var response = await client.GetAsync("/api/Beer");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(6);
+ results[5].BeerName.Should().Be("NewBeer");
+ results[5].Price.Should().Be(10);
+ results[5].BreweryId.Should().Be(1);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnUdateBeer_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestUpdateBeer";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int beerId = 4;
+
+ var newBeer = new BreweryAPI.Models.BeerModel()
+ {
+ BeerId = beerId,
+ BeerName = "UpdatedBeer",
+ Price = 5,
+ BreweryId = 2
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newBeer), Encoding.UTF8, "application/json");
+ var request = await client.PutAsync($"/api/Beer/{beerId}", httpContent);
+
+ var response = await client.GetAsync($"/api/Beer");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(5);
+ results[3].BeerName.Should().Be("UpdatedBeer");
+ results[3].Price.Should().Be(5);
+ results[3].BreweryId.Should().Be(2);
+
+ dbContext.Dispose();
+ }
+
+ public async Task OnDeleteBeer_WhenExecuteController_ShouldDeleteInDb()
+ {
+ string connectionString = "TestBeerDelete";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ int beerId = 1;
+
+ var client = _factory.CreateClient();
+
+ var request = await client.DeleteAsync($"/api/Beer/{beerId}");
+
+ var response = await client.GetAsync("/api/Beer");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(4);
+ results[0].BeerName.Should().Be("TestBeer2");
+ results[0].Price.Should().Be(2);
+ results[0].BreweryId.Should().Be(1);
+
+ dbContext.Dispose();
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/Controllers/BrewerySalesTest.cs b/BreweryAPI/IntegrationTests/Controllers/BrewerySalesTest.cs
new file mode 100644
index 0000000..c7d9b4d
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Controllers/BrewerySalesTest.cs
@@ -0,0 +1,158 @@
+using BreweryAPI.Models;
+using BreweryAPI;
+using FluentAssertions;
+using IntegrationTests.Helpers;
+using System.Net.Http.Json;
+using Newtonsoft.Json;
+using System.Text;
+
+namespace IntegrationTests.Controllers;
+
+public class BrewerySalesTest
+{
+ [Fact]
+ public async Task Get_Always_GetBrewerySales()
+ {
+ string connectionString = "TestGetBrewerySales";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("/api/BrewerySales");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].WholeSalerId.Should().Be(1);
+ results[0].BeerId.Should().Be(1);
+ results[0].Quantity.Should().Be(50);
+ results[0].TotalPrice.Should().Be(50);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetBrewerySale()
+ {
+ string connectionString = "TestGetBrewerySale";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int brewerySaleId = 2;
+
+ var response = await client.GetAsync($"/api/BrewerySales/{brewerySaleId}");
+ var results = await response.Content.ReadFromJsonAsync();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.WholeSalerId.Should().Be(1);
+ results.BeerId.Should().Be(1);
+ results.Quantity.Should().Be(50);
+ results.TotalPrice.Should().Be(50);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnAddBrewerySale_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestAddBrewerySale";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ var newBrewerySale = new BreweryAPI.Models.BrewerySalesModel()
+ {
+ WholeSalerId = 1,
+ BeerId = 1,
+ Quantity = 20,
+ TotalPrice = 40
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newBrewerySale), Encoding.UTF8, "application/json");
+ var request = await client.PostAsync("/api/BrewerySales", httpContent);
+
+ var response = await client.GetAsync("/api/BrewerySales");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(3);
+ results[2].WholeSalerId.Should().Be(1);
+ results[2].BeerId.Should().Be(1);
+ results[2].Quantity.Should().Be(20);
+ results[2].TotalPrice.Should().Be(40);
+
+ dbContext.Dispose();
+ }
+
+
+ [Fact]
+ public async Task OnUpdateBrewery_WhenExecuteController_ShouldUpdateInDb()
+ {
+ string connectionString = "TestUpdateBrewerySale";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int salesId = 2;
+
+ var updatedBrewerySale = new BreweryAPI.Models.BrewerySalesModel()
+ {
+ SalesId = salesId,
+ WholeSalerId = 1,
+ BeerId = 1,
+ Quantity = 20,
+ TotalPrice = 40
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(updatedBrewerySale), Encoding.UTF8, "application/json");
+ var request = await client.PutAsync($"/api/BrewerySales/{salesId}", httpContent);
+
+ var response = await client.GetAsync("/api/BrewerySales");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].WholeSalerId.Should().Be(1);
+ results[0].BeerId.Should().Be(1);
+ results[0].Quantity.Should().Be(20);
+ results[0].TotalPrice.Should().Be(40);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnDeleteBrewerySale_WhenExecuteController_ShouldDeleteInDb()
+ {
+ string connectionString = "TestBrewerySaleDelete";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ int brewerySaleId = 1;
+
+ var client = _factory.CreateClient();
+
+ var request = await client.DeleteAsync($"/api/BrewerySales/{brewerySaleId}");
+
+ var response = await client.GetAsync("/api/BrewerySales");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(1);
+ results[0].WholeSalerId.Should().Be(1);
+ results[0].BeerId.Should().Be(1);
+ results[0].Quantity.Should().Be(50);
+ results[0].TotalPrice.Should().Be(50);
+
+ dbContext.Dispose();
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/Controllers/BreweryTests.cs b/BreweryAPI/IntegrationTests/Controllers/BreweryTests.cs
new file mode 100644
index 0000000..7d470b2
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Controllers/BreweryTests.cs
@@ -0,0 +1,149 @@
+using BreweryAPI;
+using BreweryAPI.Models;
+using FluentAssertions;
+using IntegrationTests.Helpers;
+using Newtonsoft.Json;
+using System.Net.Http.Json;
+using System.Text;
+
+namespace IntegrationTests.Controllers
+{
+ public class BreweryTests
+ {
+ [Fact]
+ public async Task Get_Always_GetBreweries()
+ {
+ string connectionString = "TestGetBreweries";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("/api/Brewery");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].BreweryName.Should().Be("TestBrewery1");
+ results[0].BreweryLocation.Should().Be("TestLocation1");
+ results[0].BreweryLocation.Should().NotBe("Porto");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetBrewery()
+ {
+ string connectionString = "TestGetBrewery";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int breweryId = 1;
+
+ var response = await client.GetAsync($"/api/Brewery/{breweryId}");
+ var results = await response.Content.ReadFromJsonAsync();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.BreweryName.Should().Be("TestBrewery1");
+ results.BreweryLocation.Should().Be("TestLocation1");
+ results.BreweryLocation.Should().NotBe("Porto");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnAddBrewery_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestAddBrewery";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ var newBrewery = new BreweryAPI.Models.BreweryModel()
+ {
+ BreweryName = "NewName",
+ BreweryLocation = "NewLocation"
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newBrewery), Encoding.UTF8, "application/json");
+ var request = await client.PostAsync("/api/Brewery", httpContent);
+
+ var response = await client.GetAsync("/api/Brewery");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(3);
+ results[2].BreweryName.Should().Be("NewName");
+ results[2].BreweryLocation.Should().Be("NewLocation");
+ results[2].BreweryLocation.Should().NotBe("Porto");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnUpdateBrewery_WhenExecuteController_ShouldUpdateInDb()
+ {
+ string connectionString = "TestUpdateBrewery";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int breweryId = 1;
+
+ var newBrewery = new BreweryAPI.Models.BreweryModel()
+ {
+ BreweryId = breweryId,
+ BreweryName = "UpdatedName",
+ BreweryLocation = "UpdatedLocation"
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newBrewery), Encoding.UTF8, "application/json");
+ var request = await client.PutAsync($"/api/Brewery/{breweryId}", httpContent);
+
+ var response = await client.GetAsync("/api/Brewery");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].BreweryName.Should().Be("UpdatedName");
+ results[0].BreweryLocation.Should().Be("UpdatedLocation");
+ results[0].BreweryLocation.Should().NotBe("Porto");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnDeleteBrewery_WhenExecuteController_ShouldDeleteInDb()
+ {
+ string connectionString = "TestBreweryDelete";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ int breweryId = 1;
+
+ var client = _factory.CreateClient();
+
+ var request = await client.DeleteAsync($"/api/Brewery/{breweryId}");
+
+ var response = await client.GetAsync("/api/Brewery");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(1);
+ results[0].BreweryName.Should().Be("TestBrewery2");
+ results[0].BreweryLocation.Should().Be("TestLocation2");
+ results[0].BreweryLocation.Should().NotBe("Porto");
+
+ dbContext.Dispose();
+ }
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/Controllers/WholesalerInventoryTests.cs b/BreweryAPI/IntegrationTests/Controllers/WholesalerInventoryTests.cs
new file mode 100644
index 0000000..e871c68
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Controllers/WholesalerInventoryTests.cs
@@ -0,0 +1,150 @@
+using BreweryAPI.Models;
+using BreweryAPI;
+using FluentAssertions;
+using IntegrationTests.Helpers;
+using System.Net.Http.Json;
+using Newtonsoft.Json;
+using System.Text;
+
+namespace IntegrationTests.Controllers;
+
+public class WholesalerInventoryTests
+{
+ [Fact]
+ public async Task Get_Always_GetWholesalerInventories()
+ {
+ string connectionString = "TestGetWholesalerInventories";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("/api/WholesalerInventory");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].WholesalerId.Should().Be(2);
+ results[0].BeerId.Should().Be(2);
+ results[0].Quantity.Should().Be(10);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetWholesalerInventory()
+ {
+ string connectionString = "TestGetWholesalerInventory";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int wholesalerId = 2;
+
+ var response = await client.GetAsync($"/api/WholesalerInventory/{wholesalerId}");
+ var results = await response.Content.ReadFromJsonAsync();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.WholesalerId.Should().Be(2);
+ results.BeerId.Should().Be(2);
+ results.Quantity.Should().Be(10);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnAddWholesalerInventory_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestAddWholesalerInventory";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ var newWholesalerInventory = new BreweryAPI.Models.WholesalerInventory()
+ {
+ WholesalerId = 1,
+ BeerId = 2,
+ Quantity = 60,
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newWholesalerInventory), Encoding.UTF8, "application/json");
+ var request = await client.PostAsync("/api/WholesalerInventory", httpContent);
+
+ var response = await client.GetAsync("/api/WholesalerInventory");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(3);
+ results[2].WholesalerId.Should().Be(1);
+ results[2].BeerId.Should().Be(2);
+ results[2].Quantity.Should().Be(60);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnUpdateWholesalerInventory_WhenExecuteController_ShouldUpdateInDb()
+ {
+ string connectionString = "TestUpdateWholesalerInventory";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int WholesalerInventoryId = 1;
+
+ var updatedWholesalerInventory = new BreweryAPI.Models.WholesalerInventory()
+ {
+ ItemId = WholesalerInventoryId,
+ WholesalerId = 1,
+ BeerId = 2,
+ Quantity = 60,
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(updatedWholesalerInventory), Encoding.UTF8, "application/json");
+ var request = await client.PutAsync($"/api/WholesalerInventory/{WholesalerInventoryId}", httpContent);
+
+ var response = await client.GetAsync("/api/WholesalerInventory");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[1].WholesalerId.Should().Be(1);
+ results[1].BeerId.Should().Be(2);
+ results[1].Quantity.Should().Be(60);
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnDeleteWholesalerInventory_WhenExecuteController_ShouldDeleteInDb()
+ {
+ string connectionString = "TestWHolesalerInventoryDelete";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ int wholesalerInventoryId = 2;
+
+ var client = _factory.CreateClient();
+
+ var request = await client.DeleteAsync($"/api/WholesalerInventory/{wholesalerInventoryId}");
+
+ var response = await client.GetAsync("/api/WholesalerInventory");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(1);
+ results[0].WholesalerId.Should().Be(1);
+ results[0].BeerId.Should().Be(1);
+ results[0].Quantity.Should().Be(10);
+
+ dbContext.Dispose();
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/Controllers/WholesalerQuote.cs b/BreweryAPI/IntegrationTests/Controllers/WholesalerQuote.cs
new file mode 100644
index 0000000..3accd10
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Controllers/WholesalerQuote.cs
@@ -0,0 +1,127 @@
+using BreweryAPI.Models;
+using BreweryAPI;
+using FluentAssertions;
+using IntegrationTests.Helpers;
+using System.Net.Http.Json;
+using Newtonsoft.Json;
+using System.Text;
+
+namespace IntegrationTests.Controllers;
+
+public class WholesalerQuote
+{
+ [Fact]
+ public async Task Get_Always_GetWholesalerQuotes()
+ {
+ string connectionString = "TestGetWholesalerQuotes";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("/api/WholesalerQuote");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].ClientName.Should().Be("TestClient2");
+ results[0].WholesalerId.Should().Be(2);
+ results[0].BeerId.Should().Be(2);
+ results[0].Quantity.Should().Be(10);
+ results[0].TotalPrice.Should().Be(30);
+
+ Environment.SetEnvironmentVariable("TEST_ENVIRONMENT", null);
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetWholesalerQuote()
+ {
+ string connectionString = "TestGetWholesalerQuote";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int wholesalerQuoteId = 2;
+
+ var response = await client.GetAsync($"/api/WholesalerQuote/{wholesalerQuoteId}");
+ var results = await response.Content.ReadFromJsonAsync();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.ClientName.Should().Be("TestClient2");
+ results.WholesalerId.Should().Be(2);
+ results.BeerId.Should().Be(2);
+ results.Quantity.Should().Be(10);
+ results.TotalPrice.Should().Be(30);
+
+ Environment.SetEnvironmentVariable("TEST_ENVIRONMENT", null);
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnAddWholesalerQuote_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestAddWholesalerQuote";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ var newWholesalerQuote = new BreweryAPI.Models.WholesalerQuoteModel()
+ {
+ ClientName = "TestClient3",
+ WholesalerId = 1,
+ BeerId = 1,
+ Quantity = 1,
+ TotalPrice = 1,
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newWholesalerQuote), Encoding.UTF8, "application/json");
+ var request = await client.PostAsync("/api/WholesalerQuote", httpContent);
+
+ var response = await client.GetAsync("/api/WholesalerQuote");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(3);
+ results[2].ClientName.Should().Be("TestClient3");
+ results[2].WholesalerId.Should().Be(1);
+ results[2].BeerId.Should().Be(1);
+ results[2].Quantity.Should().Be(1);
+ results[2].TotalPrice.Should().Be(1);
+
+ Environment.SetEnvironmentVariable("TEST_ENVIRONMENT", null);
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnDeleteWholesalerQuote_WhenExecuteController_ShouldDeleteInDb()
+ {
+ string connectionString = "TestWholesalerQuoteDelete";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ int wholesalerQuoteId = 2;
+
+ var client = _factory.CreateClient();
+
+ var request = await client.DeleteAsync($"/api/WholesalerQuote/{wholesalerQuoteId}");
+
+ var response = await client.GetAsync("/api/WholesalerQuote");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results[0].ClientName.Should().Be("TestClient1");
+ results[0].WholesalerId.Should().Be(1);
+ results[0].BeerId.Should().Be(1);
+ results[0].Quantity.Should().Be(10);
+ results[0].TotalPrice.Should().Be(10);
+
+ dbContext.Dispose();
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/Controllers/WholsesalerTest.cs b/BreweryAPI/IntegrationTests/Controllers/WholsesalerTest.cs
new file mode 100644
index 0000000..97c4304
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Controllers/WholsesalerTest.cs
@@ -0,0 +1,143 @@
+using BreweryAPI.Models;
+using BreweryAPI;
+using FluentAssertions;
+using IntegrationTests.Helpers;
+using System.Net.Http.Json;
+using Newtonsoft.Json;
+using System.Text;
+
+namespace IntegrationTests.Controllers;
+
+public class WholsesalerTest
+{
+ [Fact]
+ public async Task Get_Always_GetWholesalers()
+ {
+ string connectionString = "TestGetWholesalers";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync("/api/Wholesaler");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[0].WholesalerName.Should().Be("WholesalerTest2");
+ results[0].WholesalerLocation.Should().Be("TestLocation2");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task Get_Always_GetWholesaler()
+ {
+ string connectionString = "TestGetWholesaler";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int wholesalerId = 1;
+
+ var response = await client.GetAsync($"/api/Wholesaler/{wholesalerId}");
+ var results = await response.Content.ReadFromJsonAsync();
+
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.WholesalerName.Should().Be("WholesalerTest1");
+ results.WholesalerLocation.Should().Be("TestLocation1");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnAddWholesaler_WhenExecuteController_ShouldStoreInDb()
+ {
+ string connectionString = "TestAddWholesaler";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ var newWholesaler = new BreweryAPI.Models.WholesalerModel()
+ {
+ WholesalerName = "Wholesaler3",
+ WholesalerLocation = "WholesalerLocation3"
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newWholesaler), Encoding.UTF8, "application/json");
+ var request = await client.PostAsync("/api/Wholesaler", httpContent);
+
+ var response = await client.GetAsync("/api/Wholesaler");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(3);
+ results[2].WholesalerName.Should().Be("Wholesaler3");
+ results[2].WholesalerLocation.Should().Be("WholesalerLocation3");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnUpdateWholesaler_WhenExecuteController_ShouldUpdateInDb()
+ {
+ string connectionString = "TestUpdateWholesaler";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ var client = _factory.CreateClient();
+ int wholesalerId = 1;
+
+ var newBrewery = new BreweryAPI.Models.WholesalerModel()
+ {
+ WholesalerID = wholesalerId,
+ WholesalerName = "Wholesaler3",
+ WholesalerLocation = "WholesalerLocation3"
+ };
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(newBrewery), Encoding.UTF8, "application/json");
+ var request = await client.PutAsync($"/api/Wholesaler/{wholesalerId}", httpContent);
+
+ var response = await client.GetAsync("/api/Wholesaler");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(2);
+ results[1].WholesalerName.Should().Be("Wholesaler3");
+ results[1].WholesalerLocation.Should().Be("WholesalerLocation3");
+
+ dbContext.Dispose();
+ }
+
+ [Fact]
+ public async Task OnDeleteWholesaler_WhenExecuteController_ShouldDeleteInDb()
+ {
+ string connectionString = "TestWholesalerDelete";
+ var _factory = TestEnvironment.CreateFactory(connectionString);
+ Context dbContext = TestEnvironment.CreateDatabase(_factory);
+
+ int wholesalerId = 2;
+
+ var client = _factory.CreateClient();
+
+ var request = await client.DeleteAsync($"/api/Wholesaler/{wholesalerId}");
+
+ var response = await client.GetAsync("/api/Wholesaler");
+ var results = await response.Content.ReadFromJsonAsync>();
+
+ request.StatusCode.Should().Be(System.Net.HttpStatusCode.NoContent);
+ response.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
+
+ results.Count.Should().Be(1);
+ results[0].WholesalerName.Should().Be("WholesalerTest1");
+ results[0].WholesalerLocation.Should().Be("TestLocation1");
+
+ dbContext.Dispose();
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/GlobalUsings.cs b/BreweryAPI/IntegrationTests/GlobalUsings.cs
new file mode 100644
index 0000000..8c927eb
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file
diff --git a/BreweryAPI/IntegrationTests/Helpers/TestData.cs b/BreweryAPI/IntegrationTests/Helpers/TestData.cs
new file mode 100644
index 0000000..12971cf
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Helpers/TestData.cs
@@ -0,0 +1,140 @@
+using BreweryAPI.Models;
+
+namespace BreweryAPI.ControllerTests
+{
+ public static class TestData
+ {
+ public static void SeedDataContext(Context _testContext)
+ {
+ if(!_testContext.Breweries.Any())
+ {
+ var brewery1 = new BreweryModel
+ {
+ BreweryName = "TestBrewery1",
+ BreweryLocation = "TestLocation1"
+ };
+ var brewery2 = new BreweryModel
+ {
+ BreweryName = "TestBrewery2",
+ BreweryLocation = "TestLocation2"
+ };
+
+ _testContext.Breweries.AddRange(brewery1, brewery2);
+ _testContext.SaveChanges();
+ }
+
+ if(!_testContext.Beers.Any())
+ {
+ var beer1 = new BeerModel
+ {
+ BeerName = "TestBeer1",
+ Price = 1,
+ BreweryId = 1,
+ };
+ var beer2 = new BeerModel
+ {
+ BeerName = "TestBeer2",
+ Price = 2,
+ BreweryId = 1,
+ };
+ var beer3 = new BeerModel
+ {
+ BeerName = "TestBeer3",
+ Price = 1,
+ BreweryId = 1,
+ };
+ var beer4 = new BeerModel
+ {
+ BeerName = "TestBeer4",
+ Price = 1,
+ BreweryId = 2,
+ };
+ var beer5 = new BeerModel
+ {
+ BeerName = "TestBeer5",
+ Price = 3,
+ BreweryId = 2,
+ };
+
+ _testContext.Beers.AddRange(beer2, beer1, beer3, beer4, beer5);
+ _testContext.SaveChanges();
+ }
+
+ if (!_testContext.Wholesalers.Any())
+ {
+ var wholesaler1 = new WholesalerModel
+ {
+ WholesalerName = "WholesalerTest1",
+ WholesalerLocation = "TestLocation1"
+ };
+ var wholesaler2 = new WholesalerModel
+ {
+ WholesalerName = "WholesalerTest2",
+ WholesalerLocation = "TestLocation2"
+ };
+ _testContext.Wholesalers.AddRange(wholesaler1, wholesaler2);
+ _testContext.SaveChanges();
+ }
+
+ if (!_testContext.BrewerySales.Any())
+ {
+ var brewerySale1 = new BrewerySalesModel
+ {
+ WholeSalerId = 1,
+ BeerId = 1,
+ Quantity = 50,
+ TotalPrice = 50
+ };
+ var brewerySale2 = new BrewerySalesModel
+ {
+ WholeSalerId = 2,
+ BeerId = 2,
+ Quantity = 10,
+ TotalPrice = 30
+ };
+ _testContext.BrewerySales.AddRange(brewerySale2, brewerySale1);
+ _testContext.SaveChanges();
+ }
+
+ if (!_testContext.WholesalerInventories.Any())
+ {
+ var wholesalerInventory1 = new WholesalerInventory
+ {
+ WholesalerId = 1,
+ BeerId = 1,
+ Quantity = 10,
+ };
+ var wholesalerInventory2 = new WholesalerInventory
+ {
+ WholesalerId = 2,
+ BeerId = 2,
+ Quantity = 10,
+ };
+ _testContext.WholesalerInventories.AddRange(wholesalerInventory1, wholesalerInventory2);
+ _testContext.SaveChanges();
+ }
+
+ if (!_testContext.WholesalerQuotes.Any())
+ {
+ var wholesalerQuote1 = new WholesalerQuoteModel
+ {
+ ClientName = "TestClient1",
+ WholesalerId = 1,
+ BeerId = 1,
+ Quantity = 10,
+ TotalPrice = 10
+ };
+ var wholesalerQuote2 = new WholesalerQuoteModel
+ {
+ ClientName = "TestClient2",
+ WholesalerId = 2,
+ BeerId = 2,
+ Quantity = 10,
+ TotalPrice = 30
+ };
+ _testContext.WholesalerQuotes.AddRange(wholesalerQuote1, wholesalerQuote2);
+ _testContext.SaveChanges();
+ }
+ }
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/Helpers/TestEnvironment.cs b/BreweryAPI/IntegrationTests/Helpers/TestEnvironment.cs
new file mode 100644
index 0000000..e59f413
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/Helpers/TestEnvironment.cs
@@ -0,0 +1,47 @@
+using BreweryAPI.ControllerTests;
+using BreweryAPI;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+
+namespace IntegrationTests.Helpers;
+
+public static class TestEnvironment
+{
+ public static WebApplicationFactory CreateFactory(string connectionString)
+ {
+ Environment.SetEnvironmentVariable("TEST_ENVIRONMENT", "true");
+
+ var _factory = new WebApplicationFactory().WithWebHostBuilder(builder =>
+ {
+ builder.ConfigureServices(services =>
+ {
+ services.RemoveAll(typeof(DbContextOptions));
+ services.AddDbContext(options =>
+ {
+ //The database needs to have different connections string trougout the running of the tests asynchonously, otherwise they access and make changes to the same database which affects the results!!
+ options.UseInMemoryDatabase(connectionString);
+ });
+ });
+ });
+
+ return _factory;
+ }
+
+ public static Context CreateDatabase(WebApplicationFactory _factory)
+ {
+ Context dbContext;
+ using (var scope = _factory.Services.CreateScope())
+ {
+ var scopeService = scope.ServiceProvider;
+ dbContext = scopeService.GetRequiredService();
+
+ dbContext.Database.EnsureCreated();
+
+ TestData.SeedDataContext(dbContext);
+ }
+
+ return dbContext;
+ }
+}
diff --git a/BreweryAPI/IntegrationTests/IntegrationTests.csproj b/BreweryAPI/IntegrationTests/IntegrationTests.csproj
new file mode 100644
index 0000000..b21b254
--- /dev/null
+++ b/BreweryAPI/IntegrationTests/IntegrationTests.csproj
@@ -0,0 +1,33 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/BreweryAPI/ReadMe.txt b/BreweryAPI/ReadMe.txt
new file mode 100644
index 0000000..20909a9
--- /dev/null
+++ b/BreweryAPI/ReadMe.txt
@@ -0,0 +1,60 @@
+The C# Academy
+
+Project: BreweryAPI
+
+
+How to use:
+----------
+For each of the tables existing in the database there are 5 endpoints in each controller that can be used:
+-to get all records
+-to get a specific record
+-to create a record
+-to update a record
+-to delete a record
+
+In the Beers controller there is an extra method/endpoint that can be used to get all beers by brewery.
+The database schema can be consulted in the image "BreweryAPI schema" in the project folder.
+
+
+Challenges/dificulties:
+----------------------
+Up until this point the databases i created all had 1 or 2 (max) tables, they were simple databases with simple table relathionships. But in this project more tables were required to comply with the requirements and relathions between them needed to be established, which was a good challenge in itself. And one that I wanted to try to overcome.
+
+Building the API methods in the controller was a challenge too, since as a beginner i did know all the "syntax" that I could or should use to make it work. During the process, I got a few errors while testing the methods in swagger and I had to figure out what the problem was. Which sometimes could be related to how the table relations were built. But with perseverance and google i overcame this, and trough repetition (by building many methods) I can say that i feel alot more confident about building API's than i was before.
+
+ The tests project:
+ ---------------------
+ I encountered several difficulties here.
+ For example, i had to figure out that while the tests were running (since they were running async) they would make changes
+ to the database of other tests, ultimately changing the results of some tests. So, it was never consistent, a test might
+ pass one time, and then run the tests again and it would fail for no aparent reason... So, each test had its own separate
+ database to avoid this issue.
+ Because of the environmental variable (that would decide which data would be seeded into the database) and due to the fact that the tests run async i encounted another bug because at the beggining of the tests the variable was set to "test mode" and and the end of the test it was set back
+ to "normal mode". This caused at least one or two tests to fail because a test that finished running would change the variable to normal mode and another test in the middle of running might seed the "working data" into its database instead of the "test data" and it would fail. So at the ending of every test i had to remove every statement that set the environmental variable to "normal mode". In retrospect, i should probably have not used "test data" just simply a different database.
+
+ The Maui project:
+ -------------------
+ I haven´t encounted any especially daunting challenges in this project. There was some stuff that i wanted to do that i was not able to figure out how to do, though. It had to do with using a "FindByName" method to find specific buttons or entries in the lists that were created given the itemsource i specified, in the end it would always return null, even when everything seemed to be correct, so i went for other aproach to achieve what i wanted to do.
+
+
+Though Proccess:
+----------------
+Since I considered myself very much a beginner when it came to building API's and i didn't think i could do it all by myself at this point, i had to watch a few tutorials to help me understand how to construct everything.
+So i ended up using a repository patterns where each table of the database had its own controller, interface and imlementation of the interface (repository file) to interact with the table.
+So basically, I ended up using the repository file to create all the EF CRUD methods, and then the API controllers would access the specific repository they needed to access the entity framework methods in order to interact with the database.
+
+Since entity framework is being used, the models (that define each property and the relations between the tables) and the context were defined. And then DTOs were created for the API/controller methods to use them. IMapper was used to facilitate the proccess of moving data between models and DTO's
+IMapper (which i never had used before) made it easier and saved some time to build the project but i also learned that using it its not universally agreed upon by all developers.
+
+A seed file also was created with all the data that will be used to populate the database (if it is empty), in the correct context.
+
+ The tests project:
+ ----------------------------
+ For this project i decided to crate a test for every single method of every controller of the API. Also, each test would use its own database (in memory database) which was seeded with "test data". So everytime a test would run it set a variable in the "main" file of the API project as a way to signal that the data that should be seeded into the current database is the "test data" and not the "working data".
+
+
+ The Maui project:
+ -------------------
+ This project was basically building a frontend to consume the breweryAPI methods (though not all methods were necessary, they still exist at least).
+ There is a user selection screen at the main page (brewery or wholesaler). Then a page to select specifically your brewery or wholesaler or to create a new entity and then it moves to the next page where the user can make changes to stuff related to his own brewery or wholesaler.
+
\ No newline at end of file