From ef5e2340381848746ad0ffb083ca9592da3319c8 Mon Sep 17 00:00:00 2001 From: m-ruiz21 <38898004+m-ruiz21@users.noreply.github.com> Date: Sun, 16 Apr 2023 22:53:08 -0500 Subject: [PATCH 1/4] contracts and cultery service interface --- Project2Api.Contracts/Cutlery/CutleryRequest.cs | 7 +++++++ Project2Api.Contracts/Cutlery/CutleryResponse.cs | 7 +++++++ Project2Api/Services/Cutlery/ICutleryService.cs | 14 ++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 Project2Api.Contracts/Cutlery/CutleryRequest.cs create mode 100644 Project2Api.Contracts/Cutlery/CutleryResponse.cs create mode 100644 Project2Api/Services/Cutlery/ICutleryService.cs diff --git a/Project2Api.Contracts/Cutlery/CutleryRequest.cs b/Project2Api.Contracts/Cutlery/CutleryRequest.cs new file mode 100644 index 0000000..336cf79 --- /dev/null +++ b/Project2Api.Contracts/Cutlery/CutleryRequest.cs @@ -0,0 +1,7 @@ +namespace Project2Api.Contracts.Cutlery +{ + public record CutleryRequest( + string Name, + string Type + ); +} \ No newline at end of file diff --git a/Project2Api.Contracts/Cutlery/CutleryResponse.cs b/Project2Api.Contracts/Cutlery/CutleryResponse.cs new file mode 100644 index 0000000..e230583 --- /dev/null +++ b/Project2Api.Contracts/Cutlery/CutleryResponse.cs @@ -0,0 +1,7 @@ +namespace Project2Api.Contracts.Cutlery +{ + public record CutleryResponse( + string Name, + string Type + ); +} \ No newline at end of file diff --git a/Project2Api/Services/Cutlery/ICutleryService.cs b/Project2Api/Services/Cutlery/ICutleryService.cs new file mode 100644 index 0000000..29aa671 --- /dev/null +++ b/Project2Api/Services/Cutlery/ICutleryService.cs @@ -0,0 +1,14 @@ +using ErrorOr; +using Microsoft.AspNetCore.Mvc; +using Project2Api.Models; + +namespace Project2Api.Services.CutleryItems; + +public interface ICutleryInterface +{ + Task> CreateCutleryAsync(Cutlery cutlery); + Task> GetCutleryAsync(string name); + Task>> GetAllCutleryAsync(); + Task> UpdateCutleryAsync(Cutlery cutlery); + Task> DeleteCutleryAsync(string name); +} \ No newline at end of file From 4cacf6fc387dc1b06839340154a69ee82121c057 Mon Sep 17 00:00:00 2001 From: m-ruiz21 <38898004+m-ruiz21@users.noreply.github.com> Date: Sun, 16 Apr 2023 23:14:36 -0500 Subject: [PATCH 2/4] Cutlery Service + Errors --- Project2Api/Errors/Errors.Cutlery.cs | 34 ++++++++ .../Services/Cutlery/CutleryService.cs | 81 +++++++++++++++++++ .../Services/Cutlery/ICutleryService.cs | 2 +- 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 Project2Api/Errors/Errors.Cutlery.cs create mode 100644 Project2Api/Services/Cutlery/CutleryService.cs diff --git a/Project2Api/Errors/Errors.Cutlery.cs b/Project2Api/Errors/Errors.Cutlery.cs new file mode 100644 index 0000000..9ed7e34 --- /dev/null +++ b/Project2Api/Errors/Errors.Cutlery.cs @@ -0,0 +1,34 @@ +using ErrorOr; + +namespace Project2Api.ServiceErrors; + +public static partial class Errors +{ + /// + /// Cutlery errors + /// + public static class Cutlery + { + public static Error NotFound => Error.NotFound( + code: "Cutlery.NotFound", + description: "Cutlery Item not found" + ); + + public static Error UnexpectedError => Error.Unexpected( + code: "Cutlery.UnexpectedError", + description: "Unexpected error occurred when getting cutlery item" + ); + + public static Error DbError => Error.Custom( + type: (int)CustomErrorType.Database, + code: "Cutlery.DbError", + description: "Error occurred when getting cutlery item from database" + ); + + public static Error InvalidCutlery => Error.Custom( + type: (int)CustomErrorType.InvalidParams, + code: "Cutlery.InvalidMenuItem", + description: "Given cutlery item is invalid" + ); + } +} \ No newline at end of file diff --git a/Project2Api/Services/Cutlery/CutleryService.cs b/Project2Api/Services/Cutlery/CutleryService.cs new file mode 100644 index 0000000..c6069bc --- /dev/null +++ b/Project2Api/Services/Cutlery/CutleryService.cs @@ -0,0 +1,81 @@ +using System.Data; +using ErrorOr; +using Microsoft.AspNetCore.Mvc; +using Project2Api.Models; +using Project2Api.Repositories; +using Project2Api.ServiceErrors; + +namespace Project2Api.Services.CutleryItems; + +public class CutleryService : ICutleryService +{ + private readonly ICutleryRepository _cutleryRepository; + + public CutleryService(ICutleryRepository cutleryRepository) + { + _cutleryRepository = cutleryRepository; + } + + public async Task> CreateCutleryAsync(Cutlery cutlery) + { + int? rowsAffected = await _cutleryRepository.CreateCutleryAsync(cutlery); + + if (rowsAffected == null || rowsAffected == 0) + { + return Errors.Cutlery.DbError; + } + + return cutlery; + } + + public async Task>> GetAllCutleryAsync() + { + IEnumerable? cutlery = await _cutleryRepository.GetCutleryAsync(); + + if (cutlery == null) + { + return Errors.Cutlery.DbError; + } + + return cutlery.ToList(); + } + + public async Task> GetCutleryAsync(string name) + { + if (String.IsNullOrEmpty(name)) + { + return Errors.Cutlery.InvalidCutlery; + } + + Cutlery? cutlery = await _cutleryRepository.GetCutleryByNameAsync(name); + + if (cutlery == null) + { + return Errors.Cutlery.NotFound; + } + + return cutlery; + } + + public async Task> UpdateCutleryAsync(Cutlery cutlery) + { + int? rowsAffected = await _cutleryRepository.UpdateCutleryAsync(cutlery); + if (rowsAffected == null || rowsAffected == 0) + { + return Errors.Cutlery.NotFound; + } + + return cutlery; + } + + public async Task> DeleteCutleryAsync(string name) + { + bool success = await _cutleryRepository.DeleteCutleryAsync(name); + if (!success) + { + return Errors.Cutlery.NotFound; + } + + return new NoContentResult(); + } +} \ No newline at end of file diff --git a/Project2Api/Services/Cutlery/ICutleryService.cs b/Project2Api/Services/Cutlery/ICutleryService.cs index 29aa671..c2b7636 100644 --- a/Project2Api/Services/Cutlery/ICutleryService.cs +++ b/Project2Api/Services/Cutlery/ICutleryService.cs @@ -4,7 +4,7 @@ namespace Project2Api.Services.CutleryItems; -public interface ICutleryInterface +public interface ICutleryService { Task> CreateCutleryAsync(Cutlery cutlery); Task> GetCutleryAsync(string name); From e7c998e7b3ccb24eca347b49dd38b04350ec1a7e Mon Sep 17 00:00:00 2001 From: m-ruiz21 <38898004+m-ruiz21@users.noreply.github.com> Date: Mon, 17 Apr 2023 00:26:35 -0500 Subject: [PATCH 3/4] cutlery --- .../Cutlery/CutleryRequest.cs | 2 +- .../Cutlery/CutleryResponse.cs | 2 +- Project2Api/Controllers/CutleryController.cs | 115 ++++++++++++++++++ Project2Api/Models/Cutlery.cs | 33 +++++ .../Repositories/Cutlery/CutleryRepository.cs | 2 +- .../Cutlery/ICutleryRepository.cs | 2 +- .../Services/Cutlery/CutleryService.cs | 2 +- .../Services/Inventory/InventoryService.cs | 2 +- 8 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 Project2Api/Controllers/CutleryController.cs diff --git a/Project2Api.Contracts/Cutlery/CutleryRequest.cs b/Project2Api.Contracts/Cutlery/CutleryRequest.cs index 336cf79..a3a17b7 100644 --- a/Project2Api.Contracts/Cutlery/CutleryRequest.cs +++ b/Project2Api.Contracts/Cutlery/CutleryRequest.cs @@ -2,6 +2,6 @@ namespace Project2Api.Contracts.Cutlery { public record CutleryRequest( string Name, - string Type + int Quantity ); } \ No newline at end of file diff --git a/Project2Api.Contracts/Cutlery/CutleryResponse.cs b/Project2Api.Contracts/Cutlery/CutleryResponse.cs index e230583..320bdb6 100644 --- a/Project2Api.Contracts/Cutlery/CutleryResponse.cs +++ b/Project2Api.Contracts/Cutlery/CutleryResponse.cs @@ -2,6 +2,6 @@ namespace Project2Api.Contracts.Cutlery { public record CutleryResponse( string Name, - string Type + int Quantity ); } \ No newline at end of file diff --git a/Project2Api/Controllers/CutleryController.cs b/Project2Api/Controllers/CutleryController.cs new file mode 100644 index 0000000..8cd8523 --- /dev/null +++ b/Project2Api/Controllers/CutleryController.cs @@ -0,0 +1,115 @@ +using ErrorOr; +using Microsoft.AspNetCore.Mvc; +using Project2Api.Contracts.Cutlery; +using Project2Api.Models; +using Project2Api.Services.CutleryItems; + +namespace Project2Api.Controllers +{ + [ApiController] + [Route("cutlery")] + public class CutleryController : ApiController + { + private readonly ICutleryService _cutleryService; + + public CutleryController(ICutleryService cutleryService) + { + _cutleryService = cutleryService; + } + + /// + /// Creates cutlery item + /// + /// + /// Cutlery item or error + [HttpPost()] + public async Task CreateCutleryItem(CutleryRequest cutleryRequest) + { + ErrorOr cutleryItem = Cutlery.From(cutleryRequest); + + if (cutleryItem.IsError) + { + return Problem(cutleryItem.Errors); + } + + ErrorOr cutleryItemErrorOr = await _cutleryService.CreateCutleryAsync(cutleryItem.Value); + + return cutleryItemErrorOr.Match( + value => Ok(value), + errors => Problem(errors) + ); + } + + /// + /// Gets all cutlery items + /// + /// List of cutlery items + [HttpGet()] + public async Task GetAllCutleryItems() + { + // get all cutlery items + ErrorOr> cutleryItemsErrorOr = await _cutleryService.GetAllCutleryAsync(); + + // return Ok(cutleryItems) if succcessful, otherwise return error + return cutleryItemsErrorOr.Match( + value => Ok(value), + errors => Problem(errors) + ); + } + + /// + /// Gets cutlery item by name + /// + /// + /// Cutlery item or error + [HttpGet("{name}")] + public async Task GetCutleryItemByName(string name) + { + ErrorOr cutleryItemErrorOr = await _cutleryService.GetCutleryAsync(name); + + return cutleryItemErrorOr.Match( + value => Ok(value), + errors => Problem(errors) + ); + } + + /// + /// Updates cutlery item + /// + /// + /// Cutlery item or error + [HttpPut()] + public async Task UpdateCutleryItem(CutleryRequest cutleryRequest) + { + ErrorOr cutleryItem = Cutlery.From(cutleryRequest); + + if (cutleryItem.IsError) + { + return Problem(cutleryItem.Errors); + } + + ErrorOr updatedCutleryItem = await _cutleryService.UpdateCutleryAsync(cutleryItem.Value); + + return updatedCutleryItem.Match( + value => Ok(value), + errors => Problem(errors) + ); + } + + /// + /// Deletes cutlery item + /// + /// + /// Success or error + [HttpDelete("{name}")] + public async Task DeleteCutleryItem(string name) + { + ErrorOr deletedCutleryItem = await _cutleryService.DeleteCutleryAsync(name); + + return deletedCutleryItem.Match( + value => Ok(value), + errors => Problem(errors) + ); + } + } +} \ No newline at end of file diff --git a/Project2Api/Models/Cutlery.cs b/Project2Api/Models/Cutlery.cs index 474ad5e..e4c6ab3 100644 --- a/Project2Api/Models/Cutlery.cs +++ b/Project2Api/Models/Cutlery.cs @@ -1,3 +1,7 @@ +using ErrorOr; +using Project2Api.Contracts.Cutlery; +using Project2Api.ServiceErrors; + namespace Project2Api.Models; public class Cutlery @@ -18,4 +22,33 @@ public class Cutlery this.Name = name; this.Quantity = quantity; } + + public static ErrorOr Create( + string name, + int quantity + ) + { + if (String.IsNullOrEmpty(name) || quantity < 0) + { + return Errors.Cutlery.InvalidCutlery; + } + + return new Cutlery( + name, + quantity + ); + } + + /// + /// Creates cutlery From cutleryRequest + /// + /// + /// Created cutlery + public static ErrorOr From(CutleryRequest cutleryRequest) + { + return Create( + cutleryRequest.Name, + cutleryRequest.Quantity + ); + } } \ No newline at end of file diff --git a/Project2Api/Repositories/Cutlery/CutleryRepository.cs b/Project2Api/Repositories/Cutlery/CutleryRepository.cs index e12dd87..53cebc5 100644 --- a/Project2Api/Repositories/Cutlery/CutleryRepository.cs +++ b/Project2Api/Repositories/Cutlery/CutleryRepository.cs @@ -51,7 +51,7 @@ public CutleryRepository(IDbConnection connection) } } - public Task?> GetCutleryAsync() + public Task?> GetAllCutleryAsync() { using (UnitOfWork uow = new UnitOfWork(_connection)) { diff --git a/Project2Api/Repositories/Cutlery/ICutleryRepository.cs b/Project2Api/Repositories/Cutlery/ICutleryRepository.cs index 1affad9..2f6410c 100644 --- a/Project2Api/Repositories/Cutlery/ICutleryRepository.cs +++ b/Project2Api/Repositories/Cutlery/ICutleryRepository.cs @@ -15,7 +15,7 @@ public interface ICutleryRepository /// Gets all cutlery. /// /// A list of cutlery. - Task?> GetCutleryAsync(); + Task?> GetAllCutleryAsync(); /// /// Gets a cutlery by name. diff --git a/Project2Api/Services/Cutlery/CutleryService.cs b/Project2Api/Services/Cutlery/CutleryService.cs index c6069bc..ab785bf 100644 --- a/Project2Api/Services/Cutlery/CutleryService.cs +++ b/Project2Api/Services/Cutlery/CutleryService.cs @@ -30,7 +30,7 @@ public async Task> CreateCutleryAsync(Cutlery cutlery) public async Task>> GetAllCutleryAsync() { - IEnumerable? cutlery = await _cutleryRepository.GetCutleryAsync(); + IEnumerable? cutlery = await _cutleryRepository.GetAllCutleryAsync(); if (cutlery == null) { diff --git a/Project2Api/Services/Inventory/InventoryService.cs b/Project2Api/Services/Inventory/InventoryService.cs index 8159002..588042f 100644 --- a/Project2Api/Services/Inventory/InventoryService.cs +++ b/Project2Api/Services/Inventory/InventoryService.cs @@ -42,7 +42,7 @@ public async Task> DeleteInventoryItem(InventoryItem inve public async Task>> GetAllInventoryItems() { - IEnumerable? allCutlery = await _cutleryRepository.GetCutleryAsync(); + IEnumerable? allCutlery = await _cutleryRepository.GetAllCutleryAsync(); IEnumerable? allMenuItems = await _menuItemRepository.GetMenuItemsAsync(); if (allCutlery == null || allMenuItems == null) { From 59daaff6b6398cf8ca0cdd2add237e097c8e567c Mon Sep 17 00:00:00 2001 From: m-ruiz21 <38898004+m-ruiz21@users.noreply.github.com> Date: Mon, 17 Apr 2023 10:27:39 -0500 Subject: [PATCH 4/4] cutlery model test --- Tests/Models/Cutlery/FromRequest.cs | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Tests/Models/Cutlery/FromRequest.cs diff --git a/Tests/Models/Cutlery/FromRequest.cs b/Tests/Models/Cutlery/FromRequest.cs new file mode 100644 index 0000000..e386cbc --- /dev/null +++ b/Tests/Models/Cutlery/FromRequest.cs @@ -0,0 +1,43 @@ +using ErrorOr; +using Project2Api.Contracts.Cutlery; +using Project2Api.Models; +using Project2Api.ServiceErrors; + +namespace Tests.Models.CutleryTests +{ + // tests for order model + [TestFixture] + internal class FromRequest + { + // test for valid order request + [Test] + public void FromRequest_ValidCutleryRequest_ReturnsCutlery() + { + // Arrange + CutleryRequest cutleryRequest = new CutleryRequest("bowl", 12); + + // Act + ErrorOr errorOrCutlery = Cutlery.From(cutleryRequest); + + // Assert + Assert.That(! errorOrCutlery.IsError); + Assert.That(errorOrCutlery.Value.Name, Is.EqualTo("bowl")); + Assert.That(errorOrCutlery.Value.Quantity, Is.EqualTo(12)); + } + + // test for invalid order request + [Test] + public void FromRequest_InvalidOrderRequest_ReturnsError() + { + // Arrange + CutleryRequest cutleryRequest = new CutleryRequest("", -1); + + // Act + ErrorOr errorOrCutlery = Cutlery.From(cutleryRequest); + + // Assert + Assert.That(errorOrCutlery.IsError); + Assert.That(Errors.Cutlery.InvalidCutlery, Is.EqualTo(errorOrCutlery.FirstError)); + } + } +} \ No newline at end of file