From f0ce73197e6548a92b44c0d9394f79d1b1493634 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:21:35 +0200 Subject: [PATCH 01/38] Added test for adding a bagel to the basket --- domainModel.md | 80 ++++++++++++++++++++++++++++ exercise.main/Basket.cs | 21 ++++++++ exercise.main/Inventory.cs | 12 +++++ exercise.main/Products/Bagel.cs | 24 +++++++++ exercise.main/Products/Cofee.cs | 12 +++++ exercise.main/Products/Filling.cs | 12 +++++ exercise.main/Products/IProduct.cs | 16 ++++++ exercise.sln | 4 ++ exercise.tests/BasketTests.cs | 23 ++++++++ exercise.tests/UnitTest1.cs | 15 ------ exercise.tests/exercise.tests.csproj | 4 ++ 11 files changed, 208 insertions(+), 15 deletions(-) create mode 100644 domainModel.md create mode 100644 exercise.main/Basket.cs create mode 100644 exercise.main/Inventory.cs create mode 100644 exercise.main/Products/Bagel.cs create mode 100644 exercise.main/Products/Cofee.cs create mode 100644 exercise.main/Products/Filling.cs create mode 100644 exercise.main/Products/IProduct.cs create mode 100644 exercise.tests/BasketTests.cs delete mode 100644 exercise.tests/UnitTest1.cs diff --git a/domainModel.md b/domainModel.md new file mode 100644 index 00000000..4f7d0cbf --- /dev/null +++ b/domainModel.md @@ -0,0 +1,80 @@ +# Bob's Bagels - Object-oriented Programming + + +## Domain Model of User stories + +``` +1. +As a member of the public, +So I can order a bagel before work, +I'd like to add a specific type of bagel to my basket. +``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|------------------------------|-------------------------------------------|-----------------| +| Basket | AddProduct(IProduct product) | Adds a bagel to basket (list of bagels) | bool | + +``` +2. +As a member of the public, +So I can change my order, +I'd like to remove a bagel from my basket. +``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|-----------------------------------------------|-----------------| +| Basket | RemoveProduct(IProduct product) | Remove a bagel from basket (list of bagels) | bool | + +``` +3. +As a member of the public, +So that I can not overfill my small bagel basket +I'd like to know when my basket is full when I try adding an item beyond my basket capacity. +``` + +``` +4. +As a Bob's Bagels manager, +So that I can expand my business, +I’d like to change the capacity of baskets. +``` + +``` +5. +As a member of the public +So that I can maintain my sanity +I'd like to know if I try to remove an item that doesn't exist in my basket. +``` + +``` +6. +As a customer, +So I know how much money I need, +I'd like to know the total cost of items in my basket. +``` + +``` +7. +As a customer, +So I know what the damage will be, +I'd like to know the cost of a bagel before I add it to my basket. +``` + +``` +8. +As a customer, +So I can shake things up a bit, +I'd like to be able to choose fillings for my bagel. +``` + +``` +9. +As a customer, +So I don't over-spend, +I'd like to know the cost of each filling before I add it to my bagel order. +``` + +``` +10. +As the manager, +So we don't get any weird requests, +I want customers to only be able to order things that we stock in our inventory. +``` \ No newline at end of file diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs new file mode 100644 index 00000000..4412a61a --- /dev/null +++ b/exercise.main/Basket.cs @@ -0,0 +1,21 @@ +using exercise.main.Products; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Basket + { + private List _basketItems = new List(); + public void AddProduct(IProduct product) + { + _basketItems.Add(product); + } + + public List basketItems { get { return _basketItems; } + } + } +} diff --git a/exercise.main/Inventory.cs b/exercise.main/Inventory.cs new file mode 100644 index 00000000..218617ac --- /dev/null +++ b/exercise.main/Inventory.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + internal class Inventory + { + } +} diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs new file mode 100644 index 00000000..e9e14a38 --- /dev/null +++ b/exercise.main/Products/Bagel.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main.Products +{ + public class Bagel : IProduct + { + private string _variant; + public Bagel(string variant) + { + _variant = variant; + } + public string Name { get; set; } + + public decimal Price { get; set; } + + public string Variant { get; set; } + + public string Id { get; set; } + } +} diff --git a/exercise.main/Products/Cofee.cs b/exercise.main/Products/Cofee.cs new file mode 100644 index 00000000..79afa58d --- /dev/null +++ b/exercise.main/Products/Cofee.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main.Products +{ + internal class Cofee + { + } +} diff --git a/exercise.main/Products/Filling.cs b/exercise.main/Products/Filling.cs new file mode 100644 index 00000000..0d5b998e --- /dev/null +++ b/exercise.main/Products/Filling.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main.Products +{ + internal class Filling + { + } +} diff --git a/exercise.main/Products/IProduct.cs b/exercise.main/Products/IProduct.cs new file mode 100644 index 00000000..6fa2c88b --- /dev/null +++ b/exercise.main/Products/IProduct.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main.Products +{ + public interface IProduct + { + string Name { get; } + decimal Price { get; } + string Variant { get; set; } + string Id { get; set; } + } +} diff --git a/exercise.sln b/exercise.sln index 0efb5453..092c8cd6 100644 --- a/exercise.sln +++ b/exercise.sln @@ -9,6 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "exercise.tests", "exercise. EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{825CCFE7-4F2E-4770-8393-FEB732F66EE4}" ProjectSection(SolutionItems) = preProject + domainModel.md = domainModel.md extension1.md = extension1.md extension2.md = extension2.md extension3.md = extension3.md @@ -34,4 +35,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AA407FFD-6646-46D3-A264-678F5333229D} + EndGlobalSection EndGlobal diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs new file mode 100644 index 00000000..7c44b99e --- /dev/null +++ b/exercise.tests/BasketTests.cs @@ -0,0 +1,23 @@ +using exercise.main; +using exercise.main.Products; + +namespace exercise.tests; + +public class BasketTests +{ + + [Test] + public void AddBagelToBasket() + { + // arrange + Basket basket = new Basket(); + IProduct onionBagel = new Bagel("Onion"); + + // act + basket.AddProduct(onionBagel); + + // assert + Assert.That(basket.basketItems.Count, Is.EqualTo(1)); + Assert.That(basket.basketItems[0].Name, Is.EqualTo("Onion Bagel")); + } +} \ No newline at end of file diff --git a/exercise.tests/UnitTest1.cs b/exercise.tests/UnitTest1.cs deleted file mode 100644 index 7bdb8968..00000000 --- a/exercise.tests/UnitTest1.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace exercise.tests; - -public class Tests -{ - [SetUp] - public void Setup() - { - } - - [Test] - public void Test1() - { - Assert.Pass(); - } -} \ No newline at end of file diff --git a/exercise.tests/exercise.tests.csproj b/exercise.tests/exercise.tests.csproj index 9fed8e17..a3a97d4f 100644 --- a/exercise.tests/exercise.tests.csproj +++ b/exercise.tests/exercise.tests.csproj @@ -17,4 +17,8 @@ + + + + From 1b03399af68391a073cf44e137de33f901692d9f Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:32:46 +0200 Subject: [PATCH 02/38] added tests for removing bagel from basket --- exercise.main/Basket.cs | 19 +++++++++++++++++-- exercise.main/Products/Bagel.cs | 6 +++--- exercise.main/Products/IProduct.cs | 2 +- exercise.tests/BasketTests.cs | 17 ++++++++++++++++- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 4412a61a..4ffb50bf 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -10,12 +10,27 @@ namespace exercise.main public class Basket { private List _basketItems = new List(); + private bool _isFull = false; + private int _basketCapacity = 5; + public void AddProduct(IProduct product) { _basketItems.Add(product); } - public List basketItems { get { return _basketItems; } + public void RemoveProduct(string productId) + { + var productToRemove = _basketItems.FirstOrDefault(p => p.Id == productId); + if (productToRemove != null) + { + _basketItems.Remove(productToRemove); + } } - } + + public List basketItems { get { return _basketItems; } } + + + } } + + diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index e9e14a38..1f9357af 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -13,12 +13,12 @@ public Bagel(string variant) { _variant = variant; } - public string Name { get; set; } + public string Name { get; } - public decimal Price { get; set; } + public decimal Price { get; } public string Variant { get; set; } - public string Id { get; set; } + public string Id { get; } } } diff --git a/exercise.main/Products/IProduct.cs b/exercise.main/Products/IProduct.cs index 6fa2c88b..83efbbbe 100644 --- a/exercise.main/Products/IProduct.cs +++ b/exercise.main/Products/IProduct.cs @@ -11,6 +11,6 @@ public interface IProduct string Name { get; } decimal Price { get; } string Variant { get; set; } - string Id { get; set; } + string Id { get; } } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 7c44b99e..2c6fbd96 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -11,7 +11,7 @@ public void AddBagelToBasket() { // arrange Basket basket = new Basket(); - IProduct onionBagel = new Bagel("Onion"); + IProduct onionBagel = new Bagel("Onion"); // adds a specific variant of Bagel // act basket.AddProduct(onionBagel); @@ -20,4 +20,19 @@ public void AddBagelToBasket() Assert.That(basket.basketItems.Count, Is.EqualTo(1)); Assert.That(basket.basketItems[0].Name, Is.EqualTo("Onion Bagel")); } + + [Test] + public void RemoveBagelFromBasket() + { + // arrange + Basket basket = new Basket(); + IProduct onionBagel = new Bagel("Onion"); + basket.AddProduct(onionBagel); + + // act + basket.RemoveProduct("BGLO"); + + // assert + Assert.That(basket.basketItems.Count, Is.EqualTo(0)); + } } \ No newline at end of file From 8bbf06a5a74d64376f789b8066cbf0f90a2b5ac5 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:45:45 +0200 Subject: [PATCH 03/38] add bagel to basket test works now --- exercise.main/Basket.cs | 4 ++-- exercise.main/Products/Bagel.cs | 3 ++- exercise.tests/BasketTests.cs | 20 +++++++++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 4ffb50bf..39c53f93 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -10,7 +10,6 @@ namespace exercise.main public class Basket { private List _basketItems = new List(); - private bool _isFull = false; private int _basketCapacity = 5; public void AddProduct(IProduct product) @@ -29,7 +28,8 @@ public void RemoveProduct(string productId) public List basketItems { get { return _basketItems; } } - + public bool IsFull { get { return _basketItems.Count >= _basketCapacity; } } + } } diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 1f9357af..05480cdb 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -9,6 +9,7 @@ namespace exercise.main.Products public class Bagel : IProduct { private string _variant; + public Bagel(string variant) { _variant = variant; @@ -17,7 +18,7 @@ public Bagel(string variant) public decimal Price { get; } - public string Variant { get; set; } + public string Variant { get { return _variant; } set { _variant = value; } } public string Id { get; } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 2c6fbd96..bfc7a5ad 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -18,7 +18,7 @@ public void AddBagelToBasket() // assert Assert.That(basket.basketItems.Count, Is.EqualTo(1)); - Assert.That(basket.basketItems[0].Name, Is.EqualTo("Onion Bagel")); + Assert.That(basket.basketItems[0].Variant, Is.EqualTo("Onion")); } [Test] @@ -35,4 +35,22 @@ public void RemoveBagelFromBasket() // assert Assert.That(basket.basketItems.Count, Is.EqualTo(0)); } + + [Test] + public void BasketIsFull() + { + // arrange + Basket basket = new Basket(); + basket.AddProduct(new Bagel("Onion")); + basket.AddProduct(new Bagel("Sesame")); + basket.AddProduct(new Bagel("Sesame")); + basket.AddProduct(new Bagel("Plain")); + basket.AddProduct(new Bagel("Sesame")); + + // act + bool isFull = basket.IsFull; + + // assert + Assert.That(isFull, Is.True); + } } \ No newline at end of file From 7a436556d697e8d15a2c557825202e1dc973c8f6 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:55:06 +0200 Subject: [PATCH 04/38] test for removing a bagel from basket works --- exercise.main/Basket.cs | 2 +- exercise.main/Products/Bagel.cs | 10 ++++++++-- exercise.main/Products/IProduct.cs | 2 +- exercise.tests/BasketTests.cs | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 39c53f93..6033ced8 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -28,7 +28,7 @@ public void RemoveProduct(string productId) public List basketItems { get { return _basketItems; } } - public bool IsFull { get { return _basketItems.Count >= _basketCapacity; } } + public bool IsFull { get { return _basketItems.Count >= _basketCapacity; } } } } diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 05480cdb..5bfa7f01 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -9,17 +9,23 @@ namespace exercise.main.Products public class Bagel : IProduct { private string _variant; + private string _id; public Bagel(string variant) { _variant = variant; } + public Bagel(string variant, string id) + { + _variant = variant; + _id = id; + } public string Name { get; } public decimal Price { get; } - public string Variant { get { return _variant; } set { _variant = value; } } + public string Variant { get { return _variant; } } - public string Id { get; } + public string Id { get { return _id; } } } } diff --git a/exercise.main/Products/IProduct.cs b/exercise.main/Products/IProduct.cs index 83efbbbe..7091755f 100644 --- a/exercise.main/Products/IProduct.cs +++ b/exercise.main/Products/IProduct.cs @@ -10,7 +10,7 @@ public interface IProduct { string Name { get; } decimal Price { get; } - string Variant { get; set; } + string Variant { get; } string Id { get; } } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index bfc7a5ad..b951af28 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -26,7 +26,7 @@ public void RemoveBagelFromBasket() { // arrange Basket basket = new Basket(); - IProduct onionBagel = new Bagel("Onion"); + IProduct onionBagel = new Bagel("Onion", "BGLO"); basket.AddProduct(onionBagel); // act From 8260f0b30d6756621d61fa32bec09acad9c436e1 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:19:04 +0200 Subject: [PATCH 05/38] added tests and source code for basket capacity --- exercise.tests/BasketTests.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index b951af28..5886ebcf 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -53,4 +53,21 @@ public void BasketIsFull() // assert Assert.That(isFull, Is.True); } + + [Test] + public void BasketIsNotFull() + { + // arrange + Basket basket = new Basket(); + basket.AddProduct(new Bagel("Onion")); + basket.AddProduct(new Bagel("Sesame")); + basket.AddProduct(new Bagel("Sesame")); + basket.AddProduct(new Bagel("Plain")); + + // act + bool isFull = basket.IsFull; + + // assert + Assert.That(isFull, Is.False); + } } \ No newline at end of file From d1f581905327f57d5738f492e918782fc4c9b25c Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:22:12 +0200 Subject: [PATCH 06/38] added test for basket capacity and implented the source code for this --- exercise.main/Basket.cs | 20 ++++++++++++++++++-- exercise.tests/BasketTests.cs | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 6033ced8..b1bb51dd 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -10,7 +10,7 @@ namespace exercise.main public class Basket { private List _basketItems = new List(); - private int _basketCapacity = 5; + private int _basketCapacity = 5; public void AddProduct(IProduct product) { @@ -30,7 +30,23 @@ public void RemoveProduct(string productId) public bool IsFull { get { return _basketItems.Count >= _basketCapacity; } } - } + public int BasketCapacity + { + get { return _basketCapacity; } + set + { + if (value > 0) + { + _basketCapacity = value; + } + else + { + throw new ArgumentException("Basket capacity must be greater than zero."); + } + } + + } + } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 5886ebcf..eb5a7379 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -70,4 +70,28 @@ public void BasketIsNotFull() // assert Assert.That(isFull, Is.False); } + + [Test] + public void BasketCapacityCanBeSet() + { + // arrange + Basket basket = new Basket(); + + // act + basket.BasketCapacity = 10; + + // assert + Assert.That(basket.BasketCapacity, Is.EqualTo(10)); + } + + [Test] + public void BasketCapacityCannotBeSetToZeroOrNegative() + { + // arrange + Basket basket = new Basket(); + + // act & assert + Assert.Throws(() => basket.BasketCapacity = 0); + Assert.Throws(() => basket.BasketCapacity = -5); + } } \ No newline at end of file From 65b65e5865031749140eb58061bc06d5c45255d9 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:27:04 +0200 Subject: [PATCH 07/38] updated domain model for user story 1-3 --- domainModel.md | 5 ++++- exercise.tests/BasketTests.cs | 12 ++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/domainModel.md b/domainModel.md index 4f7d0cbf..369b9cde 100644 --- a/domainModel.md +++ b/domainModel.md @@ -21,7 +21,7 @@ I'd like to remove a bagel from my basket. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|----------------------------------|-----------------------------------------------|-----------------| -| Basket | RemoveProduct(IProduct product) | Remove a bagel from basket (list of bagels) | bool | +| Basket | RemoveProduct(string productId) | Remove a bagel from basket (list of bagels) | bool | ``` 3. @@ -29,6 +29,9 @@ As a member of the public, So that I can not overfill my small bagel basket I'd like to know when my basket is full when I try adding an item beyond my basket capacity. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|------------------------------------------------------|-----------------| +| Basket | IsFull (property) | Check if basket item count exceeds basket capacity | bool | ``` 4. diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index eb5a7379..0cdee80a 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -6,7 +6,7 @@ namespace exercise.tests; public class BasketTests { - [Test] + [Test] // user story 1 public void AddBagelToBasket() { // arrange @@ -21,7 +21,7 @@ public void AddBagelToBasket() Assert.That(basket.basketItems[0].Variant, Is.EqualTo("Onion")); } - [Test] + [Test] // user story 2 public void RemoveBagelFromBasket() { // arrange @@ -36,7 +36,7 @@ public void RemoveBagelFromBasket() Assert.That(basket.basketItems.Count, Is.EqualTo(0)); } - [Test] + [Test] // user story 3 public void BasketIsFull() { // arrange @@ -54,7 +54,7 @@ public void BasketIsFull() Assert.That(isFull, Is.True); } - [Test] + [Test] // user story 3 public void BasketIsNotFull() { // arrange @@ -71,7 +71,7 @@ public void BasketIsNotFull() Assert.That(isFull, Is.False); } - [Test] + [Test] // user story 4 public void BasketCapacityCanBeSet() { // arrange @@ -84,7 +84,7 @@ public void BasketCapacityCanBeSet() Assert.That(basket.BasketCapacity, Is.EqualTo(10)); } - [Test] + [Test] // user story 4 public void BasketCapacityCannotBeSetToZeroOrNegative() { // arrange From 65fe2ade2d3d13d8cee8347b670687f89e8dee2c Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:40:14 +0200 Subject: [PATCH 08/38] added test for removing a product that is not present in basket --- domainModel.md | 8 +++++++- exercise.tests/BasketTests.cs | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/domainModel.md b/domainModel.md index 369b9cde..35574b3a 100644 --- a/domainModel.md +++ b/domainModel.md @@ -11,7 +11,7 @@ I'd like to add a specific type of bagel to my basket. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|------------------------------|-------------------------------------------|-----------------| -| Basket | AddProduct(IProduct product) | Adds a bagel to basket (list of bagels) | bool | +| Basket | AddProduct(IProduct product) | Add a bagel to basket (list of bagels) | bool | ``` 2. @@ -39,6 +39,9 @@ As a Bob's Bagels manager, So that I can expand my business, I’d like to change the capacity of baskets. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|---------------------------------------------------------------|-----------------| +| Basket | BasketCapacity (property) | Set basket capacity to value. Throw exception if value <= 0 | int | ``` 5. @@ -46,6 +49,9 @@ As a member of the public So that I can maintain my sanity I'd like to know if I try to remove an item that doesn't exist in my basket. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|----------------------------------------------------------------------------------|-----------------| +| Basket | RemoveProduct (string productId) | Throw exception when a product not present in basket is tried being removed | exception | ``` 6. diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 0cdee80a..a90ec455 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -30,8 +30,8 @@ public void RemoveBagelFromBasket() basket.AddProduct(onionBagel); // act - basket.RemoveProduct("BGLO"); - + basket.RemoveProduct("BGLO"); // removes the Bagel with ID "BGLO" + // assert Assert.That(basket.basketItems.Count, Is.EqualTo(0)); } @@ -94,4 +94,15 @@ public void BasketCapacityCannotBeSetToZeroOrNegative() Assert.Throws(() => basket.BasketCapacity = 0); Assert.Throws(() => basket.BasketCapacity = -5); } + + [Test] // user story 5 + public void RemoveNonExistentProduct() + { + // arrange + Basket basket = new Basket(); + basket.AddProduct(new Bagel("BGLS"); // adds a sesame bagel to basket + + // act & assert + Assert.Throws(() => basket.RemoveProduct("BGLO")); // removing a non-present onion bagel is not allowed + } } \ No newline at end of file From cccf20219d2ef39e0b1ad3d9cb4bf4b2dfc4a84f Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:43:54 +0200 Subject: [PATCH 09/38] added expection to RemoveProduct method to not allow removing a product that is not present in the basket --- exercise.main/Basket.cs | 4 ++++ exercise.tests/BasketTests.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index b1bb51dd..0d204942 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -24,6 +24,10 @@ public void RemoveProduct(string productId) { _basketItems.Remove(productToRemove); } + else + { + throw new ArgumentException("The item with this Id is not present in your basket. Could not be removed"); + } } public List basketItems { get { return _basketItems; } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index a90ec455..5113f827 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -100,7 +100,7 @@ public void RemoveNonExistentProduct() { // arrange Basket basket = new Basket(); - basket.AddProduct(new Bagel("BGLS"); // adds a sesame bagel to basket + basket.AddProduct(new Bagel("BGLS")); // adds a sesame bagel to basket // act & assert Assert.Throws(() => basket.RemoveProduct("BGLO")); // removing a non-present onion bagel is not allowed From 9c46a6872cac908826fea9155a7217b696749920 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:54:21 +0200 Subject: [PATCH 10/38] updated domain model for user story 6 --- domainModel.md | 5 ++++- exercise.main/Basket.cs | 3 +++ exercise.tests/BasketTests.cs | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/domainModel.md b/domainModel.md index 35574b3a..70cfb33a 100644 --- a/domainModel.md +++ b/domainModel.md @@ -51,7 +51,7 @@ I'd like to know if I try to remove an item that doesn't exist in my basket. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|----------------------------------|----------------------------------------------------------------------------------|-----------------| -| Basket | RemoveProduct (string productId) | Throw exception when a product not present in basket is tried being removed | exception | +| Basket | RemoveProduct (string productId) | Throw exception when a product not present in basket is tried being removed | exception | ``` 6. @@ -59,6 +59,9 @@ As a customer, So I know how much money I need, I'd like to know the total cost of items in my basket. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|----------------------------------------------|-----------------| +| Basket | BasketTotal (propertyd) | Return the total cost of products in basket | decimal | ``` 7. diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 0d204942..2c75aaae 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -50,6 +50,9 @@ public int BasketCapacity } } + + public decimal BasketTotal { get { return _basketItems.Sum(product => product.Price); } } + } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 5113f827..ff23d107 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -105,4 +105,20 @@ public void RemoveNonExistentProduct() // act & assert Assert.Throws(() => basket.RemoveProduct("BGLO")); // removing a non-present onion bagel is not allowed } + + [Test] // user story 6 + public void BasketTotal() + { + // arrange + Basket basket = new Basket(); + basket.AddProduct(new Bagel("Onion")); + basket.AddProduct(new Bagel("Plain")); + basket.AddProduct(new Bagel("Sesame")); + + // act + decimal basketTotal = basket.BasketTotal; + + // assert + Assert.That(basketTotal != 0); + } } \ No newline at end of file From acb5b6d603a036b4a742ad3c23ff9c79e64ab814 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:48:35 +0200 Subject: [PATCH 11/38] implemented source code for basket total --- exercise.main/Products/Bagel.cs | 36 ++++++++++++++++++++++++--------- exercise.tests/BasketTests.cs | 12 +++++------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 5bfa7f01..97e7e271 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -1,4 +1,5 @@ using System; + using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,24 +9,41 @@ namespace exercise.main.Products { public class Bagel : IProduct { - private string _variant; - private string _id; - public Bagel(string variant) + private static readonly Dictionary VariantPrices = new Dictionary() { - _variant = variant; - } - public Bagel(string variant, string id) + {"BGLO", 0.49m}, // Onion + {"BGLP", 0.39m}, // Plain + {"BGLE", 0.49m}, // Everything + {"BGLS", 0.49m} // Sesame + }; + + private string _name; + private string _id; + private string _variant; + + public Bagel(string id) { - _variant = variant; + _name = "Bagel"; _id = id; } + public string Name { get; } - public decimal Price { get; } + public decimal Price + { + get + { + if (!VariantPrices.ContainsKey(_id)) + throw new ArgumentException($"Invalid bagel id: {_id}"); + return VariantPrices[_id]; + } + } - public string Variant { get { return _variant; } } + public string Variant { get; } public string Id { get { return _id; } } + + } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index ff23d107..37b2e7bb 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -11,14 +11,14 @@ public void AddBagelToBasket() { // arrange Basket basket = new Basket(); - IProduct onionBagel = new Bagel("Onion"); // adds a specific variant of Bagel + IProduct onionBagel = new Bagel("BGLO"); // adds a specific Bagel variant (onion bagel) // act basket.AddProduct(onionBagel); // assert Assert.That(basket.basketItems.Count, Is.EqualTo(1)); - Assert.That(basket.basketItems[0].Variant, Is.EqualTo("Onion")); + Assert.That(basket.basketItems[0].Id, Is.EqualTo("BGLO")); } [Test] // user story 2 @@ -26,7 +26,7 @@ public void RemoveBagelFromBasket() { // arrange Basket basket = new Basket(); - IProduct onionBagel = new Bagel("Onion", "BGLO"); + IProduct onionBagel = new Bagel("BGLO"); basket.AddProduct(onionBagel); // act @@ -111,9 +111,9 @@ public void BasketTotal() { // arrange Basket basket = new Basket(); - basket.AddProduct(new Bagel("Onion")); - basket.AddProduct(new Bagel("Plain")); - basket.AddProduct(new Bagel("Sesame")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLS")); // act decimal basketTotal = basket.BasketTotal; From 2d495e39798526b216bc4bc0486fe9f8b52e7f6b Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:50:04 +0200 Subject: [PATCH 12/38] updated the domain model for user story 7 --- domainModel.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/domainModel.md b/domainModel.md index 70cfb33a..562fa473 100644 --- a/domainModel.md +++ b/domainModel.md @@ -69,6 +69,9 @@ As a customer, So I know what the damage will be, I'd like to know the cost of a bagel before I add it to my basket. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|----------------------------------------------|-----------------| +| Basket | BasketTotal (propertyd) | Return the cost of the bagel | decimal | ``` 8. From 2bea04f5cfbc9d324eca9e2aa6468b0d5eb46967 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:58:27 +0200 Subject: [PATCH 13/38] implemented test and source code for user story 7 (bagel price) --- domainModel.md | 8 ++++---- exercise.tests/BasketTests.cs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/domainModel.md b/domainModel.md index 562fa473..3e9f8a62 100644 --- a/domainModel.md +++ b/domainModel.md @@ -61,7 +61,7 @@ I'd like to know the total cost of items in my basket. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|----------------------------------|----------------------------------------------|-----------------| -| Basket | BasketTotal (propertyd) | Return the total cost of products in basket | decimal | +| Basket | BasketTotal (property) | Return the total cost of products in basket | decimal | ``` 7. @@ -69,9 +69,9 @@ As a customer, So I know what the damage will be, I'd like to know the cost of a bagel before I add it to my basket. ``` -| Classes | Methods/Properties | Scenario | Outputs | -|--------------|----------------------------------|----------------------------------------------|-----------------| -| Basket | BasketTotal (propertyd) | Return the cost of the bagel | decimal | +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|---------------------------|----------------------------------------------|-----------------| +| Bagel | Price (property) | Return the cost of the bagel | decimal | ``` 8. diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 37b2e7bb..1176a098 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -120,5 +120,24 @@ public void BasketTotal() // assert Assert.That(basketTotal != 0); + Assert.That(basketTotal, Is.EqualTo(1.37m)); // 0.49 + 0.39 + 0.49 = 1.37 } + + [Test] // user story 7 + public void BagelPrice() + { + // arrange + Bagel onionBagel = new Bagel("BGLO"); + Bagel plainBagel = new Bagel("BGLP"); + Bagel everythingBagel = new Bagel("BGLE"); + Bagel sesameBagel = new Bagel("BGLS"); + + // act and assert + Assert.That(onionBagel.Price, Is.EqualTo(0.49m)); + Assert.That(plainBagel.Price, Is.EqualTo(0.39m)); + Assert.That(everythingBagel.Price, Is.EqualTo(0.49m)); + Assert.That(sesameBagel.Price, Is.EqualTo(0.49m)); + } + + } \ No newline at end of file From e483f5b592aa75b0ed693c865cc754b02389c953 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:58:46 +0200 Subject: [PATCH 14/38] Update domainModel.md --- domainModel.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/domainModel.md b/domainModel.md index 3e9f8a62..f1e5360e 100644 --- a/domainModel.md +++ b/domainModel.md @@ -79,6 +79,9 @@ As a customer, So I can shake things up a bit, I'd like to be able to choose fillings for my bagel. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|---------------------------|----------------------------------------------|-----------------| +| Bagel | Price (property) | Return the cost of the bagel | decimal | ``` 9. From 452abecdf42687444563137fc3821bafcd4f0e6b Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:12:21 +0200 Subject: [PATCH 15/38] added test for user case 8 (filling) --- domainModel.md | 2 +- exercise.main/Products/Bagel.cs | 9 ++++----- exercise.main/Products/Filling.cs | 16 +++++++++++++++- exercise.tests/BasketTests.cs | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/domainModel.md b/domainModel.md index f1e5360e..056f9b2a 100644 --- a/domainModel.md +++ b/domainModel.md @@ -81,7 +81,7 @@ I'd like to be able to choose fillings for my bagel. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|---------------------------|----------------------------------------------|-----------------| -| Bagel | Price (property) | Return the cost of the bagel | decimal | +| | | | | ``` 9. diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 97e7e271..eefaa77e 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -18,17 +18,16 @@ public class Bagel : IProduct {"BGLS", 0.49m} // Sesame }; - private string _name; private string _id; - private string _variant; public Bagel(string id) { - _name = "Bagel"; _id = id; } - - public string Name { get; } + + // TODO: extra constructor for bagel where you can choose filling + + public string Name => "Bagel"; public decimal Price { diff --git a/exercise.main/Products/Filling.cs b/exercise.main/Products/Filling.cs index 0d5b998e..6da5e832 100644 --- a/exercise.main/Products/Filling.cs +++ b/exercise.main/Products/Filling.cs @@ -6,7 +6,21 @@ namespace exercise.main.Products { - internal class Filling + public class Filling : IProduct { + + private string _id; + + public Filling(string id) + { + _id = id; + } + public string Name => "Filling"; + + public decimal Price => 0.12m; // the price is the same for every variant of filling + + public string Variant { get; } + + public string Id => throw new NotImplementedException(); } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index 1176a098..b24310cf 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -139,5 +139,19 @@ public void BagelPrice() Assert.That(sesameBagel.Price, Is.EqualTo(0.49m)); } + [Test] // user story 8 + public void ChooseBagelFilling() + { + // arrange + Bagel onionBagel = new Bagel("BGLO"); + + // act + onionBagel.Filling("FILB") // add bacon filling to the onion bagel + + // assert + + } + + } \ No newline at end of file From a9518a81cc27074a605ee92b54ea5ec68a9716f3 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:29:56 +0200 Subject: [PATCH 16/38] implemented choose bagel filling test and source code and update domain model for this user story (8) --- domainModel.md | 6 +++--- exercise.main/Products/Bagel.cs | 6 ++++-- exercise.tests/BasketTests.cs | 7 ++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/domainModel.md b/domainModel.md index 056f9b2a..19734085 100644 --- a/domainModel.md +++ b/domainModel.md @@ -79,9 +79,9 @@ As a customer, So I can shake things up a bit, I'd like to be able to choose fillings for my bagel. ``` -| Classes | Methods/Properties | Scenario | Outputs | -|--------------|---------------------------|----------------------------------------------|-----------------| -| | | | | +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|---------------------------|---------------------|-----------------| +| Bagel | Filling (property) | Sets bagel filling | Filling | ``` 9. diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index eefaa77e..847d8f49 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -19,14 +19,13 @@ public class Bagel : IProduct }; private string _id; + private Filling _filling; public Bagel(string id) { _id = id; } - // TODO: extra constructor for bagel where you can choose filling - public string Name => "Bagel"; public decimal Price @@ -43,6 +42,9 @@ public decimal Price public string Id { get { return _id; } } + public Filling Filling { get; set; } + + } } diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/BasketTests.cs index b24310cf..43b7bdbc 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/BasketTests.cs @@ -143,13 +143,14 @@ public void BagelPrice() public void ChooseBagelFilling() { // arrange + Filling baconFilling = new Filling("FILB"); Bagel onionBagel = new Bagel("BGLO"); - // act - onionBagel.Filling("FILB") // add bacon filling to the onion bagel + // act + onionBagel.Filling = baconFilling; // assert - + Assert.That(onionBagel.Filling, Is.EqualTo(baconFilling)); } From 95bd0d88cfd123d39fd12ff48b99b03be962e292 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:31:45 +0200 Subject: [PATCH 17/38] updated domain model for user story 9 (filling price) --- domainModel.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/domainModel.md b/domainModel.md index 19734085..1f5a41c0 100644 --- a/domainModel.md +++ b/domainModel.md @@ -71,7 +71,7 @@ I'd like to know the cost of a bagel before I add it to my basket. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|---------------------------|----------------------------------------------|-----------------| -| Bagel | Price (property) | Return the cost of the bagel | decimal | +| Bagel | Price (property) | Return the price of the bagel | decimal | ``` 8. @@ -89,6 +89,9 @@ As a customer, So I don't over-spend, I'd like to know the cost of each filling before I add it to my bagel order. ``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|---------------------------|-------------------------------------------------|-----------------| +| Filling | Price (property) | Returns the price of the filling bagel filling | decimal | ``` 10. From 7a10b729526473d538bff89a9eaf4fe5399ef153 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:37:32 +0200 Subject: [PATCH 18/38] added test for user story 9 price of fillings --- .../{BasketTests.cs => CoreTests.cs} | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) rename exercise.tests/{BasketTests.cs => CoreTests.cs} (85%) diff --git a/exercise.tests/BasketTests.cs b/exercise.tests/CoreTests.cs similarity index 85% rename from exercise.tests/BasketTests.cs rename to exercise.tests/CoreTests.cs index 43b7bdbc..eef47c79 100644 --- a/exercise.tests/BasketTests.cs +++ b/exercise.tests/CoreTests.cs @@ -3,7 +3,7 @@ namespace exercise.tests; -public class BasketTests +public class CoreTests { [Test] // user story 1 @@ -153,6 +153,22 @@ public void ChooseBagelFilling() Assert.That(onionBagel.Filling, Is.EqualTo(baconFilling)); } + [Test] // user story 9 + public void FillingPrice() + { + // arrange + Filling baconFilling = new Filling("FILB"); + Filling eggFilling = new Filling("FILE"); + Filling cheeseFilling = new Filling("FILC"); + Filling creamyCheeseFilling = new Filling("FILX"); + Filling hamFilling = new Filling("FILH"); + // act and assert + Assert.That(baconFilling.Price, Is.EqualTo(0.12m)); + Assert.That(eggFilling.Price, Is.EqualTo(0.12m)); + Assert.That(cheeseFilling.Price, Is.EqualTo(0.12m)); + Assert.That(creamyCheeseFilling.Price, Is.EqualTo(0.12m)); + Assert.That(hamFilling.Price, Is.EqualTo(0.12m)); + } } \ No newline at end of file From 262bb284cdd34dbce55aa6c3eeac8b96faf35ab1 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 15:51:38 +0200 Subject: [PATCH 19/38] finished adding tests for user story 10 and implemented source code --- domainModel.md | 6 ++- exercise.main/Basket.cs | 11 ++++- exercise.main/Inventory.cs | 13 ++++- exercise.main/Products/Bagel.cs | 8 +++- exercise.main/Products/Filling.cs | 2 +- exercise.tests/CoreTests.cs | 80 +++++++++++++++++++++++-------- 6 files changed, 93 insertions(+), 27 deletions(-) diff --git a/domainModel.md b/domainModel.md index 1f5a41c0..8e86f99c 100644 --- a/domainModel.md +++ b/domainModel.md @@ -98,4 +98,8 @@ I'd like to know the cost of each filling before I add it to my bagel order. As the manager, So we don't get any weird requests, I want customers to only be able to order things that we stock in our inventory. -``` \ No newline at end of file +``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|-----------------------------|---------------------------------------------------------------------------------------------------------|--------------| +| Inventory | IsInInventory | Before adding a bagel/cofee to the basket we check that the bagel/coffee variant is in the inventory | bool | +| Inventory | IsInInventory | Before adding a filling to a bagel we check that the filling variant is in the inventory | bool | \ No newline at end of file diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 2c75aaae..bca29797 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -12,9 +12,18 @@ public class Basket private List _basketItems = new List(); private int _basketCapacity = 5; + private Inventory _inventory = new Inventory(); + + public Basket(Inventory inventory) + { + _inventory = inventory; + } + public void AddProduct(IProduct product) { - _basketItems.Add(product); + if (!_inventory.IsInInventory(product.Id)) // check if the product the customer wants to add i present in the inventory + throw new ArgumentException($"Product with SKU {product.Id} is not available in inventory."); + _basketItems.Add(product); // if it is, add it to the basket } public void RemoveProduct(string productId) diff --git a/exercise.main/Inventory.cs b/exercise.main/Inventory.cs index 218617ac..ac5bd362 100644 --- a/exercise.main/Inventory.cs +++ b/exercise.main/Inventory.cs @@ -6,7 +6,18 @@ namespace exercise.main { - internal class Inventory + public class Inventory { + private HashSet _inventory = new HashSet() + { + "BGLO", "BGLP", "BGLE", "BGLS", // bagel variant SKUs + "FILB", "FILE", "FILC", "FILX", "FILS", "FILH", // filling variant SKUs + "COFB", "COFW", "COFC", "COFL" // coffee variant SKUs + }; + + public bool IsInInventory(string productId) + { + return _inventory.Contains(productId); + } } } diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 847d8f49..4628c87d 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -43,8 +43,12 @@ public decimal Price public string Id { get { return _id; } } public Filling Filling { get; set; } - - + public void SetFilling(Filling filling, Inventory inventory) + { + if (!inventory.IsInInventory(filling.Id)) + throw new ArgumentException($"Filling {filling.Id} is not in inventory."); + this.Filling = filling; + } } } diff --git a/exercise.main/Products/Filling.cs b/exercise.main/Products/Filling.cs index 6da5e832..e89d437c 100644 --- a/exercise.main/Products/Filling.cs +++ b/exercise.main/Products/Filling.cs @@ -21,6 +21,6 @@ public Filling(string id) public string Variant { get; } - public string Id => throw new NotImplementedException(); + public string Id => _id; } } diff --git a/exercise.tests/CoreTests.cs b/exercise.tests/CoreTests.cs index eef47c79..10fddd4d 100644 --- a/exercise.tests/CoreTests.cs +++ b/exercise.tests/CoreTests.cs @@ -10,7 +10,8 @@ public class CoreTests public void AddBagelToBasket() { // arrange - Basket basket = new Basket(); + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); IProduct onionBagel = new Bagel("BGLO"); // adds a specific Bagel variant (onion bagel) // act @@ -25,7 +26,8 @@ public void AddBagelToBasket() public void RemoveBagelFromBasket() { // arrange - Basket basket = new Basket(); + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); IProduct onionBagel = new Bagel("BGLO"); basket.AddProduct(onionBagel); @@ -40,12 +42,13 @@ public void RemoveBagelFromBasket() public void BasketIsFull() { // arrange - Basket basket = new Basket(); - basket.AddProduct(new Bagel("Onion")); - basket.AddProduct(new Bagel("Sesame")); - basket.AddProduct(new Bagel("Sesame")); - basket.AddProduct(new Bagel("Plain")); - basket.AddProduct(new Bagel("Sesame")); + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLS")); + basket.AddProduct(new Bagel("BGLS")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLS")); // act bool isFull = basket.IsFull; @@ -58,11 +61,12 @@ public void BasketIsFull() public void BasketIsNotFull() { // arrange - Basket basket = new Basket(); - basket.AddProduct(new Bagel("Onion")); - basket.AddProduct(new Bagel("Sesame")); - basket.AddProduct(new Bagel("Sesame")); - basket.AddProduct(new Bagel("Plain")); + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLS")); + basket.AddProduct(new Bagel("BGLS")); + basket.AddProduct(new Bagel("BGLP")); // act bool isFull = basket.IsFull; @@ -75,8 +79,9 @@ public void BasketIsNotFull() public void BasketCapacityCanBeSet() { // arrange - Basket basket = new Basket(); - + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + // act basket.BasketCapacity = 10; @@ -88,8 +93,9 @@ public void BasketCapacityCanBeSet() public void BasketCapacityCannotBeSetToZeroOrNegative() { // arrange - Basket basket = new Basket(); - + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + // act & assert Assert.Throws(() => basket.BasketCapacity = 0); Assert.Throws(() => basket.BasketCapacity = -5); @@ -99,7 +105,8 @@ public void BasketCapacityCannotBeSetToZeroOrNegative() public void RemoveNonExistentProduct() { // arrange - Basket basket = new Basket(); + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); basket.AddProduct(new Bagel("BGLS")); // adds a sesame bagel to basket // act & assert @@ -110,7 +117,8 @@ public void RemoveNonExistentProduct() public void BasketTotal() { // arrange - Basket basket = new Basket(); + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); basket.AddProduct(new Bagel("BGLO")); basket.AddProduct(new Bagel("BGLP")); basket.AddProduct(new Bagel("BGLS")); @@ -143,14 +151,15 @@ public void BagelPrice() public void ChooseBagelFilling() { // arrange + Inventory inventory = new Inventory(); Filling baconFilling = new Filling("FILB"); Bagel onionBagel = new Bagel("BGLO"); // act - onionBagel.Filling = baconFilling; + onionBagel.SetFilling(baconFilling, inventory); // assert - Assert.That(onionBagel.Filling, Is.EqualTo(baconFilling)); + Assert.That(onionBagel.Filling.Id, Is.EqualTo(baconFilling.Id)); } [Test] // user story 9 @@ -171,4 +180,33 @@ public void FillingPrice() Assert.That(hamFilling.Price, Is.EqualTo(0.12m)); } + [Test] // user story 10; check that a user cannot add a product that is not in inventory + public void AddNonExistingProductToBasket() + { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + Bagel onionBagel = new Bagel("BGLO"); + Bagel fishBagel = new Bagel("BGLF"); + + // act + basket.AddProduct(onionBagel); // add the onion bagel to the basket + // assert that onion bagel was added + Assert.That(basket.basketItems.Count, Is.EqualTo(1)); + + // act & assert + Assert.Throws(() => basket.AddProduct(fishBagel)); // try do add the fishBagel to the basket (fish bagel is not in the inventory) + } + + [Test] // user story 10; check that a user cannot add a filling that is not in inventory to a bagel + public void AddNonExistingFillingToBagel() + { + // arrange + Inventory inventory = new Inventory(); + Bagel onionBagel = new Bagel("BGLO"); + Filling paprika = new Filling("FILP"); + + // act & assert + Assert.Throws(() => onionBagel.SetFilling(paprika, inventory)); // try do add paprika filling to the onion bagel (paprika filling is not in the inventory) + } } \ No newline at end of file From bd88627923fb7fdc6ac7fc029dde1367a9f16956 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:18:26 +0200 Subject: [PATCH 20/38] made it possible to add multiple fillings to a bagel, and updated tests to be more accurate --- exercise.main/Basket.cs | 3 +- exercise.main/Inventory.cs | 3 ++ exercise.main/Products/Bagel.cs | 37 ++++++++++++++++----- exercise.main/Products/Filling.cs | 2 +- exercise.tests/CoreTests.cs | 53 ++++++++++++++++++++++++++----- 5 files changed, 80 insertions(+), 18 deletions(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index bca29797..e6829b19 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -21,6 +21,8 @@ public Basket(Inventory inventory) public void AddProduct(IProduct product) { + if (IsFull) + throw new InvalidOperationException("Basket is full. Cannot add more products."); if (!_inventory.IsInInventory(product.Id)) // check if the product the customer wants to add i present in the inventory throw new ArgumentException($"Product with SKU {product.Id} is not available in inventory."); _basketItems.Add(product); // if it is, add it to the basket @@ -59,7 +61,6 @@ public int BasketCapacity } } - public decimal BasketTotal { get { return _basketItems.Sum(product => product.Price); } } } diff --git a/exercise.main/Inventory.cs b/exercise.main/Inventory.cs index ac5bd362..504a5b84 100644 --- a/exercise.main/Inventory.cs +++ b/exercise.main/Inventory.cs @@ -6,6 +6,9 @@ namespace exercise.main { + /// + /// Ensures that customers are only able to order things that are stocked in inventory. + /// public class Inventory { private HashSet _inventory = new HashSet() diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 4628c87d..7fe2d49b 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -18,8 +18,16 @@ public class Bagel : IProduct {"BGLS", 0.49m} // Sesame }; + private static readonly Dictionary VariantNames = new Dictionary() + { + {"BGLO", "Onion"}, + {"BGLP", "Plain"}, + {"BGLE", "Everything"}, + {"BGLS", "Sesame"} + }; + private string _id; - private Filling _filling; + private List _fillings = new List(); public Bagel(string id) { @@ -34,20 +42,33 @@ public decimal Price { if (!VariantPrices.ContainsKey(_id)) throw new ArgumentException($"Invalid bagel id: {_id}"); - return VariantPrices[_id]; + decimal price = VariantPrices[_id]; // get the spesific bagel´s price + price += _fillings.Sum(f => f.Price); + return price; } } - public string Variant { get; } + public string Variant + { + get + { + if (!VariantNames.ContainsKey(_id)) + throw new ArgumentException($"Invalid bagel id: {_id}"); + return VariantNames[_id]; + } + } public string Id { get { return _id; } } - public Filling Filling { get; set; } - public void SetFilling(Filling filling, Inventory inventory) + public IReadOnlyList Fillings => _fillings.AsReadOnly(); + public void AddFillings(IEnumerable fillings, Inventory inventory) { - if (!inventory.IsInInventory(filling.Id)) - throw new ArgumentException($"Filling {filling.Id} is not in inventory."); - this.Filling = filling; + foreach (var filling in fillings) + { + if (!inventory.IsInInventory(filling.Id)) + throw new ArgumentException($"Filling {filling.Id} is not in inventory."); + _fillings.Add(filling); + } } } diff --git a/exercise.main/Products/Filling.cs b/exercise.main/Products/Filling.cs index e89d437c..425abd20 100644 --- a/exercise.main/Products/Filling.cs +++ b/exercise.main/Products/Filling.cs @@ -17,7 +17,7 @@ public Filling(string id) } public string Name => "Filling"; - public decimal Price => 0.12m; // the price is the same for every variant of filling + public decimal Price => 0.12m; // price is the same for every filling variant public string Variant { get; } diff --git a/exercise.tests/CoreTests.cs b/exercise.tests/CoreTests.cs index 10fddd4d..5c339479 100644 --- a/exercise.tests/CoreTests.cs +++ b/exercise.tests/CoreTests.cs @@ -20,6 +20,7 @@ public void AddBagelToBasket() // assert Assert.That(basket.basketItems.Count, Is.EqualTo(1)); Assert.That(basket.basketItems[0].Id, Is.EqualTo("BGLO")); + Assert.That(basket.basketItems[0].Variant, Is.EqualTo("Onion")); } [Test] // user story 2 @@ -28,14 +29,19 @@ public void RemoveBagelFromBasket() // arrange Inventory inventory = new Inventory(); Basket basket = new Basket(inventory); - IProduct onionBagel = new Bagel("BGLO"); - basket.AddProduct(onionBagel); - + IProduct sesameBagel = new Bagel("BGLS"); + basket.AddProduct(sesameBagel); + + // assert that the sesame bagel is in the basket + Assert.That(basket.basketItems.Count, Is.EqualTo(1)); + Assert.That(basket.basketItems, Does.Contain(sesameBagel)); + // act - basket.RemoveProduct("BGLO"); // removes the Bagel with ID "BGLO" + basket.RemoveProduct("BGLS"); // removes the Bagel with ID "BGLO" // assert Assert.That(basket.basketItems.Count, Is.EqualTo(0)); + Assert.That(basket.basketItems, Does.Not.Contain(sesameBagel)); } [Test] // user story 3 @@ -55,6 +61,7 @@ public void BasketIsFull() // assert Assert.That(isFull, Is.True); + Assert.Throws(() => basket.AddProduct(new Bagel("BGLE"))); // trying to add another bagel should throw an exception } [Test] // user story 3 @@ -73,6 +80,7 @@ public void BasketIsNotFull() // assert Assert.That(isFull, Is.False); + Assert.DoesNotThrow(() => basket.AddProduct(new Bagel("BGLE"))); // adding another bagel should not throw an exception } [Test] // user story 4 @@ -114,7 +122,7 @@ public void RemoveNonExistentProduct() } [Test] // user story 6 - public void BasketTotal() + public void BasketTotal1() { // arrange Inventory inventory = new Inventory(); @@ -131,6 +139,32 @@ public void BasketTotal() Assert.That(basketTotal, Is.EqualTo(1.37m)); // 0.49 + 0.39 + 0.49 = 1.37 } + [Test] // user story 6: make sure that it also adds the price for the bagel fillings to BasketTotal + public void BasketTotal2() + { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + + Filling cheese = new Filling("FILC"); + Filling bacon = new Filling("FILB"); + + Bagel onionBagel = new Bagel("BGLO"); + onionBagel.AddFillings(new[] { cheese, bacon }, inventory); // add fillings to the onion bagel + basket.AddProduct(onionBagel); // adds the onion bagel with fillings to the basket + + Bagel sesameBagel = new Bagel("BGLS"); + sesameBagel.AddFillings(new[] { cheese }, inventory); // add filling to the sesame bagel + basket.AddProduct(sesameBagel); // adds the sesame bagel with filling to the basket + + // act + decimal basketTotal = basket.BasketTotal; + + // assert + Assert.That(basketTotal != 0); + Assert.That(basketTotal, Is.EqualTo(1.34m)); + } + [Test] // user story 7 public void BagelPrice() { @@ -153,13 +187,15 @@ public void ChooseBagelFilling() // arrange Inventory inventory = new Inventory(); Filling baconFilling = new Filling("FILB"); + Filling cheeseFilling = new Filling("FILC"); Bagel onionBagel = new Bagel("BGLO"); // act - onionBagel.SetFilling(baconFilling, inventory); + onionBagel.AddFillings(new[] { baconFilling, cheeseFilling }, inventory); // assert - Assert.That(onionBagel.Filling.Id, Is.EqualTo(baconFilling.Id)); + Assert.That(onionBagel.Fillings.Count, Is.EqualTo(2)); + Assert.That(onionBagel.Fillings.Any(f => f.Id == "FILB")); } [Test] // user story 9 @@ -204,9 +240,10 @@ public void AddNonExistingFillingToBagel() // arrange Inventory inventory = new Inventory(); Bagel onionBagel = new Bagel("BGLO"); + Filling cheese = new Filling("FILC"); Filling paprika = new Filling("FILP"); // act & assert - Assert.Throws(() => onionBagel.SetFilling(paprika, inventory)); // try do add paprika filling to the onion bagel (paprika filling is not in the inventory) + Assert.Throws(() => onionBagel.AddFillings(new[] {paprika, cheese}, inventory)); // try do add paprika filling to the onion bagel (paprika filling is not in the inventory) } } \ No newline at end of file From e9a1d5d5506df6c15e6152d073b489eab472d995 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Mon, 11 Aug 2025 21:20:43 +0200 Subject: [PATCH 21/38] updated Fillings class and implemented Coffee class --- exercise.main/Basket.cs | 1 - exercise.main/Products/Bagel.cs | 12 +++---- exercise.main/Products/Cofee.cs | 12 ------- exercise.main/Products/Coffee.cs | 59 +++++++++++++++++++++++++++++++ exercise.main/Products/Filling.cs | 21 +++++++++-- 5 files changed, 84 insertions(+), 21 deletions(-) delete mode 100644 exercise.main/Products/Cofee.cs create mode 100644 exercise.main/Products/Coffee.cs diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index e6829b19..018782e6 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -11,7 +11,6 @@ public class Basket { private List _basketItems = new List(); private int _basketCapacity = 5; - private Inventory _inventory = new Inventory(); public Basket(Inventory inventory) diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 7fe2d49b..973e38e8 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -19,12 +19,12 @@ public class Bagel : IProduct }; private static readonly Dictionary VariantNames = new Dictionary() - { - {"BGLO", "Onion"}, - {"BGLP", "Plain"}, - {"BGLE", "Everything"}, - {"BGLS", "Sesame"} - }; + { + {"BGLO", "Onion"}, + {"BGLP", "Plain"}, + {"BGLE", "Everything"}, + {"BGLS", "Sesame"} + }; private string _id; private List _fillings = new List(); diff --git a/exercise.main/Products/Cofee.cs b/exercise.main/Products/Cofee.cs deleted file mode 100644 index 79afa58d..00000000 --- a/exercise.main/Products/Cofee.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace exercise.main.Products -{ - internal class Cofee - { - } -} diff --git a/exercise.main/Products/Coffee.cs b/exercise.main/Products/Coffee.cs new file mode 100644 index 00000000..e8a8d337 --- /dev/null +++ b/exercise.main/Products/Coffee.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main.Products +{ + public class Coffee : IProduct + { + + private static readonly Dictionary VariantPrices = new Dictionary() + { + {"COFB", 0.99m}, // Black coffee + {"COFW", 1.19m}, // White coffee + {"COFC", 1.29m}, // Capuccino + {"COFL", 1.29m} // Latte + }; + + private static readonly Dictionary VariantNames = new Dictionary() + { + {"COFB", "Black"}, + {"COFW", "White"}, + {"COFC", "Capuccino"}, + {"COFL", "Latte"} + }; + + private string _id; + + public Coffee(string id) + { + _id = id; + } + public string Name => "Coffee"; + + public decimal Price + { + get + { + if (!VariantPrices.ContainsKey(_id)) + throw new ArgumentException($"Invalid coffee id: {_id}"); + decimal price = VariantPrices[_id]; // get the spesific coffee´s price + return price; + } + } + + public string Variant + { + get + { + if (!VariantNames.ContainsKey(_id)) + throw new ArgumentException($"Invalid coffee id: {_id}"); + return VariantNames[_id]; + } + } + + public string Id { get { return _id; } } + } +} diff --git a/exercise.main/Products/Filling.cs b/exercise.main/Products/Filling.cs index 425abd20..6d699837 100644 --- a/exercise.main/Products/Filling.cs +++ b/exercise.main/Products/Filling.cs @@ -8,6 +8,15 @@ namespace exercise.main.Products { public class Filling : IProduct { + private static readonly Dictionary VariantNames = new Dictionary() + { + {"FILB", "Bacon"}, + {"FILE", "Egg"}, + {"FILC", "Cheese"}, + {"FILX", "Creamy Cheese"}, + {"FILS", "Smoked Salmon"}, + {"FILH", "Ham"} + }; private string _id; @@ -19,8 +28,16 @@ public Filling(string id) public decimal Price => 0.12m; // price is the same for every filling variant - public string Variant { get; } + public string Variant + { + get + { + if (!VariantNames.ContainsKey(_id)) + throw new ArgumentException($"Invalid filling id: {_id}"); + return VariantNames[_id]; + } + } - public string Id => _id; + public string Id { get { return _id; } } } } From 2806e724390a309c3d74456a3c36599c7a25d933 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 08:14:45 +0200 Subject: [PATCH 22/38] updated domain model --- domainModel.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/domainModel.md b/domainModel.md index 8e86f99c..0d35295c 100644 --- a/domainModel.md +++ b/domainModel.md @@ -29,9 +29,10 @@ As a member of the public, So that I can not overfill my small bagel basket I'd like to know when my basket is full when I try adding an item beyond my basket capacity. ``` -| Classes | Methods/Properties | Scenario | Outputs | -|--------------|----------------------------------|------------------------------------------------------|-----------------| -| Basket | IsFull (property) | Check if basket item count exceeds basket capacity | bool | +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|---------------------------------------------------------------|-----------------| +| Basket | IsFull (property) | Check if basket item count exceeds basket capacity | bool | +| Basket | AddProduct(IProduct product) | Throws expection when trying to add product to full basket | exception | ``` 4. @@ -39,9 +40,9 @@ As a Bob's Bagels manager, So that I can expand my business, I’d like to change the capacity of baskets. ``` -| Classes | Methods/Properties | Scenario | Outputs | -|--------------|----------------------------------|---------------------------------------------------------------|-----------------| -| Basket | BasketCapacity (property) | Set basket capacity to value. Throw exception if value <= 0 | int | +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------|---------------------------------------------------------------|------------------| +| Basket | BasketCapacity (property) | Set basket capacity to value. Throw exception if value <= 0 | int or exception | ``` 5. @@ -79,9 +80,9 @@ As a customer, So I can shake things up a bit, I'd like to be able to choose fillings for my bagel. ``` -| Classes | Methods/Properties | Scenario | Outputs | -|--------------|---------------------------|---------------------|-----------------| -| Bagel | Filling (property) | Sets bagel filling | Filling | +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|----------------------------------------------------------------------|-------------------------------------------------------------------------------|---------------------------------------------------| +| Bagel | AddFillings(IEnumerable fillings, Inventory inventory) | Adds one or multiple fillings if the fillings are in inventory bagel filling | void (Bagel.Fillings updated or exception thrown | ``` 9. @@ -101,5 +102,5 @@ I want customers to only be able to order things that we stock in our inventory. ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|-----------------------------|---------------------------------------------------------------------------------------------------------|--------------| -| Inventory | IsInInventory | Before adding a bagel/cofee to the basket we check that the bagel/coffee variant is in the inventory | bool | +| Inventory | IsInInventory | Before adding a bagel/coffee to the basket we check that the bagel/coffee variant is in the inventory | bool | | Inventory | IsInInventory | Before adding a filling to a bagel we check that the filling variant is in the inventory | bool | \ No newline at end of file From 666c8fcf25574103a8450300da766ad0c8620715 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 08:29:09 +0200 Subject: [PATCH 23/38] made code cleaner --- exercise.main/Basket.cs | 7 ++----- exercise.main/Products/Bagel.cs | 3 +-- exercise.tests/CoreTests.cs | 2 +- exercise.tests/ReceiptExtentionTests.cs | 12 ++++++++++++ 4 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 exercise.tests/ReceiptExtentionTests.cs diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 018782e6..a53475b3 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -10,7 +10,7 @@ namespace exercise.main public class Basket { private List _basketItems = new List(); - private int _basketCapacity = 5; + private int _basketCapacity = 5; // default capacity of the basket private Inventory _inventory = new Inventory(); public Basket(Inventory inventory) @@ -61,8 +61,5 @@ public int BasketCapacity } public decimal BasketTotal { get { return _basketItems.Sum(product => product.Price); } } - } -} - - +} \ No newline at end of file diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 973e38e8..8a038174 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -70,6 +70,5 @@ public void AddFillings(IEnumerable fillings, Inventory inventory) _fillings.Add(filling); } } - } -} +} \ No newline at end of file diff --git a/exercise.tests/CoreTests.cs b/exercise.tests/CoreTests.cs index 5c339479..bda3ef34 100644 --- a/exercise.tests/CoreTests.cs +++ b/exercise.tests/CoreTests.cs @@ -162,7 +162,7 @@ public void BasketTotal2() // assert Assert.That(basketTotal != 0); - Assert.That(basketTotal, Is.EqualTo(1.34m)); + Assert.That(basketTotal, Is.EqualTo(1.34m)); // 0.49 (onion bagel) + 0.12 (bacon filling) + 0.12 (cheese filling) + 0.49 (sesame bagel) + 0.12 (cheese filling) = 1.34 } [Test] // user story 7 diff --git a/exercise.tests/ReceiptExtentionTests.cs b/exercise.tests/ReceiptExtentionTests.cs new file mode 100644 index 00000000..50e1f7ee --- /dev/null +++ b/exercise.tests/ReceiptExtentionTests.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.tests +{ + public class ReceiptExtentionTests + { + } +} From f3d45d33b6424dd10dab97469c3ad4e666a32554 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:09:43 +0200 Subject: [PATCH 24/38] written domain model description for receipt extension and added simple receipt print functionality --- domainModel.md | 17 +++++++++- exercise.main/Program.cs | 12 +++++-- exercise.main/Receipt.cs | 43 +++++++++++++++++++++++++ exercise.tests/ReceiptExtentionTests.cs | 1 + 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 exercise.main/Receipt.cs diff --git a/domainModel.md b/domainModel.md index 0d35295c..723dfe13 100644 --- a/domainModel.md +++ b/domainModel.md @@ -103,4 +103,19 @@ I want customers to only be able to order things that we stock in our inventory. | Classes | Methods/Properties | Scenario | Outputs | |--------------|-----------------------------|---------------------------------------------------------------------------------------------------------|--------------| | Inventory | IsInInventory | Before adding a bagel/coffee to the basket we check that the bagel/coffee variant is in the inventory | bool | -| Inventory | IsInInventory | Before adding a filling to a bagel we check that the filling variant is in the inventory | bool | \ No newline at end of file +| Inventory | IsInInventory | Before adding a filling to a bagel we check that the filling variant is in the inventory | bool | + +### RECEIPT EXTENTION +``` +11. +As a customer, +So I can track what I spend money on, +I want to revieve a receipt to my order. +``` +| Classes | Methods/Properties | Scenario | Outputs | +|----------|-----------------------------------|------------------------------------------|-----------------| +| Receipt | Print() | Print the receipt to the terminal | void | +| Receipt | Items (List) | List of items added to the basket | List | +| Receipt | TotalPrice (decimal) | Total cost of the order | decimal | +| Receipt | Timestamp (DateTime) | When the order was placed | DateTime | +| Receipt | ReceiptNumber (string/int) | Unique identifier for the receipt | string/int | \ No newline at end of file diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 3751555c..75d18c0f 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -1,2 +1,10 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); + +using exercise.main; +using exercise.main.Products; + +Inventory inventory = new Inventory(); +Basket basket = new Basket(inventory); +basket.AddProduct(new Bagel("BGLO")); + +Receipt receipt = new Receipt(basket); +receipt.Print(); \ No newline at end of file diff --git a/exercise.main/Receipt.cs b/exercise.main/Receipt.cs new file mode 100644 index 00000000..86537d1a --- /dev/null +++ b/exercise.main/Receipt.cs @@ -0,0 +1,43 @@ +using exercise.main.Products; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class Receipt + { + private string _header = " ~~~ Bob's Bagels ~~~"; + private string _thankuMessage = " Thank you/nfor your order!"; + private string _separationSymbol = "----------------------------"; + private Basket _basket; + // store order information in dictionary mapping from id to Iproduct.variant, name, amount ordered and price (amount ordered * price of one of this item) + + public Receipt(Basket basket) + { + _basket = basket; + DateTime = System.DateTime.Now; + } + + // method to loop through the items ordered (basket.basketItems) and store the information in the dictionary + + + // total price is retrieved from basket.BasketTotal + + public DateTime DateTime { get; set; } + + public void Print() + { + Console.WriteLine(_header); + Console.WriteLine(); + Console.WriteLine($" {DateTime}"); + Console.WriteLine(); + Console.WriteLine(_separationSymbol); + Console.WriteLine(); + + // print: $"{Iproduct.name} {iproduct.variant} tab {number of this item ordered} tab {price: base product price * amount ordered}" + } + } +} diff --git a/exercise.tests/ReceiptExtentionTests.cs b/exercise.tests/ReceiptExtentionTests.cs index 50e1f7ee..f64ba004 100644 --- a/exercise.tests/ReceiptExtentionTests.cs +++ b/exercise.tests/ReceiptExtentionTests.cs @@ -8,5 +8,6 @@ namespace exercise.tests { public class ReceiptExtentionTests { + // [Test] } } From 5656cd999cb67a904aae31f38a32884bcd45d863 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:19:57 +0200 Subject: [PATCH 25/38] implemented Receipt class and Print method. made the printing more estetic --- exercise.main/Products/Bagel.cs | 2 +- exercise.main/Program.cs | 24 ++++++++++ exercise.main/Receipt.cs | 62 +++++++++++++++++++------ exercise.tests/ReceiptExtentionTests.cs | 1 + 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 8a038174..92bd04cd 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -43,7 +43,7 @@ public decimal Price if (!VariantPrices.ContainsKey(_id)) throw new ArgumentException($"Invalid bagel id: {_id}"); decimal price = VariantPrices[_id]; // get the spesific bagel´s price - price += _fillings.Sum(f => f.Price); + price += _fillings.Sum(f => f.Price); // returns 0 if the bagel have no fillings return price; } } diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 75d18c0f..8a73a75c 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -4,7 +4,31 @@ Inventory inventory = new Inventory(); Basket basket = new Basket(inventory); +basket.BasketCapacity = 50; + +basket.AddProduct(new Bagel("BGLO")); basket.AddProduct(new Bagel("BGLO")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLP")); +basket.AddProduct(new Bagel("BGLE")); +basket.AddProduct(new Bagel("BGLE")); +basket.AddProduct(new Bagel("BGLE")); +basket.AddProduct(new Bagel("BGLE")); +basket.AddProduct(new Bagel("BGLE")); +basket.AddProduct(new Bagel("BGLE")); +basket.AddProduct(new Coffee("COFW")); +basket.AddProduct(new Coffee("COFW")); +basket.AddProduct(new Coffee("COFW")); Receipt receipt = new Receipt(basket); receipt.Print(); \ No newline at end of file diff --git a/exercise.main/Receipt.cs b/exercise.main/Receipt.cs index 86537d1a..e5b347a5 100644 --- a/exercise.main/Receipt.cs +++ b/exercise.main/Receipt.cs @@ -10,34 +10,70 @@ namespace exercise.main public class Receipt { private string _header = " ~~~ Bob's Bagels ~~~"; - private string _thankuMessage = " Thank you/nfor your order!"; + private string _thankuMessage1 = " Thank you"; + private string _thankuMessage2 = " for your order!"; private string _separationSymbol = "----------------------------"; private Basket _basket; - // store order information in dictionary mapping from id to Iproduct.variant, name, amount ordered and price (amount ordered * price of one of this item) + + // Dictionary to store the ordered items with associated details + private Dictionary orderDict = + new Dictionary(); public Receipt(Basket basket) { _basket = basket; - DateTime = System.DateTime.Now; + DateTime = DateTime.Now; } // method to loop through the items ordered (basket.basketItems) and store the information in the dictionary - - - // total price is retrieved from basket.BasketTotal + private void PopulateOrderDictionary() + { + orderDict.Clear(); + foreach (IProduct product in _basket.basketItems) + { + string key = product.Id; + if (orderDict.ContainsKey(key)) + { + // If the item already exists in the dictionary, increment the quantity and update subtotal + var existingItem = orderDict[key]; + existingItem.Quantity++; + existingItem.Subtotal += product.Price; + orderDict[key] = existingItem; + } + else + { + // If it's a new item, add it to the dictionary, base count 1 + orderDict[key] = (product.Name, product.Variant, 1, product.Price); + } + } + } public DateTime DateTime { get; set; } public void Print() { + PopulateOrderDictionary(); + Console.WriteLine(_header); - Console.WriteLine(); - Console.WriteLine($" {DateTime}"); - Console.WriteLine(); - Console.WriteLine(_separationSymbol); - Console.WriteLine(); + Console.WriteLine($"\n {DateTime}"); + Console.WriteLine($"\n{_separationSymbol}\n"); + + foreach (var item in orderDict) + { + var productDetails = item.Value; + string itemName = $"{productDetails.Variant} {productDetails.Name}".Trim(); + string qty = productDetails.Quantity.ToString(); + string subtotal = productDetails.Subtotal.ToString("£0.00"); + + Console.WriteLine("{0,-16} {1,3} {2,7}", itemName, qty, subtotal); + } - // print: $"{Iproduct.name} {iproduct.variant} tab {number of this item ordered} tab {price: base product price * amount ordered}" + Console.WriteLine($"\n{_separationSymbol}\n"); + string totalLabel = "Total:"; + string totalValue = _basket.BasketTotal.ToString("£0.00").PadLeft(28 - totalLabel.Length); + Console.WriteLine(totalLabel + totalValue); + Console.WriteLine($"\n{_thankuMessage1}"); + Console.WriteLine($"{_thankuMessage2}"); } } -} +} \ No newline at end of file diff --git a/exercise.tests/ReceiptExtentionTests.cs b/exercise.tests/ReceiptExtentionTests.cs index f64ba004..0efdcebe 100644 --- a/exercise.tests/ReceiptExtentionTests.cs +++ b/exercise.tests/ReceiptExtentionTests.cs @@ -9,5 +9,6 @@ namespace exercise.tests public class ReceiptExtentionTests { // [Test] + // check that something was printed } } From 8381527a59defbec931e407ee9acf6d4a1256bf8 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:30:06 +0200 Subject: [PATCH 26/38] added test for printing receipts: checking that something was actually printed --- exercise.tests/ReceiptExtentionTests.cs | 28 ++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/exercise.tests/ReceiptExtentionTests.cs b/exercise.tests/ReceiptExtentionTests.cs index 0efdcebe..f4fce09d 100644 --- a/exercise.tests/ReceiptExtentionTests.cs +++ b/exercise.tests/ReceiptExtentionTests.cs @@ -1,4 +1,6 @@ -using System; +using exercise.main; +using exercise.main.Products; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,7 +10,27 @@ namespace exercise.tests { public class ReceiptExtentionTests { - // [Test] - // check that something was printed + [Test] // user story 11, printing receipt works + public void PrintReceipt() + { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + Receipt receipt = new Receipt(basket); + + // redirect console output + var output = new StringWriter(); + Console.SetOut(output); + + // act + receipt.Print(); + + // assert + string printed = output.ToString(); + Assert.IsNotEmpty(printed); // Check that something actualy was printed + Assert.That(printed, Does.Contain("Bob's Bagels")); + } } } From bb4c10f543fb991c73205c74d3a3cae5766436d2 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:36:52 +0200 Subject: [PATCH 27/38] =?UTF-8?q?used=20CultureInfo.InvariantCulture=20to?= =?UTF-8?q?=20make=20it=20say=20=C2=A312.71=20and=20not=20=C2=A312,71?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exercise.main/Receipt.cs | 5 +++-- exercise.tests/ReceiptExtentionTests.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/exercise.main/Receipt.cs b/exercise.main/Receipt.cs index e5b347a5..413b3e06 100644 --- a/exercise.main/Receipt.cs +++ b/exercise.main/Receipt.cs @@ -1,6 +1,7 @@ using exercise.main.Products; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -63,14 +64,14 @@ public void Print() var productDetails = item.Value; string itemName = $"{productDetails.Variant} {productDetails.Name}".Trim(); string qty = productDetails.Quantity.ToString(); - string subtotal = productDetails.Subtotal.ToString("£0.00"); + string subtotal = productDetails.Subtotal.ToString("£0.00", CultureInfo.InvariantCulture); Console.WriteLine("{0,-16} {1,3} {2,7}", itemName, qty, subtotal); } Console.WriteLine($"\n{_separationSymbol}\n"); string totalLabel = "Total:"; - string totalValue = _basket.BasketTotal.ToString("£0.00").PadLeft(28 - totalLabel.Length); + string totalValue = _basket.BasketTotal.ToString("£0.00", CultureInfo.InvariantCulture).PadLeft(28 - totalLabel.Length); Console.WriteLine(totalLabel + totalValue); Console.WriteLine($"\n{_thankuMessage1}"); Console.WriteLine($"{_thankuMessage2}"); diff --git a/exercise.tests/ReceiptExtentionTests.cs b/exercise.tests/ReceiptExtentionTests.cs index f4fce09d..e7389ff8 100644 --- a/exercise.tests/ReceiptExtentionTests.cs +++ b/exercise.tests/ReceiptExtentionTests.cs @@ -33,4 +33,4 @@ public void PrintReceipt() Assert.That(printed, Does.Contain("Bob's Bagels")); } } -} +} \ No newline at end of file From 3bc9b620e5119a0bed88ad1eb39ecbf0cb0638fd Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:46:11 +0200 Subject: [PATCH 28/38] finished domain model description for receipt and finished implementing recepit extention --- domainModel.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/domainModel.md b/domainModel.md index 723dfe13..edf7cf83 100644 --- a/domainModel.md +++ b/domainModel.md @@ -112,10 +112,8 @@ As a customer, So I can track what I spend money on, I want to revieve a receipt to my order. ``` -| Classes | Methods/Properties | Scenario | Outputs | -|----------|-----------------------------------|------------------------------------------|-----------------| -| Receipt | Print() | Print the receipt to the terminal | void | -| Receipt | Items (List) | List of items added to the basket | List | -| Receipt | TotalPrice (decimal) | Total cost of the order | decimal | -| Receipt | Timestamp (DateTime) | When the order was placed | DateTime | -| Receipt | ReceiptNumber (string/int) | Unique identifier for the receipt | string/int | \ No newline at end of file +| Classes | Methods/Properties | Scenario | Outputs | +|----------|-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| +| Receipt | Print() | Print the receipt to the terminal | void | +| Receipt | PopulateOrderDictionary() | Loop through the items ordered (basket.basketItems) and store the information in the dictionary to track quantiy and subtotal | Dictionary | +| Receipt | DateTime (property) | When the order was placed | DateTime | From a6558dc85c1f64f57b833ada313a5df60ad3765e Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:52:07 +0200 Subject: [PATCH 29/38] updated domain model for discount extention --- domainModel.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/domainModel.md b/domainModel.md index edf7cf83..4999a9d3 100644 --- a/domainModel.md +++ b/domainModel.md @@ -117,3 +117,17 @@ I want to revieve a receipt to my order. | Receipt | Print() | Print the receipt to the terminal | void | | Receipt | PopulateOrderDictionary() | Loop through the items ordered (basket.basketItems) and store the information in the dictionary to track quantiy and subtotal | Dictionary | | Receipt | DateTime (property) | When the order was placed | DateTime | + +### DISCOUNT EXTENTION +``` +11. +As the manager, +When customers orders a lot I think they should recieve discount, +Special offers should be: +- 6 Onion Bagels for £2.49 +- 12 Plain Bagels for £3.99 +- 6 Everything Bagels for £2.49 +- A Black Coffee and whatever bagel for £1.25 +``` +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|---------------------------|-------------------------------------------------|-----------------| From 0214605ff5f0a4bf68b01a1e4e0a8c32795c0a38 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:02:05 +0200 Subject: [PATCH 30/38] started on tests for discount extention --- domainModel.md | 6 ++-- exercise.tests/DiscountExtentionTests.cs | 42 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 exercise.tests/DiscountExtentionTests.cs diff --git a/domainModel.md b/domainModel.md index 4999a9d3..4571fb9b 100644 --- a/domainModel.md +++ b/domainModel.md @@ -123,10 +123,8 @@ I want to revieve a receipt to my order. 11. As the manager, When customers orders a lot I think they should recieve discount, -Special offers should be: -- 6 Onion Bagels for £2.49 -- 12 Plain Bagels for £3.99 -- 6 Everything Bagels for £2.49 +Special offers should be: +- Every Bagel is available for the 6 for £2.49 and 12 for £3.99 offer, but fillings still cost the extra amount per bagel. - A Black Coffee and whatever bagel for £1.25 ``` | Classes | Methods/Properties | Scenario | Outputs | diff --git a/exercise.tests/DiscountExtentionTests.cs b/exercise.tests/DiscountExtentionTests.cs new file mode 100644 index 00000000..cb69e8de --- /dev/null +++ b/exercise.tests/DiscountExtentionTests.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.tests +{ + public class DiscountExtentionTests + { + [Test] // user story 12, Every Bagel should be available for the 6 for £2.49 + public void BuyingSixBagels() + { + + } + + [Test] // user story 12, Every Bagel should be available for the 12 for £3.99 + public void BuyingTwelveBagels() + { + + } + + [Test] // user story 12, A black coffee and a bagel should be available for £1.25 + public void BuyingBlackCoffeeAndBagel() + { + + } + + [Test] // user story 12, Full order discount test + public void DiscountedOrder() + { + //2x BGLO = 0.98 // not special price + //12x BGLP = 3.99 // special price + //6x BGLE = 2.49 // special price + //3x COF = 2.97 // 3 coffee is not discount + // ---- + // 10.43 total check + + } + + } +} From 59ca76b30a160487a981f2643353cdb7ff41cb21 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:23:51 +0200 Subject: [PATCH 31/38] added test, updated domain model and source code for discount extention --- domainModel.md | 6 +- exercise.main/Basket.cs | 49 ++++++++++- exercise.main/Products/Bagel.cs | 6 ++ exercise.tests/DiscountExtentionTests.cs | 107 ++++++++++++++++++++--- 4 files changed, 151 insertions(+), 17 deletions(-) diff --git a/domainModel.md b/domainModel.md index 4571fb9b..0eb62f42 100644 --- a/domainModel.md +++ b/domainModel.md @@ -125,7 +125,7 @@ As the manager, When customers orders a lot I think they should recieve discount, Special offers should be: - Every Bagel is available for the 6 for £2.49 and 12 for £3.99 offer, but fillings still cost the extra amount per bagel. -- A Black Coffee and whatever bagel for £1.25 ``` -| Classes | Methods/Properties | Scenario | Outputs | -|--------------|---------------------------|-------------------------------------------------|-----------------| +| Classes | Methods/Properties | Scenario | Outputs | +|--------------|---------------------------|-------------------------------------------------------------------------------|-----------------| +| Basket | BasketTotal (property) | Returns the total cost of products in basket, applies discounts if applicable | decimal | \ No newline at end of file diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index a53475b3..300fd556 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace exercise.main { @@ -60,6 +61,52 @@ public int BasketCapacity } } - public decimal BasketTotal { get { return _basketItems.Sum(product => product.Price); } } + + /// + /// Groups all bagels by SKU. + /// For each bagel group, apply the discount for every 6 bagels with same SKU, and adds the base bagel price for any leftovers. + /// Add the price of all other products as normal to BasketTotal + /// + public decimal BasketTotal + { + get + { + decimal total = 0m; + + // Group bagels by SKU + var bagelGroups = _basketItems + .Where(p => p is Bagel) + .Cast() + .GroupBy(b => b.Id); + + foreach (var group in bagelGroups) // loop through each group of bagels + { + int count = group.Count(); // count how many bagels of the same SKU are in the group + decimal basePrice = Bagel.GetBasePrice(group.Key); // get the base price of the bagel + + // 12-for-£3.99 + int setsOf12 = count / 12; + int remainderAfter12 = count % 12; + + // 6-for-£2.49 + int setsOf6 = remainderAfter12 / 6; + int remainder = remainderAfter12 % 6; + + total += setsOf12 * 3.99m; // add the price for every 12 bagels + total += setsOf6 * 2.49m; // add the price for every 6 bagels + total += remainder * basePrice; // add the price for any leftover bagels that do not fit into a 6 or 12 set + + // Sums the price of all fillings for all bagels in each group and adds it to the total. + total += group.SelectMany(b => b.Fillings).Sum(f => f.Price); + } + + // Add all non-bagel products (coffee, fillings) + total += _basketItems + .Where(p => p is not Bagel) + .Sum(p => p.Price); + + return total; + } + } } } \ No newline at end of file diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 92bd04cd..3b111598 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -70,5 +70,11 @@ public void AddFillings(IEnumerable fillings, Inventory inventory) _fillings.Add(filling); } } + + // Used when calculating BasketTotal since the discount applies to the bagel itself, not to any fillings. + public static decimal GetBasePrice(string id) + { + return VariantPrices.ContainsKey(id) ? VariantPrices[id] : 0m; + } } } \ No newline at end of file diff --git a/exercise.tests/DiscountExtentionTests.cs b/exercise.tests/DiscountExtentionTests.cs index cb69e8de..4ab46937 100644 --- a/exercise.tests/DiscountExtentionTests.cs +++ b/exercise.tests/DiscountExtentionTests.cs @@ -1,4 +1,6 @@ -using System; +using exercise.main; +using exercise.main.Products; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,35 +10,114 @@ namespace exercise.tests { public class DiscountExtentionTests { - [Test] // user story 12, Every Bagel should be available for the 6 for £2.49 + [Test] // user story 12, Every Bagel should be available for the 6 for £2.49. Must be 6 with same SKU public void BuyingSixBagels() { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.BasketCapacity = 10; // must adjust basket capacity + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + // act & assert + Assert.That(basket.BasketTotal, Is.EqualTo(2.49)); // True if discount was added } - [Test] // user story 12, Every Bagel should be available for the 12 for £3.99 + [Test] // user story 12, Every Bagel should be available for the 12 for £3.99. Must be 12 with same SKU public void BuyingTwelveBagels() { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.BasketCapacity = 12; // must adjust basket capacity + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + // act & assert + Assert.That(basket.BasketTotal, Is.EqualTo(3.99)); // True if discount was added } - [Test] // user story 12, A black coffee and a bagel should be available for £1.25 - public void BuyingBlackCoffeeAndBagel() + [Test] // user story 12, Full order discount test + public void DiscountedOrder1() { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.BasketCapacity = 30; // must adjust basket capacity + // add 2 onion bagels: price is 0.98 for 2 + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + // add 12 plain bagels: price is 3.99 for 12 + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + // add 6 everything bagels: price is 2.49 for 6 + basket.AddProduct(new Bagel("BGLE")); + basket.AddProduct(new Bagel("BGLE")); + basket.AddProduct(new Bagel("BGLE")); + basket.AddProduct(new Bagel("BGLE")); + basket.AddProduct(new Bagel("BGLE")); + basket.AddProduct(new Bagel("BGLE")); + // add 3 black coffees: price is 2.97 for 3 + basket.AddProduct(new Coffee("COFB")); + basket.AddProduct(new Coffee("COFB")); + basket.AddProduct(new Coffee("COFB")); + // act & assert + Assert.That(basket.BasketTotal, Is.EqualTo(10.43)); // True if discount was added } [Test] // user story 12, Full order discount test - public void DiscountedOrder() + public void DiscountedOrder2() { - //2x BGLO = 0.98 // not special price - //12x BGLP = 3.99 // special price - //6x BGLE = 2.49 // special price - //3x COF = 2.97 // 3 coffee is not discount - // ---- - // 10.43 total check + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.BasketCapacity = 30; // must adjust basket capacity + // add 16 plain bagels: price is £3.99 for 12 and £0.39 for each additional bagel + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + basket.AddProduct(new Bagel("BGLP")); + // act & assert + Assert.That(basket.BasketTotal, Is.EqualTo(5.55)); // True if discount was added } - } } From eab86e616413ce7c32fd9794f613f53c864c1a04 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:28:49 +0200 Subject: [PATCH 32/38] the receipt is now updated and shows subtotal and total with discount also being calculated --- exercise.main/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 8a73a75c..f2a26258 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -26,9 +26,9 @@ basket.AddProduct(new Bagel("BGLE")); basket.AddProduct(new Bagel("BGLE")); basket.AddProduct(new Bagel("BGLE")); -basket.AddProduct(new Coffee("COFW")); -basket.AddProduct(new Coffee("COFW")); -basket.AddProduct(new Coffee("COFW")); +basket.AddProduct(new Coffee("COFB")); +basket.AddProduct(new Coffee("COFB")); +basket.AddProduct(new Coffee("COFB")); Receipt receipt = new Receipt(basket); receipt.Print(); \ No newline at end of file From 039e92e12da5d3ab7fa89d5acf2e531e6677ba62 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:52:28 +0200 Subject: [PATCH 33/38] added new test for discount. chechking that no discount is added for only 5 bagels with same SKU and another with another SKU --- exercise.main/Basket.cs | 66 ++++++++++++++---------- exercise.main/Products/Bagel.cs | 2 +- exercise.main/Products/Coffee.cs | 2 +- exercise.tests/DiscountExtentionTests.cs | 20 ++++++- 4 files changed, 59 insertions(+), 31 deletions(-) diff --git a/exercise.main/Basket.cs b/exercise.main/Basket.cs index 300fd556..64f445ee 100644 --- a/exercise.main/Basket.cs +++ b/exercise.main/Basket.cs @@ -72,41 +72,51 @@ public decimal BasketTotal get { decimal total = 0m; + total += GetBagelDiscountTotal(); + total += GetNonBagelTotal(); + return total; + } + } + public decimal GetBagelDiscountTotal() + { + + decimal total = 0m; - // Group bagels by SKU - var bagelGroups = _basketItems - .Where(p => p is Bagel) - .Cast() - .GroupBy(b => b.Id); - - foreach (var group in bagelGroups) // loop through each group of bagels - { - int count = group.Count(); // count how many bagels of the same SKU are in the group - decimal basePrice = Bagel.GetBasePrice(group.Key); // get the base price of the bagel - - // 12-for-£3.99 - int setsOf12 = count / 12; - int remainderAfter12 = count % 12; + // Group bagels by SKU + var bagelGroups = _basketItems + .Where(p => p.Name is "Bagel") + .Cast() // Cast to Bagel to access specific properties + .GroupBy(b => b.Id); - // 6-for-£2.49 - int setsOf6 = remainderAfter12 / 6; - int remainder = remainderAfter12 % 6; + foreach (var group in bagelGroups) // loop through each group of bagels + { + int count = group.Count(); // count how many bagels of the same SKU are in the group + decimal basePrice = Bagel.GetBasePrice(group.Key); // get the base price of the bagel - total += setsOf12 * 3.99m; // add the price for every 12 bagels - total += setsOf6 * 2.49m; // add the price for every 6 bagels - total += remainder * basePrice; // add the price for any leftover bagels that do not fit into a 6 or 12 set + // 12-for-£3.99 + int setsOf12 = count / 12; + int remainderAfter12 = count % 12; - // Sums the price of all fillings for all bagels in each group and adds it to the total. - total += group.SelectMany(b => b.Fillings).Sum(f => f.Price); - } + // 6-for-£2.49 + int setsOf6 = remainderAfter12 / 6; + int remainder = remainderAfter12 % 6; - // Add all non-bagel products (coffee, fillings) - total += _basketItems - .Where(p => p is not Bagel) - .Sum(p => p.Price); + total += setsOf12 * 3.99m; // add the price for every 12 bagels + total += setsOf6 * 2.49m; // add the price for every 6 bagels + total += remainder * basePrice; // add the price for any leftover bagels that do not fit into a 6 or 12 set - return total; + // Sums the price of all fillings for all bagels in each group and adds it to the total. + total += group.SelectMany(b => b.Fillings).Sum(f => f.Price); } + return total; + } + + // Add all non-bagel products (coffee, fillings) + public decimal GetNonBagelTotal() + { + return _basketItems + .Where(p => p.Name is not "Bagel") + .Sum(p => p.Price); } } } \ No newline at end of file diff --git a/exercise.main/Products/Bagel.cs b/exercise.main/Products/Bagel.cs index 3b111598..74442725 100644 --- a/exercise.main/Products/Bagel.cs +++ b/exercise.main/Products/Bagel.cs @@ -71,7 +71,7 @@ public void AddFillings(IEnumerable fillings, Inventory inventory) } } - // Used when calculating BasketTotal since the discount applies to the bagel itself, not to any fillings. + // Used when calculating BasketTotal and adding discount, since the discount applies to the bagel itself, not to any fillings. public static decimal GetBasePrice(string id) { return VariantPrices.ContainsKey(id) ? VariantPrices[id] : 0m; diff --git a/exercise.main/Products/Coffee.cs b/exercise.main/Products/Coffee.cs index e8a8d337..9f6f5a4f 100644 --- a/exercise.main/Products/Coffee.cs +++ b/exercise.main/Products/Coffee.cs @@ -56,4 +56,4 @@ public string Variant public string Id { get { return _id; } } } -} +} \ No newline at end of file diff --git a/exercise.tests/DiscountExtentionTests.cs b/exercise.tests/DiscountExtentionTests.cs index 4ab46937..972f7759 100644 --- a/exercise.tests/DiscountExtentionTests.cs +++ b/exercise.tests/DiscountExtentionTests.cs @@ -28,6 +28,24 @@ public void BuyingSixBagels() Assert.That(basket.BasketTotal, Is.EqualTo(2.49)); // True if discount was added } + [Test] // user story 12, Buying 5 with same SKU and one with another SKU should not apply discount + public void BuyingFiveBagels() + { + // arrange + Inventory inventory = new Inventory(); + Basket basket = new Basket(inventory); + basket.BasketCapacity = 10; // must adjust basket capacity + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLO")); + basket.AddProduct(new Bagel("BGLP")); + + // act & assert + Assert.That(basket.BasketTotal, Is.EqualTo(2.84)); // 5 * 0.49 + 0.39 = 2.94, no discount applied + } + [Test] // user story 12, Every Bagel should be available for the 12 for £3.99. Must be 12 with same SKU public void BuyingTwelveBagels() { @@ -120,4 +138,4 @@ public void DiscountedOrder2() Assert.That(basket.BasketTotal, Is.EqualTo(5.55)); // True if discount was added } } -} +} \ No newline at end of file From 26805b49a5b2d21d7b48dc117fcdd4bf58cb2c65 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:53:16 +0200 Subject: [PATCH 34/38] small change to domain model for discount extention --- domainModel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domainModel.md b/domainModel.md index 0eb62f42..4263e2b2 100644 --- a/domainModel.md +++ b/domainModel.md @@ -120,7 +120,7 @@ I want to revieve a receipt to my order. ### DISCOUNT EXTENTION ``` -11. +12. As the manager, When customers orders a lot I think they should recieve discount, Special offers should be: From 5b360fe8b0c03ccf29f672bd476c2997f28be4d7 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:58:03 +0200 Subject: [PATCH 35/38] changed format of DateTime tostring and made some nice touches to the output of print receipt method --- exercise.main/Receipt.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercise.main/Receipt.cs b/exercise.main/Receipt.cs index 413b3e06..af6f0137 100644 --- a/exercise.main/Receipt.cs +++ b/exercise.main/Receipt.cs @@ -56,7 +56,7 @@ public void Print() PopulateOrderDictionary(); Console.WriteLine(_header); - Console.WriteLine($"\n {DateTime}"); + Console.WriteLine($"\n {DateTime.ToString("yyyy-MM-dd HH:mm:ss")}"); Console.WriteLine($"\n{_separationSymbol}\n"); foreach (var item in orderDict) @@ -70,7 +70,7 @@ public void Print() } Console.WriteLine($"\n{_separationSymbol}\n"); - string totalLabel = "Total:"; + string totalLabel = "Total"; string totalValue = _basket.BasketTotal.ToString("£0.00", CultureInfo.InvariantCulture).PadLeft(28 - totalLabel.Length); Console.WriteLine(totalLabel + totalValue); Console.WriteLine($"\n{_thankuMessage1}"); From a35918f934658224f20b554c6cec398e0bae8e13 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:26:03 +0200 Subject: [PATCH 36/38] added non implemented test for twilio receipt printer and implemented the twilioreceiptprinter class --- .../{Receipt.cs => ConsoleReceiptPrinter.cs} | 4 +-- exercise.main/IReceiptPrinter.cs | 13 +++++++++ exercise.main/Program.cs | 5 ++-- exercise.main/TwilioReceiptPrinter.cs | 28 +++++++++++++++++++ exercise.main/exercise.main.csproj | 4 +++ ...Tests.cs => ConsoleReceiptPrinterTests.cs} | 6 ++-- exercise.tests/TwilioReceiptPrinterTests.cs | 20 +++++++++++++ 7 files changed, 73 insertions(+), 7 deletions(-) rename exercise.main/{Receipt.cs => ConsoleReceiptPrinter.cs} (96%) create mode 100644 exercise.main/IReceiptPrinter.cs create mode 100644 exercise.main/TwilioReceiptPrinter.cs rename exercise.tests/{ReceiptExtentionTests.cs => ConsoleReceiptPrinterTests.cs} (82%) create mode 100644 exercise.tests/TwilioReceiptPrinterTests.cs diff --git a/exercise.main/Receipt.cs b/exercise.main/ConsoleReceiptPrinter.cs similarity index 96% rename from exercise.main/Receipt.cs rename to exercise.main/ConsoleReceiptPrinter.cs index af6f0137..69b84dd8 100644 --- a/exercise.main/Receipt.cs +++ b/exercise.main/ConsoleReceiptPrinter.cs @@ -8,7 +8,7 @@ namespace exercise.main { - public class Receipt + public class ConsoleReceiptPrinter : IReceiptPrinter { private string _header = " ~~~ Bob's Bagels ~~~"; private string _thankuMessage1 = " Thank you"; @@ -20,7 +20,7 @@ public class Receipt private Dictionary orderDict = new Dictionary(); - public Receipt(Basket basket) + public ConsoleReceiptPrinter(Basket basket) { _basket = basket; DateTime = DateTime.Now; diff --git a/exercise.main/IReceiptPrinter.cs b/exercise.main/IReceiptPrinter.cs new file mode 100644 index 00000000..5e93ecb1 --- /dev/null +++ b/exercise.main/IReceiptPrinter.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.main +{ + public interface IReceiptPrinter + { + void Print(); + } +} diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index f2a26258..9627dceb 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -30,5 +30,6 @@ basket.AddProduct(new Coffee("COFB")); basket.AddProduct(new Coffee("COFB")); -Receipt receipt = new Receipt(basket); -receipt.Print(); \ No newline at end of file +// Can change which receipt printer to use, either console or twilio +IReceiptPrinter consoleReceipt = new ConsoleReceiptPrinter(basket); +consoleReceipt.Print(); \ No newline at end of file diff --git a/exercise.main/TwilioReceiptPrinter.cs b/exercise.main/TwilioReceiptPrinter.cs new file mode 100644 index 00000000..d278fb26 --- /dev/null +++ b/exercise.main/TwilioReceiptPrinter.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Twilio; +using Twilio.Rest.Api.V2010.Account; +using System.Threading.Tasks; + +namespace exercise.main +{ + public class TwilioReceiptPrinter : IReceiptPrinter + { + private string _accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID"); + private string _authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN"); + public TwilioReceiptPrinter() { + TwilioClient.Init(_accountSid, _authToken); + } + + public async void Print() + { + var message = await MessageResource.CreateAsync( + body: "Join Earth's mightiest heroes. Like Kevin Bacon.", + from: new Twilio.Types.PhoneNumber("+15017122661"), + to: new Twilio.Types.PhoneNumber("+15558675310")); + } + } +} diff --git a/exercise.main/exercise.main.csproj b/exercise.main/exercise.main.csproj index fd4bd08d..2e5676af 100644 --- a/exercise.main/exercise.main.csproj +++ b/exercise.main/exercise.main.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/exercise.tests/ReceiptExtentionTests.cs b/exercise.tests/ConsoleReceiptPrinterTests.cs similarity index 82% rename from exercise.tests/ReceiptExtentionTests.cs rename to exercise.tests/ConsoleReceiptPrinterTests.cs index e7389ff8..c928d513 100644 --- a/exercise.tests/ReceiptExtentionTests.cs +++ b/exercise.tests/ConsoleReceiptPrinterTests.cs @@ -8,9 +8,9 @@ namespace exercise.tests { - public class ReceiptExtentionTests + public class ConsoleReceiptPrinterTests { - [Test] // user story 11, printing receipt works + [Test] // user story 11, printing receipt to console works public void PrintReceipt() { // arrange @@ -18,7 +18,7 @@ public void PrintReceipt() Basket basket = new Basket(inventory); basket.AddProduct(new Bagel("BGLO")); basket.AddProduct(new Bagel("BGLO")); - Receipt receipt = new Receipt(basket); + ConsoleReceiptPrinter receipt = new ConsoleReceiptPrinter(basket); // redirect console output var output = new StringWriter(); diff --git a/exercise.tests/TwilioReceiptPrinterTests.cs b/exercise.tests/TwilioReceiptPrinterTests.cs new file mode 100644 index 00000000..daef0355 --- /dev/null +++ b/exercise.tests/TwilioReceiptPrinterTests.cs @@ -0,0 +1,20 @@ +using exercise.main; +using exercise.main.Products; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace exercise.tests +{ + public class TwilioReceiptPrinterTests + { + [Test] // user story 13, printing receiptto twilio works + public void PrintReceipt() + { + // I have not implemented a test for this since it requires a live Twilio account and phone number and I don't have one. + Assert.Pass("Twilio receipt printing requires a live account and phone number, test not implemented."); + } + } +} From df1bc42d34715875d3932705121fe311b506cf6c Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:31:10 +0200 Subject: [PATCH 37/38] updated domain model for twilio extention --- domainModel.md | 26 +++++++++++++++++++------- exercise.main/IReceiptPrinter.cs | 2 +- exercise.main/TwilioReceiptPrinter.cs | 5 ++++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/domainModel.md b/domainModel.md index 4263e2b2..99a309c6 100644 --- a/domainModel.md +++ b/domainModel.md @@ -110,13 +110,13 @@ I want customers to only be able to order things that we stock in our inventory. 11. As a customer, So I can track what I spend money on, -I want to revieve a receipt to my order. +I want to revieve a receipt to my order trough the console ``` -| Classes | Methods/Properties | Scenario | Outputs | -|----------|-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| -| Receipt | Print() | Print the receipt to the terminal | void | -| Receipt | PopulateOrderDictionary() | Loop through the items ordered (basket.basketItems) and store the information in the dictionary to track quantiy and subtotal | Dictionary | -| Receipt | DateTime (property) | When the order was placed | DateTime | +| Classes | Methods/Properties | Scenario | Outputs | +|----------------------------------------------|-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| +| ConsoleReceiptPrinter | Print() | Print the receipt to the terminal/console | void | +| ConsoleReceiptPrinter | PopulateOrderDictionary() | Loop through the items ordered (basket.basketItems) and store the information in the dictionary to track quantiy and subtotal | Dictionary | +| ConsoleReceiptPrinter | DateTime (property) | When the order was placed | DateTime | ### DISCOUNT EXTENTION ``` @@ -128,4 +128,16 @@ Special offers should be: ``` | Classes | Methods/Properties | Scenario | Outputs | |--------------|---------------------------|-------------------------------------------------------------------------------|-----------------| -| Basket | BasketTotal (property) | Returns the total cost of products in basket, applies discounts if applicable | decimal | \ No newline at end of file +| Basket | BasketTotal (property) | Returns the total cost of products in basket, applies discounts if applicable | decimal | + +### TWILIO EXTENTION +``` +13. +As the manager, +When customers orders a lot I think they should recieve discount, +Special offers should be: +- Every Bagel is available for the 6 for £2.49 and 12 for £3.99 offer, but fillings still cost the extra amount per bagel. +``` +| Classes | Methods/Properties | Scenario | Outputs | +|----------------------------|---------------------------|---------------------------------|-----------------| +| TwilioReceiptPrinter | Print | Print the receipt to Twilio | void | \ No newline at end of file diff --git a/exercise.main/IReceiptPrinter.cs b/exercise.main/IReceiptPrinter.cs index 5e93ecb1..8263443d 100644 --- a/exercise.main/IReceiptPrinter.cs +++ b/exercise.main/IReceiptPrinter.cs @@ -10,4 +10,4 @@ public interface IReceiptPrinter { void Print(); } -} +} \ No newline at end of file diff --git a/exercise.main/TwilioReceiptPrinter.cs b/exercise.main/TwilioReceiptPrinter.cs index d278fb26..105197d0 100644 --- a/exercise.main/TwilioReceiptPrinter.cs +++ b/exercise.main/TwilioReceiptPrinter.cs @@ -9,6 +9,9 @@ namespace exercise.main { + /// + /// NB! I have not been able to test this class, as I do not have a Twilio account. + /// public class TwilioReceiptPrinter : IReceiptPrinter { private string _accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID"); @@ -25,4 +28,4 @@ public async void Print() to: new Twilio.Types.PhoneNumber("+15558675310")); } } -} +} \ No newline at end of file From 3bab7e53d06e6f01137e5dcd598fe57301be39d6 Mon Sep 17 00:00:00 2001 From: Mathias Handeland <127216029+MathiasHandeland@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:36:03 +0200 Subject: [PATCH 38/38] bobs bagels finito --- domainModel.md | 9 ++++----- exercise.main/Program.cs | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/domainModel.md b/domainModel.md index 99a309c6..d441c696 100644 --- a/domainModel.md +++ b/domainModel.md @@ -130,13 +130,12 @@ Special offers should be: |--------------|---------------------------|-------------------------------------------------------------------------------|-----------------| | Basket | BasketTotal (property) | Returns the total cost of products in basket, applies discounts if applicable | decimal | -### TWILIO EXTENTION +### TWILIO EXTENTION ATTEMPT ``` 13. -As the manager, -When customers orders a lot I think they should recieve discount, -Special offers should be: -- Every Bagel is available for the 6 for £2.49 and 12 for £3.99 offer, but fillings still cost the extra amount per bagel. +As a customer, +So I can track what I spend money on, +I want to revieve a receipt to my order trough twilio ``` | Classes | Methods/Properties | Scenario | Outputs | |----------------------------|---------------------------|---------------------------------|-----------------| diff --git a/exercise.main/Program.cs b/exercise.main/Program.cs index 9627dceb..d3a37c8e 100644 --- a/exercise.main/Program.cs +++ b/exercise.main/Program.cs @@ -1,6 +1,7 @@  using exercise.main; using exercise.main.Products; +using System.Reflection.Metadata; Inventory inventory = new Inventory(); Basket basket = new Basket(inventory); @@ -32,4 +33,22 @@ // Can change which receipt printer to use, either console or twilio IReceiptPrinter consoleReceipt = new ConsoleReceiptPrinter(basket); -consoleReceipt.Print(); \ No newline at end of file +consoleReceipt.Print(); + +// Should print something like this +// ~~~Bob's Bagels ~~~ + +// 2021 - 03 - 16 21:38:44 + +//---------------------------- + +//Onion Bagel 2 £0.98 +//Plain Bagel 12 £3.99 +//Everything Bagel 6 £2.49 +//Black Coffee 3 £2.97 + +//---------------------------- +//Total £10.43 + +// Thank you +// for your order! \ No newline at end of file