diff --git a/DOMAINMODEL.md b/DOMAINMODEL.md new file mode 100644 index 000000000..14be3368d --- /dev/null +++ b/DOMAINMODEL.md @@ -0,0 +1,43 @@ + +--- +# Domain Model – Bob’s Bagels + +| Class | Fields | Methods | What it does | Return values | +|--|----------------------------------------------------------------|----------------------------------|--------------------------------------------------|---------------------------------------| +| **Inventory** | `static Map items` | `has(sku): boolean` | If given SKU exists in inventory | `true` otherwise `false` if not exist | +| | | `priceOf(sku): double` | Looks up price of given SKU | `double` | +| | | `typeOf(sku): String` | Tells which type of item | `String` | +| | | `nameOf(sku): String` | Which name the SKU has | `String` | +| | | `variantOf(sku): String` | Which variant --> Onion, ham, latte | `String` | +| | | `allSkus(): ArrayList` | List all SKU | `ArrayList` | +| **ItemInfo** | `price: double`
`type: String`
`name: String`
`variant: String` | | container for SKU --> type, price, name, variant | | +| **BasketEntry** | `sku: String`
`qty: int` | `inc(n): void` | Increases quantity | `void` | +| | | `dec(n): void` | Decreases quanitiy | `void` | +| | | `lineTotal(): double` | Calculate sum | `double` | +| **Basket** | `capacity: int`
`entries: ArrayList` | `add(sku): String` | Tries to add item | `String` | +| | | `remove(sku): String` | Removes one item | `String` | +| | | `isFull(): boolean` | Check if basket is full | `boolean` | +| | | `setCapacity(newCap: int): void` | Change capacity (manager) | `void` | +| | | `total(): double` | Basket.total() --> loops line --> calls each entry.LineTotal --> adds them --> return the sum | `double` | +| | | `checkPrice(sku): double` | Looks up price | `double` | + + + + + +--- + +## User Stories + +1. **Add bagel to basket** +2. **Remove bagel from basket** +3. **Know when basket is full** +4. **Manager changes basket capacity** +5. **Remove non-existent item shows message** +6. **Total cost of basket** +7. **Cost of item before adding** +8. **Choose fillings for bagel** +9. **Know cost of fillings** +10. **Only order things in stock** + +--- diff --git a/src/main/java/com/booleanuk/core/Basket.java b/src/main/java/com/booleanuk/core/Basket.java new file mode 100644 index 000000000..a8267f4e6 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Basket.java @@ -0,0 +1,86 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.List; + +public class Basket { + + private int capacity; + private final List lines = new ArrayList<>(); + private final Inventory inventory = new Inventory(); + + public Basket(int capacity) { + setCapacity(capacity); + } + + public Basket() { + this(5); + } + + public String addItem(String sku) { + if (!Inventory.has(sku)){ + return "Not in Stock"; + } + + if (isFull()) { + return "Basket is full"; + } + + lines.add(new BasketItem(sku,1)); + return "Added"; + } + + public String removeItem(String sku) { + for (int i = 0; i < lines.size(); i++) { + BasketItem line = lines.get(i); + if (line.getSku().equals(sku)) { + if (line.getQuantity() > 1) { + line.setQuantity(line.getQuantity() - 1); + } else { + lines.remove(i); + } + return "Removed"; + } + } + return "Item not in basket"; + } + + public boolean isFull() { + if (lines.size() >= capacity) { + return true; + } + return false; + + } + + public void setCapacity(int capacity) { + this.capacity = capacity; + + } + + + public double total() { + double sum = 0.0; + for (BasketItem item : lines) { + ItemInfo info = Inventory.items.get(item.getSku()); + if (info != null) { + sum += info.getPrice() * item.getQuantity(); + } + } + return sum; + } + + public double checkPrice(String sku) { + if(!inventory.items.containsKey(sku)){ + throw new IllegalArgumentException("invalid sku" + sku); + } + return inventory.priceOf(sku); + } + + public int getCapacity() { + return capacity; + } +} + +// Basket.total() --> loops line --> calls each entry.LineTotal --> adds them --> return the sum + diff --git a/src/main/java/com/booleanuk/core/BasketItem.java b/src/main/java/com/booleanuk/core/BasketItem.java new file mode 100644 index 000000000..c494f5a2b --- /dev/null +++ b/src/main/java/com/booleanuk/core/BasketItem.java @@ -0,0 +1,47 @@ +package com.booleanuk.core; + +public class BasketItem { + private String sku; + private int quantity; + + public BasketItem(String sku, int quantity) { + this.sku = sku; + this.quantity = quantity; + } + + public String getSku() { + return sku; + } + + public int getQuantity() { + return quantity; + } + + public void setSku(String sku) { + this.sku = sku; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + + public void increaseQuantity(int quantity){ + if (quantity <= 0){ + throw new IllegalArgumentException("Amount must be greater than zero."); + } + this.quantity += quantity; + } + + public void decreaseQuantity(int quantity){ + if (quantity <= 0){ + throw new IllegalArgumentException("amount must be greater than zero."); + } + this.quantity -= quantity; + } + + public double lineSumTotal(){ + Inventory inventory = new Inventory(); + return this.quantity * inventory.priceOf(this.sku); + } +} diff --git a/src/main/java/com/booleanuk/core/Inventory.java b/src/main/java/com/booleanuk/core/Inventory.java new file mode 100644 index 000000000..f0db0a8d7 --- /dev/null +++ b/src/main/java/com/booleanuk/core/Inventory.java @@ -0,0 +1,70 @@ +package com.booleanuk.core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class Inventory { + + static Map items = new HashMap<>(); + + static { + // BAGEL + items.put("BGLO", new ItemInfo("Bagel", "BAGEL", 0.49, "Onion" )); + items.put("BGLP", new ItemInfo("Bagel", "BAGEL", 0.39, "Plain" )); + items.put("BGLE", new ItemInfo("Bagel", "BAGEL", 0.49, "Everything" )); + items.put("BGLS", new ItemInfo("Bagel", "BAGEL", 0.49, "Sesame" )); + + //COFFEE + items.put("COFB", new ItemInfo("Coffe", "COFFEE", 0.99, "Black")); + items.put("COFW", new ItemInfo("Coffe", "COFFEE", 1.19, "White")); + items.put("COFC", new ItemInfo("Coffe", "COFFEE", 1.29, "Capuccino")); + items.put("COFL", new ItemInfo("Coffe", "COFFEE", 1.29, "Latte")); + + //FILLING + items.put("FILB", new ItemInfo("Filling", "FILLING", 0.12, "Bacon" )); + items.put("FILE", new ItemInfo("Filling", "FILLING", 0.12, "Egg" )); + items.put("FILC", new ItemInfo("Filling", "FILLING", 0.12, "Cheese" )); + items.put("FILX", new ItemInfo("Filling", "FILLING", 0.12, "Cream Cheese" )); + items.put("FILS", new ItemInfo("Filling", "FILLING", 0.12, "Smoked Salmon" )); + items.put("FILH", new ItemInfo("Filling", "FILLING", 0.12, "Ham" )); + } + + + public static boolean has(String sku) { + return items.containsKey(sku); + } + + public double priceOf(String sku) { + ItemInfo info = items.get(sku); + return info != null ? info.getPrice() : 0.0; + } + + public String typeOf(String sku){ + ItemInfo info = items.get(sku); + if (info == null){ + throw new IllegalArgumentException("invalid sku: " + sku); + } + return info.getType(); + } + + public String nameOf(String sku){ + ItemInfo info = items.get(sku); + if (info == null){ + throw new IllegalArgumentException("invalid sku: " + sku); + } + return info.getName(); + } + + public String variantOf(String sku) { + ItemInfo info = items.get(sku); + return info != null ? info.getVariant() : null; + + } + + public ArrayList allSkus(){ + return new ArrayList<>(items.keySet()); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/booleanuk/core/ItemInfo.java b/src/main/java/com/booleanuk/core/ItemInfo.java new file mode 100644 index 000000000..14a0f95a0 --- /dev/null +++ b/src/main/java/com/booleanuk/core/ItemInfo.java @@ -0,0 +1,34 @@ +package com.booleanuk.core; + +public class ItemInfo { + private String name; + private String type; + private double price; + private String variant; + + + public ItemInfo(String name, String type, double price, String variant) { + this.name = name; + this.type = type; + this.price = price; + this.variant = variant; + } + + + public String getName() { + return name; + } + + public String getVariant() { + return variant; + } + + public double getPrice() { + return price; + } + + public String getType() { + return type; + } + +} diff --git a/src/test/java/com/booleanuk/core/BasketItemTest.java b/src/test/java/com/booleanuk/core/BasketItemTest.java new file mode 100644 index 000000000..adc12ec49 --- /dev/null +++ b/src/test/java/com/booleanuk/core/BasketItemTest.java @@ -0,0 +1,45 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BasketItemTest { + + @Test + public void testConstructor(){ + String expectedSku = "sku"; + int expectedQuantity = 1; + + BasketItem basketItem = new BasketItem(expectedSku, expectedQuantity); + String actualSku = basketItem.getSku(); + int actualQuantity = basketItem.getQuantity(); + + Assertions.assertEquals(expectedSku, actualSku); + + } + + @Test + public void testIfQuantityIncrease(){ + String expectedSku = "BGLO"; + BasketItem basketItem = new BasketItem(expectedSku, 1); + + basketItem.increaseQuantity(1); + Assertions.assertEquals(2, basketItem.getQuantity()); + } + + @Test + public void testIfQuantityDecrease(){ + String expectedSku = "BGLO"; + BasketItem basketItem = new BasketItem(expectedSku, 2); + basketItem.decreaseQuantity(1); + Assertions.assertEquals(1, basketItem.getQuantity()); + } + + @Test + public void testLineSumOfTotal(){ + BasketItem basketItem = new BasketItem("BGLO", 2); + double expected = 2 * 0.49; + + Assertions.assertEquals(expected, basketItem.lineSumTotal()); + } +} diff --git a/src/test/java/com/booleanuk/core/BasketTest.java b/src/test/java/com/booleanuk/core/BasketTest.java new file mode 100644 index 000000000..0c43a89bd --- /dev/null +++ b/src/test/java/com/booleanuk/core/BasketTest.java @@ -0,0 +1,66 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BasketTest { + + @Test + public void ConstructorStartEmptySetsCapacity() { + Basket basket = new Basket(5); + + Assertions.assertEquals(5, basket.getCapacity()); + Assertions.assertFalse(basket.isFull()); + } + + @Test + public void zeroCapicityIsFull() { + Basket basket = new Basket(0); + Assertions.assertEquals(0, basket.getCapacity()); + Assertions.assertTrue(basket.isFull()); + } + + @Test + public void addNewItem_createsLine_andAffectsTotal() { + Basket basket = new Basket(5); + + String msg = basket.addItem("BGLO"); // 0.49 + Assertions.assertEquals("Added", msg); + Assertions.assertEquals(0.49, basket.total(), 1e-6); + Assertions.assertFalse(basket.isFull()); + } + @Test + public void addSkuIncrementQtyAffectTotal() { + Basket basket = new Basket(5); + basket.addItem("BGLO"); + basket.addItem("BGLO"); + + Assertions.assertEquals(0.98, basket.total(), 1e-6); + } + + @Test + void remove_decrements_thenRemoves_andMessages() { + Basket basket = new Basket(5); + + basket.addItem("BGLO"); + basket.addItem("BGLO"); + + String msg1 = basket.removeItem("BGLO"); + Assertions.assertEquals("Removed", msg1); + Assertions.assertEquals(0.49, basket.total(), 1e-6); + + String msg2 = basket.removeItem("BGLO"); + Assertions.assertEquals("Removed", msg2); + Assertions.assertEquals(0.0, basket.total(), 1e-6); + + Assertions.assertEquals("Item not in basket", basket.removeItem("BGLO")); + } + + @Test + void checkPrice_delegatesToInventory() { + Basket basket = new Basket(5); + Assertions.assertEquals(0.49, basket.checkPrice("BGLO"), 1e-6); + Assertions.assertEquals(1.19, basket.checkPrice("COFW"), 1e-6); + } + +} diff --git a/src/test/java/com/booleanuk/core/InventoryTest.java b/src/test/java/com/booleanuk/core/InventoryTest.java new file mode 100644 index 000000000..3b491a60e --- /dev/null +++ b/src/test/java/com/booleanuk/core/InventoryTest.java @@ -0,0 +1,86 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Collections; + +public class InventoryTest { + + @Test + public void returnTrueForValidSku() { + Inventory inventory = new Inventory(); + String validSku = "BGLO"; + + Assertions.assertTrue(inventory.has(validSku)); + } + + @Test + void has_returnsTrueForValidSku() { + Assertions.assertTrue(Inventory.has("BGLO")); // static call + } + + @Test + void has_returnsFalseForInvalidSku() { + Assertions.assertFalse(Inventory.has("BGLL")); // static call + } + + @Test + public void returnFalseForInvalidSku() { + Inventory inventory = new Inventory(); + String invalidSku = "BGLL"; + Assertions.assertFalse(inventory.has(invalidSku)); + } + + @Test + public void returnPriceOfValidSku() { + Inventory inventory = new Inventory(); + String validSku = "BGLO"; + double price = 0.49; + + double result = inventory.priceOf(validSku); + + Assertions.assertEquals(price, result); + } + + @Test + public void returnPriceOfInvalidSku() { + Inventory inventory = new Inventory(); + double inValidPrice = inventory.priceOf("BGLL"); + Assertions.assertFalse(inValidPrice > 0); + } + + @Test + public void returnNameOfValidSku() { + Inventory inventory = new Inventory(); + + String validSku = "BGLO"; + String name = inventory.nameOf(validSku); + Assertions.assertEquals("Bagel", name); + } + + @Test + public void returnNameOfInvalidSku() { + Inventory inventory = new Inventory(); + Assertions.assertThrows(IllegalArgumentException.class, + () -> inventory.nameOf("NON EXIST SKU")); + } + + @Test + public void returnVariantOfValidSku() { + Inventory inventory = new Inventory(); + String sku = "BGLO"; + + String variant = inventory.variantOf(sku); + Assertions.assertEquals("Onion", variant); + } + + @Test + public void returnVariantOfInvalidSku() { + Inventory inventory = new Inventory(); + String invalidSku = "Onion"; + String variant = inventory.variantOf(invalidSku); + Assertions.assertNull(variant); + } +} diff --git a/src/test/java/com/booleanuk/core/ItemInfoTest.java b/src/test/java/com/booleanuk/core/ItemInfoTest.java new file mode 100644 index 000000000..1781c5d70 --- /dev/null +++ b/src/test/java/com/booleanuk/core/ItemInfoTest.java @@ -0,0 +1,27 @@ +package com.booleanuk.core; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ItemInfoTest { + + @Test + public void testGetItem() { + String expectedName = "Bagel"; + String expectedType = "BAGEL"; + double expectedPrice = 0.49; + String expectedVariant = "Onion"; + + ItemInfo itemInfo = new ItemInfo(expectedName, expectedType, expectedPrice, expectedVariant ); + String actualName = itemInfo.getName(); + String actualType = itemInfo.getType(); + double actualPrice = itemInfo.getPrice(); + String actualVariant = itemInfo.getVariant(); + + Assertions.assertEquals(expectedName, actualName); + Assertions.assertEquals(expectedType, actualType); + Assertions.assertEquals(expectedPrice, actualPrice); + Assertions.assertEquals(expectedVariant, actualVariant); + + } +}