diff --git a/Gemfile b/Gemfile index 342acdd559..6e302d8def 100644 --- a/Gemfile +++ b/Gemfile @@ -4,3 +4,4 @@ gem 'cane' gem 'reek' gem 'rake' gem 'rspec' +gem 'simplecov', require: false, group: :test diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..1b921dde78 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,50 @@ +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.2) + cane (3.0.0) + parallel + diff-lcs (1.5.0) + docile (1.4.0) + kwalify (0.7.2) + parallel (1.22.1) + parser (3.1.2.0) + ast (~> 2.4.1) + rainbow (3.1.1) + rake (13.0.6) + reek (6.1.1) + kwalify (~> 0.7.0) + parser (~> 3.1.0) + rainbow (>= 2.0, < 4.0) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.11.0) + rspec-support (3.11.0) + simplecov (0.21.2) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) + +PLATFORMS + x86_64-darwin-21 + +DEPENDENCIES + cane + rake + reek + rspec + simplecov + +BUNDLED WITH + 2.3.13 diff --git a/lib/all_items_test_file.csv b/lib/all_items_test_file.csv new file mode 100644 index 0000000000..a626a97a43 --- /dev/null +++ b/lib/all_items_test_file.csv @@ -0,0 +1,1367 @@ +1200, + 1300, + 1350, + 700, + 2999, + 14900, + 1490, + 690, + 40000, + 13000, + 399, + 8000, + 60000, + 65000, + 4000, + 2390, + 50000, + 2390, + 50000, + 8000, + 2390, + 55000, + 11900, + 60000, + 2400, + 4800, + 60000, + 4995, + 2000, + 1200, + 5000, + 5000, + 11000, + 3000, + 60000, + 15000, + 3700, + 20000, + 40000, + 3000, + 17000, + 7000, + 2500, + 17000, + 2500, + 2000, + 2000, + 2000, + 16150, + 2000, + 5000, + 2500, + 25000, + 4900, + 2500, + 300000, + 86000, + 72000, + 500, + 4999, + 12000, + 19, + 6000, + 300, + 1000, + 5000, + 1000, + 4500, + 4500, + 300, + 7000, + 2500, + 6000, + 2199, + 2600, + 2100, + 10000, + 495, + 7500, + 795, + 4000, + 22500, + 3000, + 15000, + 15000, + 795, + 7500, + 7500, + 795, + 7500, + 10000, + 10000, + 15000, + 795, + 199, + 7500, + 3000, + 495, + 5000, + 10000, + 15000, + 11000, + 15000, + 7500, + 3500, + 7500, + 7500, + 795, + 1000, + 1500, + 11000, + 1500, + 75, + 46000, + 9999900, + 4000, + 1000, + 390, + 14900, + 1500, + 1500, + 54900, + 245, + 2500, + 25000, + 14900, + 2000, + 4800, + 14900, + 3000, + 4000, + 3000, + 250, + 1200, + 150, + 245, + 9500, + 14900, + 160000, + 245, + 1200, + 900, + 4000, + 50000, + 600, + 3000, + 250, + 2500, + 245, + 800, + 50000, + 24900, + 9000, + 1499, + 800, + 250, + 800, + 3000, + 12500, + 12000, + 3000, + 12000, + 700, + 16000, + 400, + 4500, + 4000, + 16000, + 100000, + 250000, + 16000, + 2500, + 1200, + 2500, + 2495, + 89500, + 5000, + 1250, + 190000, + 2999, + 995, + 3000, + 1500, + 2800, + 1495, + 22500, + 19900, + 4500, + 4000, + 1800, + 1750, + 2500, + 2500, + 13500, + 3000, + 2500, + 8000, + 5000, + 1500, + 1699, + 370, + 400, + 135000, + 2050, + 5500, + 1295, + 3500, + 1000, + 4500, + 2500, + 3200, + 145000, + 180000, + 1000, + 3995, + 2700, + 40000, + 1500, + 4000, + 145000, + 6000, + 1800, + 15000, + 10000, + 2700, + 3000, + 150000, + 250, + 125000, + 1000, + 995, + 12500, + 1500, + 1790, + 10000, + 1790, + 1790, + 320000, + 4990, + 2000, + 1200, + 400, + 80000, + 50000, + 1790, + 400, + 7500, + 1790, + 400, + 1790, + 50000, + 70000, + 3000, + 80000, + 1790, + 40000, + 1790, + 3900, + 400, + 3000, + 25000, + 1000, + 500, + 5000, + 7500, + 2900, + 28000, + 895, + 1695, + 15000, + 25000, + 4000, + 4000, + 1900, + 500, + 16800, + 1000, + 700, + 6500, + 1000, + 10000, + 1900, + 25000, + 6500, + 7000, + 2450, + 3000, + 2000, + 990, + 8000, + 900, + 3500, + 20000, + 1200, + 1899, + 7500, + 4599, + 4000, + 100000, + 3800, + 600, + 5000, + 14900, + 500, + 1300, + 10999, + 1200, + 2995, + 4800, + 500, + 1500, + 500, + 5000, + 500, + 9900, + 6999, + 3500, + 500, + 1400, + 1900, + 1297, + 4900, + 9000, + 1000, + 2800, + 1500, + 1499, + 970, + 1200, + 2500, + 7999, + 15000, + 6800, + 3500, + 3900, + 2000, + 2500, + 1399, + 12000, + 500, + 4000, + 1200, + 9500, + 10000, + 20000, + 2000, + 4800, + 9000, + 10000, + 1500, + 1000, + 1500, + 5000, + 200000, + 4000, + 1000, + 1500, + 6500, + 700, + 8500, + 1200, + 1990, + 3000, + 1200, + 3200, + 17500, + 18500, + 1200, + 3000, + 16000, + 4990, + 9500, + 400, + 4000, + 4000, + 1000, + 4800, + 2400, + 300, + 6000, + 16000, + 2200, + 3000, + 250, + 1000, + 1700, + 500, + 4500, + 800, + 3995, + 16000, + 1999, + 800, + 1000, + 4999, + 3000, + 3400, + 2500, + 400, + 17000, + 2500, + 2400, + 6000, + 4500, + 1260, + 2700, + 1000, + 8000, + 1000, + 1500, + 5760, + 1000, + 1599, + 2500, + 220, + 499, + 2700, + 3860, + 3500, + 22000, + 800, + 6000, + 1500, + 1570, + 2500, + 18000, + 450, + 900, + 1000, + 1000, + 1000, + 16000, + 17000, + 4000, + 2700, + 23000, + 37500, + 2500, + 750, + 1000, + 1500, + 6500, + 695, + 2500, + 2700, + 5470, + 1000, + 3970, + 4970, + 1500, + 600, + 2500, + 2500, + 2000, + 2300, + 1900, + 11000, + 2000, + 3500, + 500, + 59500, + 11770, + 2000, + 1900, + 1200, + 750, + 500, + 4000, + 800, + 2500, + 1300, + 900, + 9000, + 1200, + 749500, + 1500, + 30000, + 2500, + 2500, + 52900, + 6000, + 2100, + 125000, + 30000, + 27000, + 1500, + 1000, + 1100, + 2000, + 7500, + 8500, + 1900, + 1500, + 12000, + 890, + 11000, + 8000, + 600, + 1000, + 3500, + 1000, + 28000, + 1900, + 32900, + 9000, + 1500, + 3500, + 7500, + 700, + 1900, + 1300, + 3500, + 4995, + 600, + 650, + 900, + 600, + 2500, + 1000, + 2000, + 2500, + 2000, + 4995, + 47500, + 3500, + 4400, + 1400, + 2500, + 8000, + 47500, + 2499500, + 2500, + 695, + 200, + 700, + 750, + 5495, + 4000, + 4995, + 4500, + 1000, + 36500, + 2000, + 595, + 1500, + 8000, + 750, + 1900, + 3500, + 29500, + 4995, + 1050, + 1500, + 5800, + 599, + 1995, + 750, + 350000, + 1900, + 2100, + 750, + 60300, + 1300, + 395, + 30000, + 3500, + 119500, + 2500, + 59400, + 15000, + 24500, + 4500, + 1500, + 1500, + 500, + 3500, + 79400, + 3000, + 1815, + 2000, + 4995, + 1500, + 795, + 28200, + 30000, + 450, + 40600, + 4000, + 2000, + 1800, + 4000, + 14900, + 1150, + 495, + 6000, + 1400, + 600, + 1505, + 1200, + 3600, + 3500, + 28200, + 2000, + 250, + 36900, + 2000, + 1500, + 9000, + 93800, + 4000, + 3000, + 4000, + 20000, + 495, + 550000, + 30000, + 1200, + 4995, + 5000, + 62500, + 4200, + 1500, + 1000, + 2500, + 4995, + 5000, + 6000, + 51300, + 2500, + 3000, + 50000, + 1500, + 500, + 1600, + 2200, + 3000, + 1000, + 4500, + 2000, + 22500, + 19900, + 1200, + 2500, + 300, + 3000, + 35000, + 500, + 2500, + 900, + 300, + 19500, + 1500, + 25000, + 2000, + 10000, + 1800, + 75000, + 10000, + 720, + 600, + 50000, + 6900, + 250, + 60000, + 4900, + 999, + 1400, + 3500, + 50000, + 4500, + 60000, + 999, + 6000, + 50000, + 1500, + 1890, + 20000, + 7000, + 2390, + 2500, + 15300, + 10000, + 790, + 2500, + 600, + 16900, + 2600, + 3600, + 1500, + 65000, + 72000, + 5999, + 15000, + 3500, + 200, + 2500, + 3500, + 5800, + 2000, + 1400, + 10000, + 2500, + 4500, + 5000, + 200, + 300, + 5000, + 15000, + 5000, + 500, + 2000, + 2500, + 250, + 10000, + 1800, + 5000, + 200000, + 2000, + 495, + 180000, + 4290, + 500, + 45000, + 5000, + 10000, + 15000, + 86000, + 15000, + 795, + 900, + 15000, + 495, + 7500, + 2100, + 10000, + 7500, + 495, + 10000, + 250, + 495, + 795, + 20000, + 6000, + 795, + 7500, + 999, + 5000, + 20000, + 7500, + 7500, + 6500, + 1800, + 795, + 600, + 6000, + 8000, + 245, + 7500, + 2500, + 1730, + 1000, + 8000, + 1000, + 245, + 1200, + 1000, + 250, + 1200, + 245, + 100, + 1000, + 245, + 500, + 20000, + 12000, + 3500, + 2500, + 2500, + 5000, + 2500, + 245, + 2500, + 14900, + 5000, + 3000, + 5000, + 2200, + 3400, + 800, + 3000, + 7800, + 6000, + 80000, + 800, + 3000, + 250, + 800, + 1400, + 3000, + 2000, + 7500, + 110000, + 350, + 3500, + 16000, + 3000, + 16000, + 1200, + 1000, + 3500, + 110000, + 3500, + 16000, + 80000, + 6000, + 25000, + 1800, + 3500, + 3000, + 2300, + 800, + 1900, + 9000, + 1000, + 2700, + 800, + 100, + 5599, + 6000, + 9900, + 150000, + 2500, + 19000, + 1150, + 1200, + 11000, + 4000, + 1769, + 1500, + 2500, + 2200, + 800, + 3000, + 700, + 12500, + 1499, + 3200, + 1500, + 3000, + 4500, + 1499, + 250, + 1500, + 5000, + 15000, + 8000, + 2500, + 9500, + 45000, + 19500, + 7000, + 2346, + 1500, + 1000, + 30000, + 5000, + 145000, + 1200, + 250, + 3500, + 3200, + 2000, + 2700, + 1400, + 35000, + 2000, + 3000, + 1395, + 80000, + 100, + 1200, + 1800, + 150000, + 9500, + 500, + 5900, + 1790, + 15000, + 3000, + 70000, + 1790, + 15000, + 250, + 10000, + 1200, + 3000, + 4900, + 400, + 600, + 20000, + 1595, + 1000, + 55000, + 7000, + 695, + 16500, + 45000, + 2200, + 2000, + 400, + 2500, + 500, + 10000, + 2500, + 400, + 3500, + 1200, + 3300, + 5000, + 3000, + 500, + 25000, + 1299, + 900, + 250, + 2500, + 500, + 10000, + 6500, + 9500, + 7500, + 1200, + 2500, + 1400, + 1700, + 35000, + 7000, + 8000, + 5500, + 89500, + 5900, + 500000, + 5000, + 80000, + 6000, + 600, + 5000, + 900, + 5000, + 2900, + 5999, + 5000, + 2500, + 15000, + 1000, + 1200, + 500, + 30000, + 500, + 140000, + 250, + 7500, + 6800, + 700, + 500, + 400, + 600, + 1000, + 5500, + 800, + 40000, + 500, + 500, + 1000, + 4000, + 500, + 2000, + 1000, + 2500, + 32000, + 8500, + 7999, + 7500, + 80000, + 1000, + 400, + 1500, + 27500, + 4800, + 10000, + 900, + 1000, + 5800, + 1200, + 2900, + 1199, + 1300, + 16000, + 200000, + 2500, + 1200, + 600, + 600, + 15000, + 1800, + 2000, + 800, + 9000, + 35000, + 3000, + 1500, + 2000, + 2500, + 700, + 3500, + 4000, + 499, + 4500, + 13000, + 1795, + 1000, + 120000, + 15000, + 45000, + 4500, + 2500, + 9000, + 500, + 650, + 12500, + 5000, + 3500, + 1500, + 1500, + 400, + 400, + 9000, + 2500, + 12500, + 59500, + 5000, + 400, + 2500, + 16300, + 800, + 1500, + 400, + 2500, + 1000, + 400, + 3000, + 800, + 15000, + 400, + 2500, + 40000, + 5499, + 25000, + 250, + 120000, + 3500, + 2500, + 8500, + 3500, + 5000, + 450, + 3400, + 1799, + 3400, + 1000, + 3900, + 10000, + 3000, + 3400, + 450, + 29500, + 112000, + 5900, + 1000, + 1000, + 1000, + 3500, + 2500, + 1300, + 1400, + 3500, + 3995, + 400, + 1500, + 1500, + 85000, + 2500, + 2500, + 1500, + 3000, + 450, + 10000, + 1000, + 2000, + 1000, + 400, + 34900, + 6000, + 4500, + 8500, + 1200, + 99500, + 2400, + 4000, + 2200, + 1000, + 10000, + 29500, + 22000, + 2100, + 900, + 400, + 500, + 19900, + 4500, + 1900, + 2500, + 800, + 8000, + 599, + 500, + 29500, + 1900, + 1599, + 900, + 11000, + 80000, + 23999, + 3500, + 59500, + 3500, + 2400, + 1500, + 1900, + 3000, + 7500, + 3500, + 699, + 3500, + 500000, + 3500, + 999, + 4970, + 29900, + 4800, + 17500, + 3500, + 3500, + 2700, + 16500, + 8000, + 4500, + 890, + 25000, + 1599, + 1000, + 55999, + 30000, + 2499, + 2500, + 3500, + 310000, + 3000, + 650, + 800, + 3000, + 1200, + 27000, + 39900, + 1000, + 1200, + 500, + 800, + 1500, + 8000, + 79500, + 1900, + 999, + 9500, + 1500, + 3000, + 2100, + 2195, + 1500, + 2000, + 2000, + 599, + 2000, + 1000, + 2000, + 3000, + 10000, + 800, + 600, + 890, + 3500, + 1500, + 400, + 1400, + 1000, + 2000, + 1900, + 695, + 8000, + 2500, + 15000, + 500, + 2499500, + 8000, + 2000, + 6200, + 599, + 100, + 3500, + 500, + 800, + 1200, + 1500, + 6500, + 3500, + 6000, + 250000, + 8000, + 4995, + 1100, + 1500, + 700, + 8000, + 2500, + 1200, + 2000, + 4000, + 1500, + 9500, + 650, + 250, + 6500, + 450, + 4995, + 1300, + 90000, + 3500, + 1000, + 1500, + 125000, + 1500, + 500, + 24000, + 2500, + 1200, + 4400, + 2500, + 1900, + 3500, + 1800, + 1205, + 999, + 7000, + 4995, + 1000, + 40000, + 2000, + 2500, + 2000, + 31800, + 20000, + 595, + 3500, + 1500, + 2500, + 4499, + 4995, + 700000, + 3500, + 4000, + 795, + 23000, + 1200, + 4000, + 30000, + 1505, + 50000, + 2500, + 1600, + 2500, + 1200, + 1500, + 3500, + 1500, + 21000, + 3000, + 2500, + 29500, + 200, + 29900, + 3400, + 6500, + 1800, + 3600, + 1250, + 2000, + 550, + 22000, + 2000, + 5000, + 5000, + 4000, + 20000, + 2000, + 3499, + 4000, + 3200, + 4000, + 1995, + 28000, + 4900, + 5000, + 2500, + 22500, + 4000, + 2995, + 1400, + 71900, + 5000, + 23000, + 18000, + 2000, + 1499, + 395, + 1800, + 1200, + 6999, + 4000, + 13000, + 2500, + 795, + 13000, + 3000, + 1200, + 25000, + 500, + 25000, + 1000, + 1199, + 2500, + 10000, + 1500, + 5000, + 4500, + 1000, + 9500, + 1200, + 999, + 7500, + 3000, + 2000, + 1000, + 2750, + 2999, + 6100, + 25000, + 3800 diff --git a/lib/customer.rb b/lib/customer.rb new file mode 100644 index 0000000000..3f1566f244 --- /dev/null +++ b/lib/customer.rb @@ -0,0 +1,10 @@ +class Customer + attr_reader :id, :first_name, :last_name, :created_at, :updated_at + def initialize(data) + @id = data[:id] + @first_name = data[:first_name] + @last_name = data[:last_name] + @created_at = data[:created_at] + @updated_at = data[:updated_at] + end +end diff --git a/lib/invoice.rb b/lib/invoice.rb new file mode 100644 index 0000000000..b4c6ddf034 --- /dev/null +++ b/lib/invoice.rb @@ -0,0 +1,19 @@ +class Invoice + + attr_reader :id, + :customer_id, + :created_at, + :merchant_id + + attr_accessor :status, + :updated_at + + def initialize(data) + @id = data[:id] + @customer_id = data[:customer_id] + @status = data[:status] + @created_at = data[:created_at] + @updated_at = data[:updated_at] + @merchant_id = data[:merchant_id] + end +end diff --git a/lib/invoice_item.rb b/lib/invoice_item.rb new file mode 100644 index 0000000000..f0979cba7b --- /dev/null +++ b/lib/invoice_item.rb @@ -0,0 +1,24 @@ +class InvoiceItem +attr_reader :id, + :item_id, + :invoice_id, + :created_at, + :unit_price_to_dollars + +attr_accessor :quantity, + :unit_price, + :updated_at + + def initialize(data) + @id = data[:id] + @item_id = data[:item_id] + @invoice_id = data[:invoice_id] + @quantity = data[:quantity] + @unit_price = data[:unit_price] + @created_at = data[:created_at] + @updated_at = data[:updated_at] + @unit_price_to_dollars = @unit_price.to_f + end + + +end diff --git a/lib/invoice_item_repository.rb b/lib/invoice_item_repository.rb new file mode 100644 index 0000000000..17ad9a5df0 --- /dev/null +++ b/lib/invoice_item_repository.rb @@ -0,0 +1,66 @@ +require 'CSV' +require 'BigDecimal' +require_relative './invoice_item.rb' + +class InvoiceItemRepository + attr_reader :all + def initialize(invoice_item_path) + @invoice_item_path = invoice_item_path + @all = [] + + CSV.foreach(@invoice_item_path, headers: true, header_converters: :symbol) do |row| + @all << InvoiceItem.new({ + :id => row[:id], + :item_id => row[:item_id], + :invoice_id => row[:invoice_id], + :quantity => row[:quantity], + :unit_price => row[:unit_price], + :created_at => row[:created_at], + :updated_at => row[:updated_at], + :unit_price => row[:unit_price] + }) + end + + end + + def find_by_id(id) + @all.find do |invoice_item| + invoice_item.id.to_i == id + end + end + + def find_all_by_item_id(item_id) + @all.find_all do |invoice_item| + invoice_item.item_id == item_id + end + end + + def find_all_by_invoice_id(invoice_id) + @all.find_all do |invoice_item| + invoice_item.invoice_id.to_i == invoice_id + end + end + + def create(new_invoice_attributes) + new_id = @all.last.id.to_i + 1 + new_attribute = new_invoice_attributes + @all << InvoiceItem.new(:id => new_id.to_s, :item_id => new_attribute[:item_id], :invoice_id => + new_attribute[:invoice_id], :unit_price => new_attribute[:unit_price], :quantity => new_attribute[:quantity], :created_at => Time.now, :updated_at => Time.now) + return @all.last + + end + + def update(id, attributes) + updated_item = find_by_id(id) + updated_item.quantity = attributes[:quantity] + updated_item.unit_price = attributes[:unit_price] + updated_item.updated_at = Time.now + end + + def delete(id) + removed_item = find_by_id(id) + @all.delete(removed_item) + end + + +end diff --git a/lib/invoice_repository.rb b/lib/invoice_repository.rb new file mode 100644 index 0000000000..ff6deb3606 --- /dev/null +++ b/lib/invoice_repository.rb @@ -0,0 +1,64 @@ +require 'CSV' +require "BigDecimal" +require_relative'./invoice.rb' +class InvoiceRepository + attr_reader :all + + def initialize(invoice_path) + @invoice_path = invoice_path + @all = [] + + CSV.foreach(@invoice_path, headers: true, header_converters: :symbol) do |row| + @all << Invoice.new({ + :id => row[:id], + :customer_id => row[:customer_id], + :status => row[:status], + :created_at => row[:created_at], + :updated_at => row[:updated_at], + :merchant_id => row[:merchant_id]}) + end + end + + def find_by_id(id) + @all.find do |invoice| + invoice.id.to_i == id + end + end + + def find_all_by_customer_id(customer_id) + @all.find_all do |invoice| + customer_id.to_i == invoice.customer_id.to_i + end + end + + def find_all_by_merchant_id(merchant_id) + @all.find_all do |invoice| + merchant_id.to_i == invoice.merchant_id.to_i + end + end + + def find_all_by_status(status) + @all.find_all do |invoice| + status == invoice.status + end + end + + def create(new_invoice_attributes) + new_id = @all.last.id.to_i + 1 + new_attribute = new_invoice_attributes + @all << Invoice.new(:id => new_id.to_s, :customer_id => new_attribute[:customer_id], :merchant_id => + new_attribute[:merchant_id], :status => "pending", :created_at => Time.now, :updated_at => Time.now) + return @all.last + end + + def update(id, attributes) + updated_item = find_by_id(id) + updated_item.status = attributes[:status] + updated_item.updated_at = Time.now + end + + def delete(id) + removed_item = find_by_id(id) + @all.delete(removed_item) + end +end diff --git a/lib/item.rb b/lib/item.rb new file mode 100644 index 0000000000..3b3b8e535e --- /dev/null +++ b/lib/item.rb @@ -0,0 +1,28 @@ + +require 'CSV' + +class Item + attr_reader :id, + :created_at, + :merchant_id + + attr_accessor :name, + :description, + :unit_price, + :updated_at + + def initialize(data) + @id = data[:id] + @name = data[:name] + @description = data[:description] + @unit_price = data[:unit_price] + @created_at = data[:created_at] + @updated_at = data[:updated_at] + @merchant_id = data[:merchant_id] + end + + def unit_price_to_dollars + @unit_price.to_f + end + +end diff --git a/lib/item_repository.rb b/lib/item_repository.rb new file mode 100644 index 0000000000..ce2cdd615a --- /dev/null +++ b/lib/item_repository.rb @@ -0,0 +1,79 @@ +require 'CSV' +require "BigDecimal" +require_relative'./item.rb' + +class ItemRepository + attr_reader :all + def initialize(items_path) + @items_path = items_path + @all = [] + + CSV.foreach(@items_path, headers: true, header_converters: :symbol) do |row| + @all << Item.new({ + :id => row[:id], + :name => row[:name], + :description => row[:description], + :unit_price => row[:unit_price], + :created_at => row[:created_at], + :updated_at => row[:updated_at], + :merchant_id => row[:merchant_id]}) + end + end + + def find_by_id(id) + @all.find do |item| + item.id.to_i == id + end + end + + def find_by_name(name) + @all.find do |item| + item.name.downcase.include?(name.downcase) + end + end + + def find_all_with_description(description) + @all.find_all do |item| + item.description.downcase.include?(description.downcase) + end + end + + def find_all_by_price(unit_price) + @all.find_all do |item| + item.unit_price == unit_price + end + end + + def find_all_by_price_in_range(range) + @all.find_all do |item| + (range.min..range.max).include?(item.unit_price.to_i) + end + end + + def find_all_by_merchant_id(merchant_id) + @all.find_all do |item| + merchant_id.to_i == item.merchant_id.to_i + end + end + + def create(attributes) + new_id = @all.last.id.to_i + 1 + new_attribute = attributes + @all << Item.new(:id => new_id.to_s, :name => new_attribute[:name], :unit_price => + new_attribute[:unit_price], :description => new_attribute[:description], :created_at => Time.now) + return @all.last + end + + def update(id, attributes) + updated_item = find_by_id(id) + updated_item.name = attributes[:name] + updated_item.unit_price = attributes[:unit_price] + updated_item.description = attributes[:description] + updated_item.updated_at = Time.now + end + + def delete(id) + removed_item = find_by_id(id) + @all.delete(removed_item) + end +end diff --git a/lib/merchant.rb b/lib/merchant.rb new file mode 100644 index 0000000000..44f52caf76 --- /dev/null +++ b/lib/merchant.rb @@ -0,0 +1,10 @@ +class Merchant + attr_reader :id + attr_accessor :name + + def initialize(data) + @id = data[:id] + @name = data[:name] + end + +end diff --git a/lib/merchant_repository.rb b/lib/merchant_repository.rb new file mode 100644 index 0000000000..8c2291cd5f --- /dev/null +++ b/lib/merchant_repository.rb @@ -0,0 +1,51 @@ +require 'CSV' +require_relative './merchant.rb' +class MerchantRepository + attr_reader :all + def initialize(file_path) + @file_path = file_path + @all = [] + + CSV.foreach(@file_path, headers: true, header_converters: :symbol) do |row| + @all << Merchant.new({:id => row[:id], :name => row[:name]}) + + end + + end + + def find_by_id(id) + @all.find do |merchant| + merchant.id.to_i == id + end + end + + def find_by_name(name) + @all.find do |merchant| + merchant.name.downcase.include?(name.downcase) + end + end + + def find_all_by_name(name_fragment) + @all.find_all do |merchant| + merchant.name.downcase.include?(name_fragment.downcase) + end + end + + def create(attribute) + new_id = @all.last.id.to_i + 1 + new_attribute = attribute + @all << Merchant.new(:id => new_id.to_s, :name => new_attribute) + return @all.last + end + + def update(id, attributes) + renamed_merchant = find_by_id(id) + renamed_merchant.name = attributes + end + + def delete(id) + removed_merchant = find_by_id(id) + @all.delete(removed_merchant) + end + +end diff --git a/lib/sales_analyst.rb b/lib/sales_analyst.rb new file mode 100644 index 0000000000..5994f0e091 --- /dev/null +++ b/lib/sales_analyst.rb @@ -0,0 +1,201 @@ +require_relative "./sales_engine" +require_relative "./item_repository" +require_relative "./merchant_repository" +require "bigdecimal" +require "bigdecimal/util" +require "date" + +class SalesAnalyst + attr_reader :items, :merchants, :invoices + def initialize(items, merchants, invoices) + @items = items + @merchants = merchants + @invoices = invoices + end + + def average_items_per_merchant + average_number = items.all.count.to_f / merchants.all.count.to_f + return average_number.round(2) + end + + def items_by_merchant + items_per_merchant = Hash.new(0) + merchant_ids = items.all.map {|item| item.merchant_id} + merchant_ids.each do |id| + items_per_merchant[id] += 1 + end + return items_per_merchant + end + + def average_items_per_merchant_standard_deviation + set = items_by_merchant.values + mean = average_items_per_merchant + sums = set.sum { |num| (num - mean)**2 } + std_dev = Math.sqrt(sums / (set.length - 1).to_f) + std_dev.round(2) + end + + def merchants_with_high_item_count + standard_deviation = average_items_per_merchant_standard_deviation + mean_and_standard_dev = standard_deviation + average_items_per_merchant + merchants_with_high_sales = [] + items_by_merchant.each_pair do |merchant, items| + merchants_with_high_sales << merchant if items > mean_and_standard_dev + end + return merchants_with_high_sales + end + + def average_item_price_for_merchant(merchant_id) + find_merchant = @items.find_all_by_merchant_id(merchant_id) + items_sum = find_merchant.sum do |item| + item.unit_price.to_f + end + (items_sum / find_merchant.count).to_d(3) + end + + def average_average_price_per_merchant + merchant_price_sums = [] + merchant_ids = items.all.map {|item| item.merchant_id.to_i} + merchant_ids.each do |id| + merchant_price_sums << average_item_price_for_merchant(id).to_f + end + (merchant_price_sums.sum / merchant_price_sums.size).to_d(3) + end + + def standard_deviation(values, mean) + sums = values.sum { |value| (value - mean)**2 } + std_dev = Math.sqrt(sums / (values.length - 1).to_f) + std_dev.round(2) + end + + def golden_items + array_of_all_prices = @items.all.map {|item| item.unit_price.to_i} + set = array_of_all_prices + mean = array_of_all_prices.sum / array_of_all_prices.size + std_dev = standard_deviation(set, mean) + minimum_golden_price = mean += (2 * std_dev) + items.all.find_all{ |item| item.unit_price.to_i > minimum_golden_price } + end + + def average_invoices_per_merchant + (@invoices.all.size / @merchants.all.size.to_f).round(2) + end + + def average_invoices_per_merchant_standard_deviation + set = invoices_by_merchant.values + avg = average_invoices_per_merchant + standard_deviation(set, avg) + end + + def invoices_by_merchant + invoices_per_merchant = Hash.new(0) + merchant_ids = invoices.all.map {|invoice| invoice.merchant_id} + merchant_ids.each do |id| + invoices_per_merchant[id] += 1 + end + return invoices_per_merchant + end + + def merchant_z_score(invoice_count) + mean = average_invoices_per_merchant + std_dev = average_invoices_per_merchant_standard_deviation + z_score = (invoice_count - mean) / std_dev + return z_score.round(2) + end + + def merchants_by_zscore + merchant_by_z_score = Hash.new + invoices_by_merchant.each do |merchant, invoice_count| + merchant_by_z_score[merchant] = merchant_z_score(invoice_count) + end + return merchant_by_z_score + end + + def top_merchants_by_invoice_count + top_merchants = [] + merchants_by_zscore.each do |merchants, zscore| + top_merchants << merchants if zscore > 2 + end + return top_merchants + end + + def bottom_merchants_by_invoice_count + bottom_merchants = [] + merchants_by_zscore.each do |merchants, zscore| + bottom_merchants << merchants if zscore < 2 + end + return bottom_merchants + end + + def top_days_by_invoice_count + top_days = [] + weekday_by_zscore.each do |day, zscore| + top_days << day if zscore > 1 + end + return top_days + end + + def date_to_day(date) + weekday = Date.parse(date) + weekday_num = weekday.wday + weekday_name = Date::DAYNAMES[weekday_num] + return weekday_name + end + + def invoices_by_day + invoices_per_day = Hash.new(0) + invoice_dates = invoices.all.map {|invoice| invoice.created_at} + invoice_dates.each do |date| + invoices_per_day[date_to_day(date)] += 1 + end + return invoices_per_day + end + + def average_invoices_per_day + invoices_by_day.values.sum / invoices_by_day.count + end + + def average_invoices_per_day_standard_deviation + set = invoices_by_day.values + avg = average_invoices_per_day + standard_deviation(set, avg) + end + + def weekday_by_zscore + day_by_z_score = Hash.new + invoices_by_day.each do |day, invoice_count| + day_by_z_score[day] = weekday_z_score(invoice_count) + end + return day_by_z_score + end + + def weekday_z_score(invoice_count) + mean = average_invoices_per_day + std_dev = average_invoices_per_day_standard_deviation + z_score = (invoice_count - mean) / std_dev + return z_score.round(2) + end + + def invoice_status(status) + status_percentage = ((invoice_by_status_count[(status)].to_f / invoice_by_status_count.values.sum.to_f)*100) + return status_percentage.round(2) + end + + def invoice_by_status + invoices_per_status = Hash.new + invoices.all.each do |invoice| + invoices_per_status[invoice.id] = invoice.status + end + return invoices_per_status + end + + def invoice_by_status_count + status_count = Hash.new(0) + invoice_by_status.each do |id, status| + status_count[status.to_sym] += 1 + end + return status_count + end + + +end diff --git a/lib/sales_engine.rb b/lib/sales_engine.rb new file mode 100644 index 0000000000..cb02716f10 --- /dev/null +++ b/lib/sales_engine.rb @@ -0,0 +1,18 @@ +class SalesEngine + attr_reader :items, + :merchants, + :invoices, + :analyst + + def initialize(items_path, merchants_path, invoice_path) + @items = ItemRepository.new(items_path) + @merchants = MerchantRepository.new(merchants_path) + @invoices = InvoiceRepository.new(invoice_path) + @analyst = SalesAnalyst.new(items, merchants, invoices) + end + + def self.from_csv(data) + return SalesEngine.new(data[:items], data[:merchants], data[:invoices]) + end + +end diff --git a/test/.gitignore b/spec/.gitignore similarity index 100% rename from test/.gitignore rename to spec/.gitignore diff --git a/spec/customer_spec.rb b/spec/customer_spec.rb new file mode 100644 index 0000000000..50689b4f71 --- /dev/null +++ b/spec/customer_spec.rb @@ -0,0 +1,79 @@ +require './lib/customer' +require 'time' + +RSpec.describe Customer do + + it 'exists' do + c = Customer.new({ + :id => 6, + :first_name => "Joan", + :last_name => "Clarke", + :created_at => Time.now, + :updated_at => Time.now + }) + + expect(c).to be_an_instance_of Customer + end + + it 'can return the customer id' do + c = Customer.new({ + :id => 6, + :first_name => "Joan", + :last_name => "Clarke", + :created_at => Time.now, + :updated_at => Time.now + }) + + expect(c.id).to eq(6) + + end + + it 'can return the customers first name' do + c = Customer.new({ + :id => 6, + :first_name => "Joan", + :last_name => "Clarke", + :created_at => Time.now, + :updated_at => Time.now + }) + + expect(c.first_name).to eq("Joan") + end + + it 'can return the customers last name' do + c = Customer.new({ + :id => 6, + :first_name => "Joan", + :last_name => "Clarke", + :created_at => Time.now, + :updated_at => Time.now + }) + + expect(c.last_name).to eq("Clarke") + + end + + it 'can return the time the customers profile was created' do + c = Customer.new({ + :id => 6, + :first_name => "Joan", + :last_name => "Clarke", + :created_at => Time.now.round, + :updated_at => Time.now.round + }) + + expect(c.created_at).to eq(Time.now.round) + end + + it 'can return the time the customers profile was updated' do + c = Customer.new({ + :id => 6, + :first_name => "Joan", + :last_name => "Clarke", + :created_at => Time.now.round, + :updated_at => Time.now.round + }) + + expect(c.updated_at).to eq(Time.now.round) + end +end diff --git a/spec/invoice_item_repository_spec.rb b/spec/invoice_item_repository_spec.rb new file mode 100644 index 0000000000..22471d300e --- /dev/null +++ b/spec/invoice_item_repository_spec.rb @@ -0,0 +1,92 @@ +require './lib/invoice_item_repository' +require 'BigDecimal' +require 'CSV' + + +RSpec.describe InvoiceItemRepository do + it 'exists' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + expect(ii_repo).to be_a(InvoiceItemRepository) + end + + it 'returns an array of all known InvoiceItem instances' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + expect(ii_repo.all).to be_a(Array) + end + + it 'return the amount of all known invoice_items instances' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + expect(ii_repo.all.count).to eq(21830) + end + + it 'can find all by id' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + + expect(ii_repo.find_by_id(1)).to be_an_instance_of(InvoiceItem) + expect(ii_repo.find_by_id(999991)).to eq(nil) + end + + it 'can find all by item_id' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + + expect(ii_repo.find_all_by_item_id(263519844)).to be_an_instance_of(Array) + expect(ii_repo.find_all_by_item_id(999991)).to eq([]) + end + + it 'can find all by invoice_id' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + + expect(ii_repo.find_all_by_invoice_id(1)).to be_instance_of(Array) + expect(ii_repo.find_all_by_invoice_id(999991)).to eq([]) + expect(ii_repo.find_all_by_invoice_id(1).size).to eq(8) + end + + it 'can create attributes' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + new_item_attributes = {:item_id => "2635999123", :invoice_id => "4986", + :unit_price => "99999",:quantity => "9"} + + new_item = (ii_repo.create(new_item_attributes)) + + expect(new_item.id).to eq("21831") + expect(new_item.item_id).to eq("2635999123") + expect(new_item.invoice_id).to eq("4986") + expect(new_item.unit_price).to eq("99999") + expect(new_item.quantity).to eq("9") + expect(new_item.created_at).to be_an_instance_of(Time) + expect(ii_repo.find_by_id(21831)).to be_an_instance_of(InvoiceItem) + end + + it 'can update Invoice items with attributes' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + + expect(ii_repo.find_by_id(10).quantity).to eq("4") + expect(ii_repo.find_by_id(10).unit_price).to eq("1859") + + new_test_attributes = {:quantity => "99", :unit_price => "2000", :updated_at => "1"} + ii_repo.update(10, new_test_attributes) + + expect(ii_repo.find_by_id(10).quantity).to eq("99") + expect(ii_repo.find_by_id(10).unit_price).to eq("2000") + expect(ii_repo.find_by_id(10).updated_at).to be_an_instance_of(Time) + + end + + it 'can delete the InvoiceItem instance with the corresponding id' do + invoice_items = './data/invoice_items.csv' + ii_repo = InvoiceItemRepository.new(invoice_items) + + expect(ii_repo.find_by_id(10)).to be_a(InvoiceItem) + ii_repo.delete(10) + expect(ii_repo.find_by_id(10)).to eq(nil) + end + +end diff --git a/spec/invoice_item_spec.rb b/spec/invoice_item_spec.rb new file mode 100644 index 0000000000..754143af5c --- /dev/null +++ b/spec/invoice_item_spec.rb @@ -0,0 +1,50 @@ +require "./lib/invoice_item" +require "bigdecimal" +require "Rspec" + +RSpec.describe InvoiceItem do + + + it 'exists' do + data = ({:id => 1, + :item_id => 263519844, + :invoice_id => 1, + :quantity => 5, + :unit_price => 13635, + :created_at => Time.now, + :updated_at => Time.now}) + + invoiceitem = InvoiceItem.new(data) + expect(invoiceitem).to be_an_instance_of(InvoiceItem) + end + + it "can return the details of an invoice id" do + data = ({:id => 1, + :item_id => 263519844, + :invoice_id => 1, + :quantity => 5, + :unit_price => 13635, + :created_at => Time.now.round, + :updated_at => Time.now.round}) + + invoiceitem = InvoiceItem.new(data) + expect(invoiceitem.id).to eq(1) + expect(invoiceitem.item_id).to eq(263519844) + expect(invoiceitem.quantity).to eq(5) + expect(invoiceitem.created_at).to eq(Time.now.round) + expect(invoiceitem.updated_at).to eq(Time.now.round) + end + + it "can return the unit price as a float" do + data = ({:id => 1, + :item_id => 263519844, + :invoice_id => 1, + :quantity => 5, + :unit_price => 13635, + :created_at => Time.now, + :updated_at => Time.now}) + + invoiceitem = InvoiceItem.new(data) + expect(invoiceitem.unit_price_to_dollars).to eq(13635.0) + end +end diff --git a/spec/invoice_repository_spec.rb b/spec/invoice_repository_spec.rb new file mode 100644 index 0000000000..7f1e4d1b8f --- /dev/null +++ b/spec/invoice_repository_spec.rb @@ -0,0 +1,84 @@ +require './lib/item.rb' +require './lib/item_repository' +require './lib/merchant_repository' +require './lib/merchant' +require './lib/invoice' +require './lib/invoice_repository' + +RSpec.describe InvoiceRepository do + + it "exists" do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo).to be_a(InvoiceRepository) + end + + it "can return an array of all invoices" do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo.all.count).to eq(4985) + end + + it "can find a invoice by an id" do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo.find_by_id(1)).to be_a(Invoice) + expect(invoice_repo.find_by_id(123542345293423)).to eq(nil) + end + + it "can find all invoices by a specific customer id" do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo.find_all_by_customer_id(1)).to be_instance_of(Array) + expect(invoice_repo.find_all_by_customer_id(1).length).to eq(8) + expect(invoice_repo.find_all_by_customer_id(12345678910112)).to eq([]) + end + + it "can find all invoices by a matching merchant id" do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo.find_all_by_merchant_id(12335938)).to be_instance_of(Array) + expect(invoice_repo.find_all_by_merchant_id(12335938).length).to eq(16) + expect(invoice_repo.find_all_by_merchant_id(12345678910112)).to eq([]) + end + + it 'can find all invoices by a matching status' do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo.find_all_by_status("shipped")).to be_a(Array) + expect(invoice_repo.find_all_by_status("returned")).to be_a(Array) + expect(invoice_repo.find_all_by_status("pending")).to be_a(Array) + expect(invoice_repo.find_all_by_status("super cool status")).to eq([]) + end + + it 'can create an invoice instance with provided attributes' do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + new_invoice_attributes = {:customer_id => "1000", + :merchant_id => "12334372"} + new_invoice = (invoice_repo.create(new_invoice_attributes)) + expect(new_invoice.customer_id).to eq("1000") + expect(new_invoice.merchant_id).to eq("12334372") + expect(invoice_repo.find_all_by_merchant_id(12334372)).to be_a(Array) + end + + it 'can update an invoices attributes' do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + new_invoice_attributes = {:customer_id => "1000", + :merchant_id => "12334372"} + new_invoice = (invoice_repo.create(new_invoice_attributes)) + + expect(invoice_repo.find_by_id(4986).customer_id).to eq("1000") + expect(invoice_repo.find_by_id(4986).merchant_id).to eq("12334372") + expect(invoice_repo.find_by_id(4986).status).to eq("pending") + + new_test_attributes = {:status => "shipped"} + invoice_repo.update(4986, new_test_attributes) + + expect(invoice_repo.find_by_id(4986).customer_id).to eq("1000") + expect(invoice_repo.find_by_id(4986).merchant_id).to eq("12334372") + expect(invoice_repo.find_by_id(4986).status).to eq("shipped") + expect(invoice_repo.find_by_id(4986).updated_at).to be_instance_of(Time) + end + + it 'can delete an invoice' do + invoice_repo = InvoiceRepository.new('./data/invoices.csv') + expect(invoice_repo.find_by_id(4985)).to be_a(Invoice) + invoice_repo.delete(4985) + expect(invoice_repo.find_by_id(4985)).to eq(nil) + end + +end diff --git a/spec/invoice_spec.rb b/spec/invoice_spec.rb new file mode 100644 index 0000000000..84f543c495 --- /dev/null +++ b/spec/invoice_spec.rb @@ -0,0 +1,80 @@ +require './lib/item' +require 'time' +require 'bigdecimal' +require './lib/invoice.rb' + +RSpec.describe Invoice do + + it "exists" do + inv = Invoice.new({ + :id => 6, + :customer_id => 7, + :status => "pending", + :created_at => Time.now, + :updated_at => Time.now, + :merchant_id => 8}) + + expect(inv).to be_instance_of(Invoice) + end + + it "returns the id" do + inv = Invoice.new({ + :id => 6, + :customer_id => 7, + :status => "pending", + :created_at => Time.now, + :updated_at => Time.now, + :merchant_id => 8}) + + expect(inv.id).to eq(6) + end + + it "returns the customer_id" do + inv = Invoice.new({ + :id => 6, + :customer_id => 7, + :status => "pending", + :created_at => Time.now, + :updated_at => Time.now, + :merchant_id => 8}) + + expect(inv.customer_id).to eq(7) + end + + it "returns the merchant_id" do + inv = Invoice.new({ + :id => 6, + :customer_id => 7, + :status => "pending", + :created_at => Time.now, + :updated_at => Time.now, + :merchant_id => 8}) + + expect(inv.merchant_id).to eq(8) + end + + it "returns the status" do + inv = Invoice.new({ + :id => 6, + :customer_id => 7, + :status => "pending", + :created_at => Time.now, + :updated_at => Time.now, + :merchant_id => 8}) + + expect(inv.status).to eq("pending") + end + + it "returns the time updated at and created at" do + inv = Invoice.new({ + :id => 6, + :customer_id => 7, + :status => "pending", + :created_at => Time.now.round, + :updated_at => Time.now.round, + :merchant_id => 8}) + + expect(inv.created_at).to eq(Time.now.round) + expect(inv.updated_at).to eq(Time.now.round) + end +end diff --git a/spec/item_repository_spec.rb b/spec/item_repository_spec.rb new file mode 100644 index 0000000000..e421bd199f --- /dev/null +++ b/spec/item_repository_spec.rb @@ -0,0 +1,92 @@ +require './lib/item.rb' +require './lib/item_repository' +require './lib/merchant_repository' +require './lib/merchant' + +RSpec.describe ItemRepository do + it "exists" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo).to be_a(ItemRepository) + end + + it "can return an array of all known item instances" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.all.count).to eq(1367) + end + + it "can find item by ID" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_by_id(263400305)).to be_a(Item) + expect(item_repo.find_by_id(12345678910)).to eq(nil) + end + + it "can find an item by name" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_by_name("Free standing Woden letters")).to be_instance_of(Item) + expect(item_repo.find_by_name("FREE stANDing wOdeN lEttErs")).to be_instance_of(Item) + expect(item_repo.find_by_name("InvalidName")).to eq(nil) + end + + it "can return an item by parts of a description" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_all_with_description("Disney")).to be_instance_of(Array) + expect(item_repo.find_all_with_description("dISneY")).to be_instance_of(Array) + #This next one was tricky, I had to look through the items.csv, and filter + #out anything that wasn't a specific item (lots of pitches, dialogues) + expect(item_repo.find_all_with_description("Disney").length).to eq (5) + expect(item_repo.find_all_with_description("Thiago")).to eq([]) + end + + it "can find all items by price" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_all_by_price("1300")).to be_instance_of(Array) + expect(item_repo.find_all_by_price("1300").count).to eq(8) + expect(item_repo.find_all_by_price("1,000,000")).to eq([]) + end + + it "can find all items by price in a range" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_all_by_price_in_range(1..1400)).to be_instance_of(Array) + expect(item_repo.find_all_by_price_in_range(0..0)).to eq([]) + end + + it "can find all by merchant id" do + item_repo = ItemRepository.new('./data/items.csv') + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(item_repo.find_all_by_merchant_id(12334105)).to be_instance_of(Array) + expect(item_repo.find_all_by_merchant_id(12334105).length).to eq(3) + expect(item_repo.find_all_by_merchant_id(12345678910112)).to eq([]) + end + + it "can create a new item with provided attributes" do + item_repo = ItemRepository.new('./data/items.csv') + new_item_attributes = {:name => "Oreos", :description => "a sandwich cookie", + :unit_price => "50", } + new_item = (item_repo.create(new_item_attributes)) + expect(new_item.name).to eq("Oreos") + expect(new_item.unit_price).to eq("50") + expect(new_item.description).to eq("a sandwich cookie") + expect(new_item.created_at).to be_instance_of(Time) + expect(item_repo.find_by_id(263567475)).to be_a(Item) + end + + it "can update an item's attributes" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_by_id(263567474).name).to eq("Minty Green Knit Crochet Infinity Scarf") + expect(item_repo.find_by_id(263567474).description).to eq("- Super Chunky knit infinity scarf\n- Soft mixture of 97% Acrylic and 3% Viscose\n- Beautiful, Warm, and Stylish\n- Very easy to care for\n\nHand wash with cold water and lay flat to dry") + expect(item_repo.find_by_id(263567474).unit_price).to eq("3800") + new_test_attributes = {:name => "New Test Scarf", :description => "A beautiful testing scarf", :unit_price => "1"} + item_repo.update(263567474, new_test_attributes) + expect(item_repo.find_by_id(263567474).name).to eq("New Test Scarf") + expect(item_repo.find_by_id(263567474).description).to eq("A beautiful testing scarf") + expect(item_repo.find_by_id(263567474).unit_price).to eq("1") + expect(item_repo.find_by_id(263567474).updated_at).to be_instance_of(Time) + end + + it "can delete an item" do + item_repo = ItemRepository.new('./data/items.csv') + expect(item_repo.find_by_id(263567474)).to be_a(Item) + item_repo.delete(263567474) + expect(item_repo.find_by_id(263567474)).to eq(nil) + end +end diff --git a/spec/merchant_repository_spec.rb b/spec/merchant_repository_spec.rb new file mode 100644 index 0000000000..c0073b4012 --- /dev/null +++ b/spec/merchant_repository_spec.rb @@ -0,0 +1,78 @@ +require './lib/merchant.rb' +require './lib/merchant_repository.rb' + +RSpec.describe MerchantRepository do + it 'exists' do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(merchant_repo).to be_a(MerchantRepository) + end + + it 'returns an array of all known Merchant instances' do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(merchant_repo.all.count).to eq(475) + end + + it 'can find merchant by ID' do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(merchant_repo.find_by_id(12334105)).to be_a(Merchant) + expect(merchant_repo.find_by_id(12948129048)).to eq(nil) + end + + it 'can find merchant by name' do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(merchant_repo.find_by_name('Shopin1901')).to be_instance_of(Merchant) + expect(merchant_repo.find_by_name('sHoPiN1901')).to be_instance_of(Merchant) + expect(merchant_repo.find_by_name('InvalidName')).to eq(nil) + end + + it 'can find all merchants by name fragment' do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + merchant_repo.find_all_by_name("mini").each do |merchant| + expect merchant.name.include?("mini"). to eq("mini") + end + + expect(merchant.name.downcase.include?("mini")).to eq(true) + expect(merchant).to be_instance_of(Merchant) + end + expect(merchant_repo.find_all_by_name('mini')).to be_instance_of(Array) + + merchant_repo.find_all_by_name("MiNi").each do |merchant| + expect(merchant.name.downcase.include?("mini")).to eq(true) + expect(merchant).to be_instance_of(Merchant) + end + + expect(merchant_repo.find_all_by_name('MiNi')).to be_instance_of(Array) + expect(merchant_repo.find_all_by_name('inG')).to be_instance_of(Array) + expect(merchant_repo.find_all_by_name('sHoPiN')).to be_instance_of(Array) + expect(merchant_repo.find_all_by_name('sHoPiN1901')).to be_instance_of(Array) + + merchant_repo.find_all_by_name("InvalidName").each do |merchant| + expect(merchant.name.downcase.include?("invalidname")).to eq(false) + expect(merchant).to eq(nil) + end + expect(merchant_repo.find_all_by_name('InvalidName')).to eq([]) + end + + it "can create a new merchant instance" do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + new_merchant = merchant_repo.create("Turing School of Software and Design") + expect(new_merchant.name).to eq("Turing School of Software and Design") + expect(merchant_repo.find_by_id(12337412)).to be_a(Merchant) + end + + it "can update a merchant object" do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(merchant_repo.find_by_id(12334105).name).to eq("Shopin1901") + merchant_repo.update(12334105, "Shopin2022") + expect(merchant_repo.find_by_id(12334105).name).to eq("Shopin2022") + expect(merchant_repo.find_by_name("Shopin1901")).to eq(nil) + end + + it 'can delete a merchant object' do + merchant_repo = MerchantRepository.new('./data/merchants.csv') + expect(merchant_repo.find_by_id(12334105)).to be_a(Merchant) + merchant_repo.delete(12334105) + expect(merchant_repo.find_by_id(12334105)).to eq(nil) + end + +end diff --git a/spec/merchant_spec.rb b/spec/merchant_spec.rb new file mode 100644 index 0000000000..6b228668fc --- /dev/null +++ b/spec/merchant_spec.rb @@ -0,0 +1,21 @@ +require './lib/merchant' + +RSpec.describe Merchant do + it "exists" do + merchant = Merchant.new(:id => 1, :name => "Bob's Burgers") + expect(merchant).to be_instance_of (Merchant) + end + + + it "can return a name" do + merchant = Merchant.new(:id => 1, :name => "Bob's Burgers") + + expect(merchant.name).to eq("Bob's Burgers") + end + + it "can return an id" do + merchant = Merchant.new(:id => 1, :name => "Bob's Burgers") + + expect(merchant.id).to eq(1) + end +end diff --git a/spec/sales_engine_spec.rb b/spec/sales_engine_spec.rb new file mode 100644 index 0000000000..a100aa1804 --- /dev/null +++ b/spec/sales_engine_spec.rb @@ -0,0 +1,48 @@ +require "./lib/sales_engine" +require "./lib/item_repository" +require "./lib/merchant_repository" +require "./lib/invoice_repository" + +RSpec.describe SalesEngine do + it "exists" do + sales_engine = SalesEngine.from_csv({ + :items => "./data/items.csv", + :merchants => "./data/merchants.csv", + :invoices => "./data/invoices.csv" + }) + expect(sales_engine).to be_instance_of SalesEngine + end + + it "can return an array of all items" do + sales_engine = SalesEngine.from_csv({ + :items => "./data/items.csv", + :merchants => "./data/merchants.csv", + :invoices => "./data/invoices.csv" + + }) + + expect(sales_engine.items).to be_instance_of ItemRepository + end + + it "can return an array of all merchants" do + sales_engine = SalesEngine.from_csv({ + :items => "./data/items.csv", + :merchants => "./data/merchants.csv", + :invoices => "./data/invoices.csv" + + }) + expect(sales_engine.merchants).to be_instance_of MerchantRepository + + end + + it "can return an array of all merchants" do + sales_engine = SalesEngine.from_csv({ + :items => "./data/items.csv", + :merchants => "./data/merchants.csv", + :invoices => "./data/invoices.csv" + + }) + expect(sales_engine.invoices).to be_instance_of InvoiceRepository + + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000000..39e075fadc --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,2 @@ +require 'simplecov' +SimpleCov.start