diff --git a/lib/far_mar.rb b/lib/far_mar.rb index b5b6336f..7b177d7d 100644 --- a/lib/far_mar.rb +++ b/lib/far_mar.rb @@ -1,7 +1,10 @@ require 'csv' require 'time' +require 'pry' # Order matters here so I might have to change it +require './lib/far_mar/far_mar_base' +require './lib/far_mar/vend_prod_base' require './lib/far_mar/market' require './lib/far_mar/vendor' require './lib/far_mar/product' diff --git a/lib/far_mar/far_mar_base.rb b/lib/far_mar/far_mar_base.rb new file mode 100644 index 00000000..a504eabc --- /dev/null +++ b/lib/far_mar/far_mar_base.rb @@ -0,0 +1,43 @@ +module FarMar + class FarMar_Base + def initialize(init_hash) + # This block sets each key to an instance variable and assigns the value + init_hash.each do |k,v| + instance_variable_set("@#{k}", v) unless v.nil? + end + end + + def self.all + if !self.class_variable_defined?(:@@all_objects) + csv_file = CSV.read(self::FILENAME) + # Create empty array which will hold all the objects + objects = [] + csv_file.each do |row| + # Convert the array to a hash + csv_hash = self.convert_to_hash(row) + # Create an object from each row-hash in the csv file + temp = self.new(csv_hash) + # Push object to array of products + objects.push(temp) + end + self.class_variable_set(:@@all_objects, objects) + end + self.all_objects + end + + def self.find(id) + self.all_objects.find { |obj| obj.id == id } + end + + # returns a single instance whose attribute matches the parameter + def self.find_by_name(match) + return nil if match.class != String + result = FarMar::Vendor.all_objects.find do |vendor| + test_string = vendor.name.downcase + test_string.include?(match.downcase) + end + return result + end + + end +end diff --git a/lib/far_mar/market.rb b/lib/far_mar/market.rb index 2515aaf6..84706b3b 100644 --- a/lib/far_mar/market.rb +++ b/lib/far_mar/market.rb @@ -1,5 +1,93 @@ module FarMar - class Market + class Market < FarMar_Base + attr_reader :id, :name, :address, :city, :county, :state, :zip + FILENAME = './support/markets.csv' + + def initialize(market_hash) + super(market_hash) + end + + def self.all_objects + @@all_objects ||= self.all + end + + # Converts an array to a hash for passing to market instantiation + def self.convert_to_hash(market_array) + market_hash = {} + market_hash[:id] = market_array[0].to_i + market_hash[:name] = market_array[1] + market_hash[:address] = market_array[2] + market_hash[:city] = market_array[3] + market_hash[:county] = market_array[4] + market_hash[:state] = market_array[5] + market_hash[:zip] = market_array[6] + return market_hash + end + + # Returns a collection of FarMar::Market instances where the market name + # or vendor name contain the search_term + def self.search(search_term) + return [] if search_term.class != String + search_term.downcase! + # find all markets that include the search term in the market name + market_match = FarMar::Market.all_objects.select do |market| + market_name = market.name.downcase + market_name.include?(search_term) + end + # find all markets that have the search term in the vendor name + vendor_match = FarMar::Vendor.all_objects.select do |vendor| + vendor_name = vendor.name.downcase + vendor_name.include?(search_term) + end + # This iterates through the vendors that include the search term + vendor_match.each do |vendor| + # and finds their associated market based on the market_id + market = FarMar::Market.find(vendor.market_id) + # then checks to see if the market is already in the market_match array + # and if not, it pushes it into the array + market_match.push(market) if !market_match.include?(market) + end + return market_match + end + + # Returns a collection of FarMar::Vendor instances that are associated + # with the market by the market_id field + def vendors + return FarMar::Vendor.by_market(@id) + end + + # returns a collection of FarMar::Product instances that are associated + # to the market through the FarMar::Vendor class + def products + products = [] + v = vendors + v.each do |vendor| + products += vendor.products + end + return products + end + + # returns the vendor with the highest revenue for the given date + # or returns the vendor with the highest revenue if no date is given + def preferred_vendor(date = nil) + return vendors.max_by { |vend| vend.revenue } if date.nil? + return nil if date.class != DateTime + m_vendors = vendors + rev = m_vendors.map { |vend| vend.day_revenue(date) } + max_index = rev.each_with_index.max[1] + return m_vendors[max_index] + end + + # returns the vendor with the lowest revenue on the given date + # or returns the vendor with the lowest revenue if no date is given + def worst_vendor(date = nil) + return vendors.min_by { |vend| vend.revenue } if date.nil? + return nil if date.class != DateTime + m_vendors = vendors + rev = m_vendors.map { |vend| vend.day_revenue(date) } + min_index = rev.each_with_index.min[1] + return m_vendors[min_index] + end end end diff --git a/lib/far_mar/product.rb b/lib/far_mar/product.rb index 8efc48d2..c95edec7 100644 --- a/lib/far_mar/product.rb +++ b/lib/far_mar/product.rb @@ -1,5 +1,57 @@ module FarMar - class Product + class Product < FarMar_Base + attr_reader :id, :name, :vendor_id + FILENAME = './support/products.csv' + REV_ATTR = :@@product_stats # the attribute accessed by the revenue method + # include adds methods to the instance of a class + # in this case, revenue is an instance method that is included + include VendorProductBase + + def initialize(product_hash) + super(product_hash) + @revenue = revenue + end + + def self.all_objects + @@all_objects ||= self.all + end + + # Converts an array to a hash for passing to product instantiation + def self.convert_to_hash(product_array) + product_hash = {} + product_hash[:id] = product_array[0].to_i + product_hash[:name] = product_array[1] + product_hash[:vendor_id] = product_array[2].to_i + return product_hash + end + + # returns all of the products with the given vendor_id + def self.by_vendor(vendor_id) + FarMar::Product.all_objects.find_all { |product| product.vendor_id == vendor_id } + end + + # returns the top n products instances ranked by total revenue + def self.most_revenue(n) + most_x(n, "@revenue") + # FarMar::VendorProductBase.class_method(:most_x).bind(self).call(n, "@revenue") + end + + # returns the FarMar::Vendor instance that is associated with this + # vendor using the vendor_id field + def vendor + return FarMar::Vendor.find(@vendor_id) + end + + # returns a collection of FarMar::Sale instances that are associated using + # the product_id field + def sales + return FarMar::Sale.by_product(@id) + end + + # returns the number of times the product has been sold + def number_of_sales + return sales.length + end end end diff --git a/lib/far_mar/sale.rb b/lib/far_mar/sale.rb index d68f9ded..a3625851 100644 --- a/lib/far_mar/sale.rb +++ b/lib/far_mar/sale.rb @@ -1,5 +1,99 @@ module FarMar - class Sale + class Sale < FarMar_Base + attr_reader :id, :amount, :purchase_time, :vendor_id, :product_id + FILENAME = './support/sales.csv' + def initialize(sale_hash) + super(sale_hash) + end + + def self.all_objects + @@all_objects ||= self.all[0] + end + + def self.vendor_stats + @@vendor_stats ||= self.all[1] + end + + def self.product_stats + @@product_stats ||= self.all[2] + end + + def self.all + if !self.class_variable_defined?(:@@all_objects) ||!self.class_variable_defined?(:@@vendor_stats) + csv_file = CSV.read(FILENAME) + # Create empty array which will hold all the objects + objects = [] + vend_stats = {} + prod_stats = {} + csv_file.each do |row| + # Convert the array to a hash + sale_hash = convert_to_hash(row) + # Create an object from each row-hash in the csv file + temp = self.new(sale_hash) + # Push object to array of products + objects.push(temp) + # Populate the vend_stats array + if vend_stats[sale_hash[:vendor_id]].nil? # if there is no revenue yet + vend_stats[sale_hash[:vendor_id]] = {} + vend_stats[sale_hash[:vendor_id]][:revenue] = sale_hash[:amount] # store the first revenue + vend_stats[sale_hash[:vendor_id]][:num_sales] = 1 # and tally 1 for number of sales + else + vend_stats[sale_hash[:vendor_id]][:revenue] += sale_hash[:amount] # add the amount to the revenue + vend_stats[sale_hash[:vendor_id]][:num_sales] += 1 # and add 1 to sale tally + end + # Populate product_stats array + if prod_stats[sale_hash[:product_id]].nil? # if there is no product revenue yet + prod_stats[sale_hash[:product_id]] = {} + prod_stats[sale_hash[:product_id]][:revenue] = sale_hash[:amount] # stores the first revenue + else + prod_stats[sale_hash[:product_id]][:revenue] += sale_hash[:amount] # adds the amount to the revenue + end + end + return self.class_variable_set(:@@all_objects, objects), self.class_variable_set(:@@vendor_stats, vend_stats), self.class_variable_set(:@@product_stats, prod_stats) + + end + self.all_objects + end + + def self.convert_to_hash(sale_array) + sale_hash = {} + sale_hash[:id] = sale_array[0].to_i + sale_hash[:amount] = sale_array[1].to_i + sale_hash[:purchase_time] = DateTime.parse(sale_array[2]) + sale_hash[:vendor_id] = sale_array[3].to_i + sale_hash[:product_id] = sale_array[4].to_i + return sale_hash + end + + # returns all of the sales with the given product id + def self.by_product(product_id) + return FarMar::Sale.all_objects.find_all { |sale| sale.product_id == product_id } + end + + # returns all of the sales with the given vendor id + def self.by_vendor(vendor_id) + return FarMar::Sale.all_objects.find_all { |sale| sale.vendor_id == vendor_id } + end + + # returns a collection of FarMar::Sale objects where the purchase time + # is between the two times given as arguments + def self.between(beginning_time, end_time) + return [] if + beginning_time.class != DateTime || + end_time.class != DateTime || + end_time <= beginning_time + return FarMar::Sale.all_objects.find_all { |sale_obj| sale_obj.purchase_time > beginning_time && sale_obj.purchase_time < end_time } + end + + # returns the Vendor that is associated with the sale + def vendor + return FarMar::Vendor.find(@vendor_id) + end + + # returns the Product that is associated with the sale + def product + return FarMar::Product.find(@product_id) + end end end diff --git a/lib/far_mar/vend_prod_base.rb b/lib/far_mar/vend_prod_base.rb new file mode 100644 index 00000000..a02e8660 --- /dev/null +++ b/lib/far_mar/vend_prod_base.rb @@ -0,0 +1,34 @@ +module FarMar + module VendorProductBase + # info from http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/ + def self.included(base) + # extend is for adding class methods + base.extend(ClassMethods) + end + + module ClassMethods + # these are class methods for the VendorProductBase module + # written this way so that "self" refers to the class that is calling it + # self is either FarMar::Vendor or FarMar::Product + def most_x(n, attribute) + return [] if + n.class != Fixnum || + n < 0 || + n > self.all_objects.length + backwards = self.all_objects.sort_by { |obj| obj.instance_variable_get(attribute) } + sorted = backwards.reverse + return sorted[0, n] + end + end + + def revenue + return @revenue if !@revenue.nil? + results = FarMar::Sale.class_variable_get(self.class::REV_ATTR) + if results[@id].nil? + @revenue = 0 + else + @revenue = results[@id][:revenue] + end + end + end +end diff --git a/lib/far_mar/vendor.rb b/lib/far_mar/vendor.rb index bfe19c33..4a138101 100644 --- a/lib/far_mar/vendor.rb +++ b/lib/far_mar/vendor.rb @@ -1,5 +1,90 @@ module FarMar - class Vendor + class Vendor < FarMar_Base + attr_reader :id, :name, :emp_num, :market_id + FILENAME = './support/vendors.csv' + REV_ATTR = :@@vendor_stats # the attribute accessed by the revenue method + + # include adds methods to the instance of a class + # in this case, revenue is an instance method that is included + include VendorProductBase + + def initialize(vendor_hash) + super(vendor_hash) + @revenue = revenue + @num_sales = num_sales + end + + def self.all_objects + @@all_objects ||= self.all + end + + def self.convert_to_hash(array) + vendor = {} + vendor[:id] = array[0].to_i + vendor[:name] = array[1] + vendor[:emp_num] = array[2].to_i + vendor[:market_id] = array[3].to_i + return vendor + end + + # returns all of the vendors with the given market_id + def self.by_market(market_id) + FarMar::Vendor.all_objects.find_all { |vendor| vendor.market_id == market_id } + end + + # returns the top n vendor instances ranked by total number of items sold + def self.most_revenue(n) + most_x(n, "@revenue") + end + + # returns the top n vendor instances ranked by total number of items sold + def self.most_items(n) + most_x(n, "@num_sales") + end + + # returns a collection of FarMar::Product instances that are + # associated by the FarMar::Product vendor_id field + def products + return FarMar::Product.by_vendor(@id) + end + + # returns a collection of FarMar::Sale instances that are + # associated by the vendor_id + def sales + return FarMar::Sale.by_vendor(@id) + end + + # returns the FarMar::Market instance that is associate with this vendor + # using the FarMar::Vendor market_id field + def market + return FarMar::Market.find(@market_id) + end + + def num_sales + return @num_sales if !@num_sales.nil? + results = FarMar::Sale.vendor_stats + if results[@id].nil? + @num_sales = 0 + else + @num_sales = results[@id][:num_sales] + end + end + + # returns the total revenue across all vendors for a given date + def self.revenue_on(date) + return 0 if date.class != DateTime + match = FarMar::Sale.all_objects.select { |sale| sale.purchase_time.to_date == date.to_date } + rev = match.inject(0) { |sum, sale| sum + sale.amount } + return rev + end + + # returns the total revenue for the specific date and vendor instance + def day_revenue(date) + return 0 if date.class != DateTime + all_sales = FarMar::Sale.by_vendor(@id) + day_sales = all_sales.select { |sale| sale.purchase_time.to_date == date.to_date } + return day_sales.inject(0) { |sum, sale_obj| sum + sale_obj.amount } + end end end diff --git a/spec/far_mar/market_spec.rb b/spec/far_mar/market_spec.rb index 97f0833b..012e15cf 100644 --- a/spec/far_mar/market_spec.rb +++ b/spec/far_mar/market_spec.rb @@ -2,10 +2,144 @@ describe FarMar do describe FarMar::Market do + market_hash = FarMar::Market.convert_to_hash(["64","Oakmont Farmers Market","1 W Eagle Road","Havertown","Delaware","Pennsylvania","19083"]) + let(:sample_market) { FarMar::Market.new(market_hash)} + let(:sample_market2) { FarMar::Market.new({ :id => 20, :name => "Scottdale Farmers Market", :address => "1 Centennial Way", :city => "Scottdale", :county => "Westmoreland", :state => "Pennsylvania", :zip => "15683" })} describe "#initialize" do it "creates a new Market instance" do - expect(FarMar::Market.new()).to be_an_instance_of(FarMar::Market) + expect(sample_market).to be_an_instance_of(FarMar::Market) + end + market_hash.each do |attr, val| + it "assigns the #{attr} attribute correctly" do + expect(sample_market.instance_variable_get("@#{attr}")).to eq(val) + end + end + end + + describe ".all" do + it "returns an array of 500 Market objects" do + all_markets = FarMar::Market.all + expect(all_markets).to be_an(Array) + expect(all_markets[0]).to be_an_instance_of(FarMar::Market) + expect(all_markets[-1]).to be_an_instance_of(FarMar::Market) + expect(all_markets[0].id).to eq(1) + expect(all_markets[-1].id).to eq(500) + expect(all_markets.length).to eq(500) + end + end + + describe ".find(id)" do + it "returns nil when id is not an integer" do + expect(FarMar::Market.find('a')).to be_nil + expect(FarMar::Market.find([1, 2])).to be_nil + end + it "returns nil for no matching id" do + expect(FarMar::Market.find(9999999999999)).to be_nil + expect(FarMar::Market.find(-1)).to be_nil + end + + it "returns Market object for matching id" do + result = FarMar::Market.find(18) + expect(result).to be_an_instance_of(FarMar::Market) + expect(result.name).to eq("Grand Valley State University Farmers Market") + end + end + + describe ".search(search_term)" do + let(:cor_search) { FarMar::Market.search("cor") } + it "returns an empty array when search term is not a string" do + expect(FarMar::Market.search(123)).to eq([]) + expect(FarMar::Market.search([1, 2, 3])).to eq([]) + end + it "returns a collection of market instances" do + expect(cor_search).to be_an_instance_of(Array) + cor_search.each do |item| + expect(item).to be_an_instance_of(FarMar::Market) + end + end + it "markets have search term in market or vendor name" do + expect(cor_search.length).to eq(37) + end + + end + + describe "#vendors" do + it "returns array of vendors for the market" do + vendors = sample_market2.vendors + expect(vendors).to be_an(Array) + expect(vendors.length).to eq(7) + expect(vendors[-1]).to be_an_instance_of(FarMar::Vendor) + expect(vendors[0].name).to eq("Davis Group") end end + + describe "#products" do + it "returns all Products sold in the market" do + products = sample_market.products + expect(products).to be_an_instance_of(Array) + expect(products.length).to eq(4) + expect(products[0]).to be_an_instance_of(FarMar::Product) + expect(products[0].id).to eq(1073) + expect(products[-1].id).to eq(1076) + products2 = sample_market2.products + expect(products2.length).to eq(22) + end + end + + # Returns the vendor with the highest revenue + describe "#preferred_vendor" do + it "returns the market's vendor with the highest revenue" do + max_vendor1 = sample_market.preferred_vendor + expect(max_vendor1).to be_an_instance_of(FarMar::Vendor) + expect(max_vendor1.id).to eq(350) + max_vendor2 = sample_market2.preferred_vendor + expect(max_vendor2).to be_an_instance_of(FarMar::Vendor) + expect(max_vendor2.id).to eq(102) + expect(max_vendor2.revenue).to eq(44789) + end + end + + # Returns the vendor with the lowest revenue + describe "#worst_vendor" do + it "returns the market's vendor with the lowest revenue" do + min_vendor1 = sample_market.worst_vendor + expect(min_vendor1).to be_an_instance_of(FarMar::Vendor) + expect(min_vendor1.id).to eq(350) + min_vendor2 = sample_market2.worst_vendor + expect(min_vendor2).to be_an_instance_of(FarMar::Vendor) + expect(min_vendor2.id).to eq(105) + expect(min_vendor2.revenue).to eq(1810) + end + end + + # Returns the vendor with the highest revenue for the given date + describe "#preferred_vendor(date)" do + it "returns nil for an invalid date" do + expect(sample_market.preferred_vendor(123)).to be_nil + expect(sample_market.preferred_vendor('abc')).to be_nil + end + it "returns the vendor with the highest revenue for the given date" do + date = DateTime.parse("2013-11-12T13:07:19-08:00") + preferred = sample_market2.preferred_vendor(date) + expect(preferred).to be_an_instance_of(FarMar::Vendor) + expect(preferred.id).to eq(104) + end + end + + # Returns the vendor with the lowest revenue for the given date + describe "#worst_vendor(date)" do + it "returns nil for an invalid date" do + expect(sample_market.worst_vendor(123)).to be_nil + expect(sample_market.worst_vendor('abc')).to be_nil + end + it "returns the vendor with the lowest revenue for the given date" do + date = DateTime.parse("2013-11-12T13:07:19-08:00") + worst = sample_market2.worst_vendor(date) + expect(worst).to be_an_instance_of(FarMar::Vendor) + # NOTE: many different possible with 0: 102, 105, 107 + expect(worst.id).to eq(102) + end + end + end end diff --git a/spec/far_mar/product_spec.rb b/spec/far_mar/product_spec.rb index c11eb829..e5c5b19c 100644 --- a/spec/far_mar/product_spec.rb +++ b/spec/far_mar/product_spec.rb @@ -2,9 +2,101 @@ describe FarMar do describe FarMar::Product do + product_hash = FarMar::Product.convert_to_hash(["14","Stupendous Carrots","7"]) + let(:sample_product) { FarMar::Product.new(product_hash) } describe "#initialize" do it "creates a new Product instance" do - expect(FarMar::Product.new()).to be_an_instance_of(FarMar::Product) + expect(sample_product).to be_an_instance_of(FarMar::Product) + end + product_hash.each do |attr, val| + it "assigns the #{attr} attribute correctly" do + expect(sample_product.instance_variable_get("@#{attr}")).to eq(val) + end + end + end + + describe ".all" do + it "returns an array of 8193 Product objects" do + all_products = FarMar::Product.all + expect(all_products).to be_an(Array) + expect(all_products.length).to eq(8193) + expect(all_products[0]).to be_an_instance_of(FarMar::Product) + expect(all_products[-1]).to be_an_instance_of(FarMar::Product) + expect(all_products[-1].name).to eq("Cruel Beef") + end + end + + describe ".find(id)" do + it "returns Product object for matching ID" do + result = FarMar::Product.find(11) + expect(result).to be_an_instance_of(FarMar::Product) + expect(result.name).to eq("Gigantic Bread") + expect(result.vendor_id).to eq(6) + end + end + + describe ".by_vendor(vendor_id)" do + it "returns empty array for an invalid vendor_id" do + expect(FarMar::Product.by_vendor('a')).to eq([]) + expect(FarMar::Product.by_vendor([1, 2])).to eq([]) + expect(FarMar::Product.by_vendor(-5)).to eq([]) + expect(FarMar::Product.by_vendor(999999999999)).to eq([]) + end + + it "returns all the products with the given vendor_id" do + products = FarMar::Product.by_vendor(91) + expect(products).to be_an_instance_of(Array) + expect(products.length).to eq(3) + expect(products[-1].id).to eq(285) + end + end + + describe ".revenue" do + it "returns the revenue for a given product" do + expect(sample_product.revenue).to eq(39719) + end + end + + describe ".most_revenue(n)" do + it "returns an empty array when n is invalid" do + expect(FarMar::Product.most_revenue(-3)).to eq([]) + expect(FarMar::Product.most_revenue('abc')).to eq([]) + expect(FarMar::Product.most_revenue(9999999999999)).to eq([]) + end + it "returns the top n products ranked by total revenue" do + top_revenue = FarMar::Product.most_revenue(1) + top_five = FarMar::Product.most_revenue(5) + expect(top_revenue).to be_an_instance_of(Array) + expect(top_revenue.length).to eq(1) + expect(top_revenue[0].revenue).to eq(118516) + expect(top_five).to be_an_instance_of(Array) + expect(top_five.length).to eq(5) + expect(top_five[-1].revenue).to eq(99098) + end + end + + describe "#sales" do + it "returns array of Sales that match the product id" do + sales = sample_product.sales + expect(sales).to be_an_instance_of(Array) + expect(sales.length).to eq(7) + expect(sales[0].id).to eq(32) + expect(sales[-1].id).to eq(38) + end + end + + describe "#vendor" do + it "returns the Vendor associated with this Product" do + sample_vendor = sample_product.vendor + expect(sample_vendor).to be_an_instance_of(FarMar::Vendor) + expect(sample_vendor.id).to eq(sample_product.vendor_id) + expect(sample_vendor.name).to eq("Bechtelar Inc") + end + end + + describe "#number_of_sales" do + it "returns the number of times the product has been sold" do + expect(sample_product.number_of_sales).to eq(7) end end end diff --git a/spec/far_mar/sale_spec.rb b/spec/far_mar/sale_spec.rb index 0168ee5f..76c074e3 100644 --- a/spec/far_mar/sale_spec.rb +++ b/spec/far_mar/sale_spec.rb @@ -2,9 +2,88 @@ describe FarMar do describe FarMar::Sale do + sale_hash = FarMar::Sale.convert_to_hash(["1", "9290", "2013-11-12 04:36:56 -0800", "5", "12"]) + let(:sample_sale) { FarMar::Sale.new(sale_hash) } describe "#initialize" do it "creates a new Sale instance" do - expect(FarMar::Sale.new()).to be_an_instance_of(FarMar::Sale) + expect(sample_sale).to be_an_instance_of(FarMar::Sale) + end + sale_hash.each do |attr, val| + it "assigns the #{attr} attribute correctly" do + expect(sample_sale.instance_variable_get("@#{attr}")).to eq(val) + end + end + end + describe ".all" do + it "returns an array of 12798 Sale objects" do + all_sales = FarMar::Sale.all + expect(all_sales).to be_an(Array) + expect(all_sales[0].id).to eq(1) + expect(all_sales[0].product_id).to eq(1) + expect(all_sales[-1].id).to eq(12001) + expect(all_sales[-1].product_id).to eq(8192) + expect(all_sales.length).to eq(12798) + end + end + + describe ".find(id)" do + it "returns Sale object for matching ID" do + result = FarMar::Sale.find(19) + expect(result).to be_an_instance_of(FarMar::Sale) + expect(result.id).to eq(19) + expect(result.amount).to eq(9035) + expect(result.vendor_id).to eq(4) + expect(result.product_id).to eq(6) + end + end + + describe ".by_product(product_id)" do + it "returns empty array for an invalid product_id" do + expect(FarMar::Sale.by_product('a')).to eq([]) + expect(FarMar::Sale.by_product([1, 2])).to eq([]) + expect(FarMar::Sale.by_product(-5)).to eq([]) + expect(FarMar::Sale.by_product(999999999999)).to eq([]) + end + it "returns all the products with the given product_id" do + products = FarMar::Sale.by_product(14) + expect(products).to be_an_instance_of(Array) + expect(products.length).to eq(7) + expect(products[0].id).to eq(32) + expect(products[-1].id).to eq(38) + end + end + + describe "#vendor" do + it "returns vendor associated with the sale" do + sample_vendor = sample_sale.vendor + expect(sample_vendor.id).to eq(sample_sale.vendor_id) + expect(sample_vendor.name).to eq("Reynolds, Schmitt and Klocko") + end + end + + describe "#product" do + it "returns the Product associate with the sale" do + sample_product = sample_sale.product + expect(sample_product.id).to eq(sample_sale.product_id) + expect(sample_product.name).to eq("Gorgeous Fish") + end + end + + describe "#between(beginning_time, end_time)" do + beginning = FarMar::Sale.find(1990).purchase_time + ending = FarMar::Sale.find(3602).purchase_time + + it "returns empty array if parameters not DateTime" do + expect(FarMar::Sale.between('a', 'b')).to eq([]) + end + it "returns empty array if end time is before or equal to beginning" do + expect(FarMar::Sale.between(ending, beginning)).to eq([]) + end + it "returns all sales where the purchase time is between two times given" do + + between_array = FarMar::Sale.between(beginning, ending) + expect(between_array).to be_an_instance_of(Array) + expect(between_array.length).to eq(24) end end end diff --git a/spec/far_mar/vendor_spec.rb b/spec/far_mar/vendor_spec.rb index 04290bd9..29c45d73 100644 --- a/spec/far_mar/vendor_spec.rb +++ b/spec/far_mar/vendor_spec.rb @@ -2,9 +2,170 @@ describe FarMar do describe FarMar::Vendor do + vendor_hash = FarMar::Vendor.convert_to_hash(["70","Eichmann Group","8","16"]) + let(:sample_vendor) { FarMar::Vendor.new(vendor_hash) } describe "#initialize" do it "creates a new Vendor instance" do - expect(FarMar::Vendor.new()).to be_an_instance_of(FarMar::Vendor) + expect(sample_vendor).to be_an_instance_of(FarMar::Vendor) + end + vendor_hash.each do |attr, val| + it "assigns the #{attr} attribute correctly" do + expect(sample_vendor.instance_variable_get("@#{attr}")).to eq(val) + end + end + end + describe "self.all" do + it "returns an array of 2690 Vendor objects" do + FarMar::Vendor.all + expect(FarMar::Vendor.all_objects).to be_an(Array) + expect(FarMar::Vendor.all_objects.length).to eq(2690) + expect(FarMar::Vendor.all_objects[0].id).to eq(1) + expect(FarMar::Vendor.all_objects[-1].id).to eq(2690) + end + end + + describe ".find(id)" do + it "returns Vendor object for matching ID" do + result = FarMar::Vendor.find(2690) + expect(result).to be_an_instance_of(FarMar::Vendor) + expect(result.id).to eq(2690) + expect(result.name).to eq("Mann-Lueilwitz") + expect(result.emp_num).to eq(4) + expect(result.market_id).to eq(500) + end + end + + describe ".by_market(market_id)" do + it "returns empty array for an invalid market_id" do + expect(FarMar::Vendor.by_market('a')).to eq([]) + expect(FarMar::Vendor.by_market([1, 2])).to eq([]) + expect(FarMar::Vendor.by_market(-5)).to eq([]) + expect(FarMar::Vendor.by_market(999999999999)).to eq([]) + end + it "returns all the vendors with the given market_id" do + vendors = FarMar::Vendor.by_market(12) + expect(vendors).to be_an_instance_of(Array) + expect(vendors.length).to eq(3) + expect(vendors[0].id).to eq(51) + end + end + + describe ".most_revenue(n)" do + it "returns an empty array when n is invalid" do + expect(FarMar::Vendor.most_revenue(-1)).to eq([]) + expect(FarMar::Vendor.most_revenue('a')).to eq([]) + expect(FarMar::Vendor.most_revenue(9999999999999999)).to eq([]) + end + it "returns the top n vendor instances ranked by total revenue" do + top_revenue = FarMar::Vendor.most_revenue(1) + top_five = FarMar::Vendor.most_revenue(5) + expect(top_revenue).to be_an_instance_of(Array) + expect(top_revenue[0].revenue).to eq(123474) + expect(top_five).to be_an_instance_of(Array) + expect(top_five.length).to eq(5) + expect(top_five[0].revenue).to eq(123474) + expect(top_five[-1].revenue).to eq(107516) + end + end + + describe ".most_items(n)" do + it "returns an empty array when n is invalid" do + expect(FarMar::Vendor.most_items(-1)).to eq([]) + expect(FarMar::Vendor.most_items('a')).to eq([]) + expect(FarMar::Vendor.most_items(9999999999999999)).to eq([]) + end + it "returns the top n vendor instances ranked by number of items sold" do + top_item = FarMar::Vendor.most_items(1) + top_thirty = FarMar::Vendor.most_items(30) + expect(top_item).to be_an_instance_of(Array) + expect(top_item.length).to eq(1) + expect(top_item[0].num_sales).to eq(18) + expect(top_thirty).to be_an_instance_of(Array) + expect(top_thirty.length).to eq(30) + expect(top_thirty[-1].num_sales).to eq(17) + end + end + + describe ".find_by_name(match)" do + it "returns nil for no match" do + expect(FarMar::Vendor.find_by_name(3)).to be_nil + expect(FarMar::Vendor.find_by_name('xxxxxxxxxx')).to be_nil + expect(FarMar::Vendor.find_by_name([])).to be_nil + end + it "returns a single instance for matching the attribute" do + expect(FarMar::Vendor.find_by_name('Von-Hamill').id).to be(18) + expect(FarMar::Vendor.find_by_name('von-hamill').id).to be(18) + end + end + + describe "#products" do + it "returns a collection of Products with the vendor's ID" do + products = sample_vendor.products + expect(products).to be_an(Array) + expect(products.length).to eq(5) + expect(products[0].id).to eq(221) + expect(products[-1].name).to eq("Cheerful Bread") + end + end + + describe "#sales" do + it "returns a collection of Sales with the vendor's ID" do + sales = sample_vendor.sales + expect(sales).to be_an(Array) + expect(sales.length).to eq(7) + expect(sales[0].id).to eq(313) + expect(sales[-1].id).to eq(319) + end + end + + describe "#market" do + it "returns the market associated with the vendor" do + sample_market = sample_vendor.market + expect(sample_market).to be_an_instance_of(FarMar::Market) + expect(sample_market.id).to eq(sample_vendor.market_id) + expect(sample_market.name).to eq("Riverside Farmers' Market") + end + end + + describe "#revenue" do + it "returns the sum of all the vendor's sales" do + expect(sample_vendor.revenue).to eq(17211) + end + end + + describe "#day_revenue(date)" do + it "returns 0 for invalid date" do + expect(sample_vendor.day_revenue(123)).to eq(0) + expect(sample_vendor.day_revenue('abc')).to eq(0) + end + it "returns the total revenue for the vendor on the given date" do + date1 = DateTime.parse("2013-11-12T13:07:19-08:00") + date2 = DateTime.parse("2013-11-10T15:40:57-08:00") + date3 = DateTime.parse("2013-11-08T07:41:09-08:00") + date4 = DateTime.parse("2013-11-09T07:41:09-08:00") + expect(sample_vendor.day_revenue(date1)).to eq(1135) + expect(sample_vendor.day_revenue(date2)).to eq(7225) + expect(sample_vendor.day_revenue(date3)).to eq(4733) + expect(sample_vendor.day_revenue(date4)).to eq(0) + end + end + + describe ".revenue_on(date)" do + it "returns 0 for invalid dates" do + expect(FarMar::Vendor.revenue_on(123)).to eq(0) + expect(FarMar::Vendor.revenue_on('abc')).to eq(0) + end + it "returns the total revenue for the date across all vendors" do + date1 = DateTime.parse("2013-11-12T13:07:19-08:00") + date2 = DateTime.parse("2013-11-10T15:40:57-08:00") + match1 = FarMar::Vendor.revenue_on(date1) + match2 = FarMar::Vendor.revenue_on(date2) + # date3 = DateTime.parse("2013-11-08T07:41:09-08:00") + # date4 = DateTime.parse("2013-11-09T07:41:09-08:00") + expect(match1).to be_an_instance_of(Fixnum) + expect(match1).to eq(8871052) + expect(match2).to be_an_instance_of(Fixnum) + expect(match2).to eq(9119618) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f7dc6dfb..3ac4c70e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,8 @@ require 'simplecov' SimpleCov.start +RSpec.configure do |config| + config.order = 'random' +end + require './lib/far_mar'