Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This is how far i got, will continue soon #63

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a4eefe5
create-project-structure-and-domain-model
JHalvor Aug 16, 2024
2fcce95
setup-class-structures
JHalvor Aug 16, 2024
db1856f
removed-domainmodel-ms-name
JHalvor Aug 16, 2024
135e982
Fixups-and-add-item-to-basket-test
JHalvor Aug 16, 2024
ac46ec2
Making-add-item-to-basket-test-pass
JHalvor Aug 16, 2024
5900463
Add-RemoveItemFromBasket-Test
JHalvor Aug 16, 2024
ea155a3
Make-TestRemoveItemFromBasket-pass
JHalvor Aug 16, 2024
1b74606
add-sumtestforbasket
JHalvor Aug 16, 2024
a9d0663
add-sumtestforbasket-pass
JHalvor Aug 16, 2024
7cd66ac
small-refactor
JHalvor Aug 16, 2024
f4f3e82
add-changebasketcapacity-test
JHalvor Aug 16, 2024
41f6d22
add-changebasketcapacity-test-pass
JHalvor Aug 16, 2024
cb8e48e
add-test-for-getitemfrominventory
JHalvor Aug 16, 2024
fde12ef
work-in-progress
JHalvor Aug 16, 2024
b766964
Make-TestGetItemFromInventory-pass
JHalvor Aug 16, 2024
af341eb
add-view-inventory
JHalvor Aug 16, 2024
35ffe7e
Exercise-core-complete
JHalvor Aug 19, 2024
04cdef0
Exercise-extension2-add-domain-model-and-user-stories
JHalvor Aug 19, 2024
fa56eb1
Extension2-add-TestAddItemToReceipt
JHalvor Aug 19, 2024
1572eee
Extension2-generate-receipt
JHalvor Aug 19, 2024
d94425b
Extension2-add-view-profits
JHalvor Aug 19, 2024
f642f7d
Extension2-complete
JHalvor Aug 19, 2024
8c8225d
Extension2-complete
JHalvor Aug 20, 2024
fd7cde5
Extension1&3-work-in-progress
JHalvor Aug 20, 2024
5c4b13f
Exercise1&3-work-in-progress
JHalvor Aug 21, 2024
df5935b
Extension1&3-complete
JHalvor Aug 21, 2024
2044c57
Exercise4-complete
JHalvor Aug 22, 2024
de8cb2a
Updated-Class-Diagram
JHalvor Aug 22, 2024
22b0112
removed-phonenumber-from-smscontroller
JHalvor Aug 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions DomainModel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Domain Model - Core

- 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.
- As a member of the public, So I can change my order, I'd like to remove a bagel from my basket.
- 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.
- As a Bob's Bagels manager, So that I can expand my business, I�d like to change the capacity of baskets.
- 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.
- As a customer, So I know how much money I need, I'd like to know the total cost of items in my basket.
- 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.
- As a customer, So I can shake things up a bit, I'd like to be able to choose fillings for my bagel.
- 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.
- 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.


| **Classes** | **Members** | **Methods** | **Scenario** | **Outputs** |
|:--:|:--:|:--:|:--:|:--:|
| `Basket` | `Dictionary<Item, int> _items (value is num of same item in basket)` | `AddItem(Item item)` | Add item to basket | `true` |
| `Basket` | `Dictionary<Item, int> _items, int basketCapacity` | `AddItem(Item item)` | Add item to basket when basket is full | `false` |
| `Basket` | `Dictionary<Item, int> _items` | `RemoveItem(Item item)` | Remove item from basket | `true` |
| `Basket` | `Dictionary<Item, int> _items` | `RemoveItem(Item item)` | Remove item from basket that doesn't exist in basket | `false` |
| `Basket` | `int basketCapacity` | `ChangeCapacity(int capacity, User user)` | As manager change basket capacity | `true` |
| `Basket` | `Dictionary<Item, int> _items` | `SumOfItemCosts()` | Get sum of total cost of items in basket | `float` |
| `BobsBagelStore` | `List<Item> _inventory` | `GetItem(string sku)` | Get item from inventory | `true` |
| `BobsBagelStore` | `List<Item> _inventory` | `ViewInventory()` | View products in store to choose wanted name and variant | `Console + bool` |
| `BobsBagelStore` | `List<Item> _inventory` | `ViewInventory()` | View products with prices | `Console + bool` |
| `Item` | float Price | | Get price of item | `float` |


# Domain Model - Extension 2: Receipts
- As a customer, So i know which items im paying for, I'd like to get a receipt when checking out with the items in my basket.
- As a customer, So i know how much money i need to pay, I'd like get a total sum of the cost of all the items in my receipt.
- As a manager, So i know how the business of the store is going, I'd like to view total profit from customers today.

| **Classes** | **Members** | **Methods** | **Scenario** | **Outputs** |
|:--:|:--:|:--:|:--:|:--:|
| `BobsBagelStore` | `List<Receipt> _receipts` | `GenerateReceipt(Basket basket)` | Generate receipt from items in basket | `Receipt?` |
| `Receipt` | `Basket _relatedBasket` | `PrintReceipt(Item item)` | Print out receipt to terminal | `Console` |
| `BobsBagelStore` | `List<Receipt> _receipts` | `ViewProfits()` | View total profits today | `Console + float` |


# Domain Model - Extension 1 & 3: Discounts on receipt
- As a customer, So im able to save money, I'd like to take advantage of special offers available in the store.

| **Classes** | **Members** | **Methods** | **Scenario** | **Outputs** |
|:--:|:--:|:--:|:--:|:--:|
| `Item` | `List<Receipt> _receipts` | `GenerateReceipt(Basket basket)` | Generate receipt from items in basket | `Receipt?` |
| `Receipt` | `Basket _relatedBasket` | `PrintReceipt(Item item)` | Print out receipt to terminal | `Console` |
| `BobsBagelStore` | `List<Receipt> _receipts` | `ViewProfits()` | View total profits today | `Console + float` |
94 changes: 94 additions & 0 deletions exercise.main/Basket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace exercise.main
{
public class Basket
{
private int _basketCapacity;
private Dictionary<Item, int> _items;

public Basket(int basketCapacity = 3)
{
_items = new Dictionary<Item, int>();
_basketCapacity = basketCapacity;
}

public bool AddItem(Item newItem)
{
if (_basketCapacity <= _items.Sum(item => item.Value))
{
Console.WriteLine("Basket capacity reached, can't add more items!");
return false;
}

Item? itemFound = GetItem(newItem.SKU);
if (itemFound == null)
{
_items.Add(newItem, 1);
return true;
}
else
{
_items[itemFound]++;
return true;
}
}

public Item? GetItem(string sku)
{
List<Item> itemsFound = _items.Where(item => item.Key.SKU == sku).Select(item => item.Key).ToList();
if (itemsFound.Count == 0) return null;
return itemsFound[0];
}

public bool RemoveItem(string sku)
{
Item? itemFound = GetItem(sku);
if (itemFound == null)
{
Console.WriteLine("Item not found!");
return false;
}

if (_items[itemFound] > 1)
{
_items[itemFound]--;
}
else
{
_items.Remove(itemFound);
}
return true;
}

public float SumOfItemCosts()
{
float sum = 0f;
foreach (var item in _items)
{
sum += item.Key.Price * item.Value;
}
return sum;
}

public bool ChangeCapacity(int basketCapacity, User user)
{
if (user.Role == Role.Customer)
{
return false;
}
if (basketCapacity < _items.Sum(item => item.Value))
{
return false;
}
_basketCapacity = basketCapacity;
return true;
}

public Dictionary<Item, int> Items { get { return _items; } }
}
}
184 changes: 184 additions & 0 deletions exercise.main/BobsBagelStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Twilio.TwiML.Messaging;

namespace exercise.main
{
public class BobsBagelStore
{
private int _receiptIDs = 0;
private List<Item> _inventory;
private List<Basket> _baskets;
private List<Receipt> _receipts;
private List<Order> _orders;

public BobsBagelStore()
{
_inventory = new List<Item>();
_baskets = new List<Basket>();
_receipts = new List<Receipt>();
_orders = new List<Order>();
}

public bool AddReceipt(Basket basket, Receipt newReceipt)
{
if (basket == null)
{
return false;
}

_receiptIDs++;

if (_baskets.Where(x => x == basket).Count() == 0)
{
AddBasket(basket);
}

newReceipt.ID = _receiptIDs;

_receipts.Add(newReceipt);
return true;
}

public bool AddBasket(Basket basket)
{
if (basket == null) return false;
if (_baskets.Contains(basket)) return false;
_baskets.Add(basket);
return true;
}

public Item? GetItem(string sku)
{
return _inventory.Find(item => item.SKU == sku);
}

public void StockUpInventory()
{
_inventory = new List<Item>();
_inventory.Add(new Item("BGLO", 0.49f, "Bagel", "Onion"));
_inventory.Add(new Item("BGLP", 0.39f, "Bagel", "Plain"));
_inventory.Add(new Item("BGLE", 0.49f, "Bagel", "Everything"));
_inventory.Add(new Item("BGLS", 0.49f, "Bagel", "Sesame"));
_inventory.Add(new Item("COFB", 0.99f, "Coffee", "Black"));
_inventory.Add(new Item("COFW", 1.19f, "Coffee", "White"));
_inventory.Add(new Item("COFC", 1.29f, "Coffee", "Capuccino"));
_inventory.Add(new Item("COFL", 1.29f, "Coffee", "Latte"));
_inventory.Add(new Item("FILB", 0.12f, "Filling", "Bacon"));
_inventory.Add(new Item("FILE", 0.12f, "Filling", "Egg"));
_inventory.Add(new Item("FILC", 0.12f, "Filling", "Cheese"));
_inventory.Add(new Item("FILX", 0.12f, "Filling", "Cream Cheese"));
_inventory.Add(new Item("FILS", 0.12f, "Filling", "Smoked Salmon"));
_inventory.Add(new Item("FILH", 0.12f, "Filling", "Ham"));
}

public string ViewInventory()
{
StringBuilder message = new StringBuilder();

if (_inventory.Count == 0)
{
message.Append("No items in inventory!");
Console.Write(message.ToString());
return message.ToString();
}

message.Append("| SKU | Price | Name | Variant |\n");
message.Append("|------|-------|---------|---------------|\n");

foreach (Item item in _inventory)
{
message.Append($"| {item.SKU} ");
message.Append(string.Format("| {0:C2} ", item.Price.ToString("C", new CultureInfo("en-GB"))));

message.Append(string.Format("| {0} ", item.Name.Length > 8 ? item.Name.Substring(0, 8) : item.Name));
int spacesAmount = 7 - item.Name.Length;
for (int i = 0; i < spacesAmount; i++) { message.Append(" "); }

message.Append(string.Format("| {0} ", item.Variant.Length > 13 ? item.Variant.Substring(0, 13) : item.Variant));
spacesAmount = 13 - item.Variant.Length;
for (int i = 0; i < spacesAmount; i++) { message.Append(" "); }

message.Append("|\n");
}
message.Append("\n\n\n");
Console.Write(message.ToString());
return message.ToString();
}

public float ViewProfits()
{
float profits = 0;
foreach (Receipt receipt in _receipts)
{
foreach (Item item in receipt.Items.Keys)
{
profits += item.Price * receipt.Items[item];
}
}
Console.WriteLine($"Todays profits came to a total of {profits}£");
return profits;
}

public string MakeOrder(Receipt receipt)
{
Order order = new Order(receipt);
_orders.Add(order);
StringBuilder orderMessage = new StringBuilder();

orderMessage.Append(" ~~~ Order Created ~~~\n\n");
orderMessage.Append($"Items Ordered at {order.OrderDate}\n".PadRight(5));
orderMessage.Append($"Estimated delivery time is {order.DeliveryTime} minutes\n");
orderMessage.Append($"at {order.DeliveryDate.Hour}:{order.DeliveryDate.Minute}\n".PadLeft(5));
orderMessage.Append($"\nOrder receipt is\n");

Console.WriteLine(orderMessage.ToString());

orderMessage.Insert(0, receipt.PrintReceipt());

return orderMessage.ToString();
}

public string PrintOrderHistory()
{
int counter = 0;
StringBuilder orderHistory = new StringBuilder();
orderHistory.Append(" ~~~ Order History ~~~\n\n");
foreach (Order order in _orders)
{
counter++;
orderHistory.Append($"Order {counter} from {order.OrderDate}\n");
orderHistory.Append($"Delivered at {order.DeliveryDate}\n\n");
orderHistory.Append($"With items:\n");
orderHistory.Append(new string('-', 33) + '\n');
orderHistory.Append($"{order.BelongingReceipt.CalculateItems()}");
orderHistory.Append(new string('-', 33) + '\n');
orderHistory.Append($"Total\t\t".PadRight(18));
orderHistory.Append($"£{float.Round(order.BelongingReceipt.Total, 2)}\n");
if (order.BelongingReceipt.TotalDiscount > 0f)
{
orderHistory.Append($"Total saved\t\t".PadRight(16));
orderHistory.Append($"£{float.Round(order.BelongingReceipt.TotalDiscount, 2)}\n");
}
orderHistory.Append(new string('~', 33) + "\n\n\n");
}

Console.WriteLine(orderHistory);

return orderHistory.ToString();
}

public List<Basket> Baskets { get { return _baskets; } }
public List<Item> Inventory { get { return _inventory; } }
public List<Receipt> Receipts { get { return _receipts; } }
public List<Order> Orders { get { return _orders; } }
}
}
67 changes: 67 additions & 0 deletions exercise.main/ClassDiagram.cd
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="exercise.main.Basket">
<Position X="7" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAABAAAAAgACEAAAAAAAAAAgBAAAAAEAAAAAAAACAA=</HashCode>
<FileName>Basket.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.BobsBagelStore">
<Position X="0.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAUAAAAQAAGAAEAAAAAAAAABQBAAAACAEIAACkABAAA=</HashCode>
<FileName>BobsBagelStore.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.Discount">
<Position X="9" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AABAAAAAAABAAAAAAAACAAACAgEAAAAAAAAAAAAAAgA=</HashCode>
<FileName>Discount.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.Item">
<Position X="9" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AhAAIAAAAQAIAAAAAAAAAAQAAACAAAAAAAAAEAAAAAA=</HashCode>
<FileName>Item.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.Order">
<Position X="2.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>iAAAACQAAIAAAAAABAAAIAAAAgAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Order.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.Receipt">
<Position X="4.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AABAQAAAAAABiAAAAAAAAICAABAAQAAAAggAACQAAAA=</HashCode>
<FileName>Receipt.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.SmsController">
<Position X="2.75" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAACAAAABAAAgAAAAAAAAAAAAAAAA=</HashCode>
<FileName>SmsController.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="exercise.main.User">
<Position X="4.75" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>QAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAABAAAAAAA=</HashCode>
<FileName>User.cs</FileName>
</TypeIdentifier>
</Class>
<Enum Name="exercise.main.Role">
<Position X="6.75" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAA=</HashCode>
<FileName>Enums.cs</FileName>
</TypeIdentifier>
</Enum>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>
Loading