Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f1e8692
completed table setup, started class recipes
SamWhite745 Mar 31, 2023
6a35962
items recipe complete
SamWhite745 Mar 31, 2023
18de48e
item prepped for testing
SamWhite745 Mar 31, 2023
268556d
test - find all items - green
SamWhite745 Mar 31, 2023
1f28caa
test - create an item - green
SamWhite745 Mar 31, 2023
5ae8b64
orders recipe complete
SamWhite745 Mar 31, 2023
20cd5b6
orders ready to be tested
SamWhite745 Mar 31, 2023
a83a091
test - find all orders - green
SamWhite745 Mar 31, 2023
e6d364e
test - create order - green
SamWhite745 Mar 31, 2023
1df6dea
test - finds orders by item - green, order repo testing complete
SamWhite745 Mar 31, 2023
de817c8
test - find items by order - green, item testing complete
SamWhite745 Mar 31, 2023
1a255f2
application class designed
SamWhite745 Mar 31, 2023
0d1389e
test - application prints menu - green
SamWhite745 Mar 31, 2023
2c0f6e1
test - application actions on user selection - red
SamWhite745 Mar 31, 2023
9ab595d
test - application prints all items - green
SamWhite745 Mar 31, 2023
f1aa6b1
test - application creates an item - green
SamWhite745 Mar 31, 2023
daa3805
test - application prints all orders - green
SamWhite745 Mar 31, 2023
7085b4e
test - application prints orders by item - green
SamWhite745 Mar 31, 2023
e7ab044
test - application creates an order - green
SamWhite745 Mar 31, 2023
e9510e9
test - application actions on user selection - green
SamWhite745 Mar 31, 2023
ee31364
fixed actions on user selection exiting
SamWhite745 Mar 31, 2023
87bb671
Code tidying
SamWhite745 Mar 31, 2023
3c9a1c1
Updated README
SamWhite745 Mar 31, 2023
4e7c518
README header update
SamWhite745 Mar 31, 2023
6138bdd
Update README with instruction on creating the database
SamWhite745 Mar 31, 2023
ac87435
Create seeds_create.sql
SamWhite745 Mar 31, 2023
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
98 changes: 18 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,32 @@
Shop Manager Project
=================

* Feel free to use Google, your notes, books, etc. but work on your own
* If you refer to the solution of another coach or student, please put a link to that in your README
* If you have a partial solution, **still check in a partial solution**
* You must submit a pull request to this repo with your code next Monday morning
Welcome to the Shop Manager!

Challenge:
-------

Please start by [forking this repo](https://github.com/makersacademy/shop-manager-challenge/fork), then clone your fork to your local machine. Work into that directory.

We are going to write a small terminal program allowing the user to manage a shop database containing some items and orders.

User stories:
-------
You can run the program using:

```
As a shop manager
So I can know which items I have in stock
I want to keep a list of my shop items with their name and unit price.

As a shop manager
So I can know which items I have in stock
I want to know which quantity (a number) I have for each item.

As a shop manager
So I can manage items
I want to be able to create a new item.

As a shop manager
So I can know which orders were made
I want to keep a list of orders with their customer name.
ruby app.rb
```

As a shop manager
So I can know which orders were made
I want to assign each order to their corresponding item.
The program will continuously ask for actions to perform on the database until you select option 7 to exit the program

As a shop manager
So I can know which orders were made
I want to know on which date an order was placed.
### Database

As a shop manager
So I can manage orders
I want to be able to create a new order.
You will need to have a database running locally named 'items_orders'.
This can be achieved by running the following in the terminal
```

Here's an example of the terminal output your program should generate (yours might be slightly different — that's totally OK):

createdb items_orders
```
Welcome to the shop management program!

What do you want to do?
1 = list all shop items
2 = create a new item
3 = list all orders
4 = create a new order

1 [enter]

Here's a list of all shop items:

#1 Super Shark Vacuum Cleaner - Unit price: 99 - Quantity: 30
#2 Makerspresso Coffee Machine - Unit price: 69 - Quantity: 15
(...)
To initialise the tables run the following:
```

Technical Approach:
-----

In this unit, you integrated a database by using the `PG` gem, and test-driving and building Repository classes. You can continue to use this approach when building this challenge.

[You'll also need to mock IO](https://github.com/makersacademy/golden-square/blob/main/mocking_bites/05_unit_testing_terminal_io_bite.md) in your integration or unit tests, since the program will ask for user input.

Notes on test coverage
----------------------

Please ensure you have the following **AT THE TOP** of your spec_helper.rb in order to have test coverage stats generated
on your pull request:

```ruby
require 'simplecov'
require 'simplecov-console'

SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::Console,
# Want a nice code coverage website? Uncomment this next line!
# SimpleCov::Formatter::HTMLFormatter
])
SimpleCov.start
psql -h 127.0.0.1 items_orders < spec/seeds_create.sql
```
If you want to import some existing data into this table you can use the provided seed by entering the following into the terminal:
```
psql -h 127.0.0.1 items_orders < spec/seeds.sql
```
>hint: this will also refresh the table with the starter data if you wish to restart after adding data!
### WARNING

You can see your test coverage when you run your tests. If you want this in a graphical form, uncomment the `HTMLFormatter` line and see what happens!
Incorrect data entry wasn't in the scope of the program and can cause errors - **DOUBLE CHECK YOUR DATA ENTRY**
9 changes: 9 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Dir["./lib/*.rb"].each {|file| require file}

app = Application.new(
'items_orders',
Kernel,
ItemRepository.new,
OrderRepository.new
)
app.run
133 changes: 133 additions & 0 deletions lib/application.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
class Application

# The Application class initializer
# takes four arguments:
# * The database name to call `DatabaseConnection.connect`
# * the Kernel object as `io` (so we can mock the IO in our tests)
# * the ItemRepository object (or a double of it)
# * the OrderRepository object (or a double of it)
def initialize(database_name, io, item_repository, order_repository)
DatabaseConnection.connect(database_name)
@io = io
@item_repository = item_repository
@order_repository = order_repository
end

# "Runs" the terminal application
def run
loop do
print_menu
selection = @io.gets.chomp
do_selection(selection)
end
end

# Takes the user's selection and perfoms the appropriate action
def do_selection(selection)
case selection
when "1"
print_items
when "2"
print_items_by_order
when "3"
create_item
when "4"
print_orders
when "5"
print_orders_by_item
when "6"
create_order
when "7"
@io.exit
end
end

# Prints the menu
def print_menu
@io.puts "Welcome to the shop!"
@io.puts "What would you like to do?"
@io.puts "1 - List all items"
@io.puts "2 - List all items attached to an order"
@io.puts "3 - Create a new item"
@io.puts "4 - List all orders"
@io.puts "5 - List all orders that contain a specific item"
@io.puts "6 - Create a new order"
@io.puts "7 - Exit"
end

# Prints all the items
def print_items
@io.puts "All items:"
@item_repository.all.each do |item|
print_item(item)
end
end

# Prints all the items attached to an order
def print_items_by_order
@io.puts "What order do you want to see the items for?"
order_id = @io.gets.chomp.to_i
@item_repository.find_by_order(order_id).each do |item|
print_item(item)
end
end

# Creates an item
def create_item
item = Item.new

@io.print "Name: "
item.name = @io.gets.chomp

@io.print "Price: "
item.unit_price = @io.gets.chomp.to_f

@io.print "Quantity: "
item.quantity = @io.gets.chomp.to_i

@item_repository.create(item)
@io.puts("Item created!")
end

# Prints all the orders
def print_orders
@io.puts "All orders:"
@order_repository.all.each do |order|
print_order(order)
end
end

# Prints all orders that have an item
def print_orders_by_item
@io.puts "What item do you want to see the orders for?"
item_id = @io.gets.chomp.to_i

@order_repository.find_by_item(item_id).each do |order|
print_order(order)
end
end

# Creates a new item
def create_order
order = Order.new

@io.print "Name: "
order.customer_name = @io.gets.chomp

@io.print "Date: "
order.date = @io.gets.chomp

@order_repository.create(order)
@io.puts "Order created!"
end

# Prints a single item
def print_item(item)
@io.puts "#{item.name} - Price: £#{sprintf('%.2f',item.unit_price)} - Quantity: #{item.quantity}"
end

# Prints a single order
def print_order(order)
@io.puts "#{order.customer_name} - #{order.date}"
end
end
26 changes: 26 additions & 0 deletions lib/database_connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'pg'

# This class is a thin "wrapper" around the
# PG library. We'll use it in our project to interact
# with the database using SQL.

class DatabaseConnection
# This method connects to PostgreSQL using the
# PG gem. We connect to 127.0.0.1, and select
# the database name given in argument.
def self.connect(database_name)
@connection = PG.connect({ host: '127.0.0.1', dbname: database_name })
end

# This method executes an SQL query
# on the database, providing some optional parameters
# (you will learn a bit later about when to provide these parameters).
def self.exec_params(query, params)
if @connection.nil?
raise 'DatabaseConnection.exec_params: Cannot run a SQL query as the connection to'\
'the database was never opened. Did you make sure to call first the method '\
'`DatabaseConnection.connect` in your app.rb file (or in your tests spec_helper.rb)?'
end
@connection.exec_params(query, params)
end
end
3 changes: 3 additions & 0 deletions lib/item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Item
attr_accessor :id, :name, :unit_price, :quantity
end
65 changes: 65 additions & 0 deletions lib/item_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
class ItemRepository

# Selecting all records
def all
# Executes the SQL query:
sql = "SELECT * FROM items;"

result_set = DatabaseConnection.exec_params(sql, [])

return result_set_to_items(result_set)
end

# Adding an item to the table
# item: Item - item to add to table
def create(item)
# Executes the SQL query:
sql = 'INSERT INTO items (name, unit_price, quantity) VALUES ($1,$2,$3)'
sql_params = [item.name,item.unit_price,item.quantity]

DatabaseConnection.exec_params(sql, sql_params)

return nil
end

# Find all the items attached to an order
# order_id: int - the id of the order to filter by
def find_by_order(order_id)
sql =
'SELECT
items.id,
items.name,
items.unit_price,
items.quantity
FROM items
JOIN items_orders
ON items.id = items_orders.item_id
JOIN orders
ON items_orders.order_id = orders.id
WHERE order_id = $1;'

sql_params = [order_id]
result_set = DatabaseConnection.exec_params(sql, sql_params)

# Returns an array of item objects.
return result_set_to_items(result_set)
end

# Converts an SQL result set into a list of items
# result_set: tuple - whats returned when querying a table
def result_set_to_items(result_set)
items = []

result_set.each do |record|
item = Item.new
item.id = record['id'].to_i
item.name = record['name']
item.unit_price = record['unit_price'].to_f
item.quantity = record['quantity'].to_i

items << item
end

return items
end
end
3 changes: 3 additions & 0 deletions lib/order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Order
attr_accessor :id, :customer_name, :date
end
Loading