diff --git a/app/models/importers/ingredients_importer.rb b/app/models/importers/ingredients_importer.rb new file mode 100644 index 00000000..7ba4f28b --- /dev/null +++ b/app/models/importers/ingredients_importer.rb @@ -0,0 +1,44 @@ +require "csv" + +class Importers::IngredientsImporter + def initialize(file_path:, initiator:) + @initiator = initiator + @file_path = file_path + + check_filetype + + @data = CSV.read(@file_path, headers: true) + + check_headers + end + + def run + @data.each do |row| + import_row(row) + end + end + + def import_row(row) + name = row["název"] + measurement = Measurement.find_by(name: row["jednotka"]) + category = IngredientCategory.find_by(name: row["kategorie"]) + + return if @initiator.ingredients.find_by(name:).present? + return if Ingredient.common.find_by(name:).present? + + ingredient = Ingredient.new(name: row["název"], measurement:, category:, author: @initiator) + ingredient.save! + end + + private + + def check_filetype + raise Exception, "Importer can only work with csv files for now" unless File.extname(@file_path) == ".csv" + end + + def check_headers + required_headers = [ "název", "jednotka", "kategorie" ] + + raise NameError, "Headers must include: #{required_headers.join(", ")}" unless (@data.headers & required_headers) == required_headers + end +end diff --git a/test/data/importers/ingredients.csv b/test/data/importers/ingredients.csv new file mode 100644 index 00000000..d33c5366 --- /dev/null +++ b/test/data/importers/ingredients.csv @@ -0,0 +1,11 @@ +"PC","název","jednotka","kategorie","NDRUH","BALENI","CENA","TRVAN","VYBAVA" +1,"Kokos strouhaný","gr","Přípravky",,0.00,,1, +2,"Cibule","gr","Zelenina",,,,1, +3,"Sádlo škvařené","gr","Maso",,500.00,,, +4,"Květák","gr","Zelenina",,,,, +5,"Mrkev","gr","Zelenina",,,,, +6,"Petržel kořenová","gr","Zelenina",,,,, +7,"Mléko konzumní","ml","Mléko",,,,1, +8,"Mouka hladká","gr","Základní",,1000.00,,1, +9,"Houby sušené","gr","Koření",,,,1, +10,"Celer","gr","Zelenina",,,,, diff --git a/test/data/importers/ingredients_with_wrong_headers.csv b/test/data/importers/ingredients_with_wrong_headers.csv new file mode 100644 index 00000000..6bee740b --- /dev/null +++ b/test/data/importers/ingredients_with_wrong_headers.csv @@ -0,0 +1,16 @@ +"PC","nazev","jednotka","DRUH","NDRUH","BALENI","CENA","TRVAN","VYBAVA" +1,"Kokos strouhaný","gr","Přípravky",,0.00,,1, +2,"Cibule","gr","Zelenina",,,,1, +3,"Sádlo škvařené","gr","Maso",,500.00,,, +4,"Květák","gr","Zelenina",,,,, +5,"Mrkev","gr","Zelenina",,,,, +6,"Petržel kořenová","gr","Zelenina",,,,, +7,"Mléko konzumní","ml","Mléko",,,,1, +8,"Mouka hladká","gr","Základní",,1000.00,,1, +9,"Houby sušené","gr","Koření",,,,1, +10,"Celer","gr","Zelenina",,,,, +11,"Kapusta","gr","Zelenina",,,,, +12,"Pepř mletý","gr","Koření",,,,1, +13,"Vývar B 10101","ml","Receptura",,,,, +14,"Brambory","gr","Zelenina",,,,1, +15,"Sůl","gr","Základní",,1000.00,,1, diff --git a/test/models/importers/ingredients_importer_test.rb b/test/models/importers/ingredients_importer_test.rb new file mode 100644 index 00000000..dd0f925b --- /dev/null +++ b/test/models/importers/ingredients_importer_test.rb @@ -0,0 +1,44 @@ +require "test_helper" + +class Importers::IngredientsImporterTest < ActiveSupport::TestCase + test "raises error on non-csv file" do + exception = assert_raises Exception do + Importers::IngredientsImporter.new(file_path: "test/data/importers/ingredients.xlsx", initiator: @current_user).run + end + + assert_equal exception.message, "Importer can only work with csv files for now" + end + + test "raises error if data headers are not correct" do + exception = assert_raises NameError do + Importers::IngredientsImporter.new(file_path: "test/data/importers/ingredients_with_wrong_headers.csv", initiator: @current_user).run + end + + assert_equal exception.message, "Headers must include: název, jednotka, kategorie" + end + + test "creates ingredients with correct name" do + # TODO: prepare data in database (categories, measurements, common ingredients) + + Importers::IngredientsImporter.new(file_path: "test/data/importers/ingredients.csv", initiator: @current_user).run + + assert_equal Ingredient.all.count, 10 + end + + test "it doesn't create duplicate ingredients" do + Ingredient.create(name: "Mrkev", author: @current_user) + + Importers::IngredientsImporter.new(file_path: "test/data/importers/ingredients.csv", initiator: @current_user).run + + assert_equal Ingredient.all.count, 10 + end + + test "it assigns correct category and measurement" do + Measurement.create(name: "gram") + IngredientCategory.create(name: "Zelenina") + + Importers::IngredientsImporter.new(file_path: "test/data/importers/ingredients.csv", initiator: @current_user).run + + assert Ingredient.find_by(name: "Mrkev").category.name == "Zelenina" + end +end