From b3a20bc26e7031a035a8083f139a437354313a5a Mon Sep 17 00:00:00 2001 From: Kat <54268893+kosiakkatrina@users.noreply.github.com> Date: Fri, 21 Mar 2025 13:04:17 +0000 Subject: [PATCH] Allow passing a year to generating sales validations docs task --- lib/tasks/generate_sales_documentation.rake | 47 ++-- .../generate_sales_documentation_spec.rb | 202 +++++++++++++++++- 2 files changed, 232 insertions(+), 17 deletions(-) diff --git a/lib/tasks/generate_sales_documentation.rake b/lib/tasks/generate_sales_documentation.rake index c595c4f18..f5dd550fa 100644 --- a/lib/tasks/generate_sales_documentation.rake +++ b/lib/tasks/generate_sales_documentation.rake @@ -1,6 +1,12 @@ namespace :generate_sales_documentation do desc "Generate documentation for hard sales validations" - task describe_sales_validations: :environment do + task :describe_sales_validations, %i[year] => :environment do |_task, args| + form_year = args[:year]&.to_i + raise "Usage: rake generate_sales_documentation:describe_sales_validations['year']" if form_year.blank? + + form = FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(form_year, "sales")] + raise "No form found for given year" if form.blank? + client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"]) include Validations::Sales::SetupValidations include Validations::Sales::HouseholdValidations @@ -20,37 +26,50 @@ namespace :generate_sales_documentation do all_helper_methods = all_methods - all_validation_methods - DocumentationGenerator.new.describe_hard_validations(client, all_validation_methods, all_helper_methods, "sales") + DocumentationGenerator.new.describe_hard_validations(client, form, all_validation_methods, all_helper_methods, "sales") end desc "Generate documentation for soft sales validations" - task describe_soft_sales_validations: :environment do + task :describe_soft_sales_validations, %i[year] => :environment do |_task, args| include Validations::SoftValidations include Validations::Sales::SoftValidations + form_year = args[:year]&.to_i + raise "Usage: rake generate_sales_documentation:describe_soft_sales_validations['year']" if form_year.blank? + + form = FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(form_year, "sales")] + raise "No form found for given year" if form.blank? client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"]) all_helper_methods = Validations::SoftValidations.private_instance_methods + Validations::Sales::SoftValidations.private_instance_methods all_validation_methods = Validations::SoftValidations.instance_methods + Validations::Sales::SoftValidations.instance_methods - DocumentationGenerator.new.describe_soft_validations(client, all_validation_methods, all_helper_methods, "sales") + DocumentationGenerator.new.describe_soft_validations(client, form, all_validation_methods, all_helper_methods, "sales") end desc "Generate documentation for hard bu sales validations" - task describe_bu_sales_validations: :environment do + task :describe_bu_sales_validations, %i[year] => :environment do |_task, args| + form_year = args[:year]&.to_i + raise "Usage: rake generate_sales_documentation:describe_bu_sales_validations['year']" if form_year.blank? + + form = FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(form_year, "sales")] + raise "No form found for given year" if form.blank? + + row_parser_class = "BulkUpload::Sales::Year#{form_year}::RowParser".constantize client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"]) - [[FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(2023, "sales")], BulkUpload::Sales::Year2023::RowParser], - [FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(2024, "sales")], BulkUpload::Sales::Year2024::RowParser]].each do |form, row_parser_class| - all_validation_methods = row_parser_class.private_instance_methods.select { |method| method.starts_with?("validate_") } - all_helper_methods = row_parser_class.private_instance_methods(false) + row_parser_class.instance_methods(false) - all_validation_methods - field_mapping_for_errors = row_parser_class.new.send("field_mapping_for_errors") + all_validation_methods = row_parser_class.private_instance_methods.select { |method| method.starts_with?("validate_") } + all_helper_methods = row_parser_class.private_instance_methods(false) + row_parser_class.instance_methods(false) - all_validation_methods + field_mapping_for_errors = row_parser_class.new.send("field_mapping_for_errors") - DocumentationGenerator.new.describe_bu_validations(client, form, row_parser_class, all_validation_methods, all_helper_methods, field_mapping_for_errors, "sales") - end + DocumentationGenerator.new.describe_bu_validations(client, form, row_parser_class, all_validation_methods, all_helper_methods, field_mapping_for_errors, "sales") end desc "Generate documentation for sales numeric validations" - task add_numeric_sales_validations: :environment do - form = FormHandler.instance.forms["current_sales"] + task :add_numeric_sales_validations, %i[year] => :environment do |_task, args| + form_year = args[:year]&.to_i + raise "Usage: rake generate_sales_documentation:add_numeric_sales_validations['year']" if form_year.blank? + + form = FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(form_year, "sales")] + raise "No form found for given year" if form.blank? form.numeric_questions.each do |question| next unless question.min || question.max diff --git a/spec/lib/tasks/generate_sales_documentation_spec.rb b/spec/lib/tasks/generate_sales_documentation_spec.rb index 4626f1a42..2766b921d 100644 --- a/spec/lib/tasks/generate_sales_documentation_spec.rb +++ b/spec/lib/tasks/generate_sales_documentation_spec.rb @@ -6,14 +6,24 @@ RSpec.describe "generate_sales_documentation" do subject(:task) { Rake::Task["generate_sales_documentation:add_numeric_sales_validations"] } before do + Timecop.freeze(Time.zone.local(2025, 1, 1)) + Singleton.__init__(FormHandler) + allow(FormHandler.instance).to receive(:forms).and_return({ "current_sales" => FormHandler.instance.forms["current_sales"], "previous_sales" => "2023_form", "next_sales" => "2025_form" }) Rake.application.rake_require("tasks/generate_sales_documentation") Rake::Task.define_task(:environment) task.reenable end + after do + Timecop.return + Singleton.__init__(FormHandler) + end + context "when the rake task is run" do it "creates new validation documentation records" do - expect { task.invoke }.to change(LogValidation, :count) + allow(FormHandler.instance.forms).to receive(:[]).with("current_sales").and_return(FormHandler.instance.forms["current_sales"]) + + expect { task.invoke(2024) }.to change(LogValidation, :count) expect(LogValidation.where(validation_name: "minimum").count).to be_positive expect(LogValidation.where(validation_name: "range").count).to be_positive any_min_validation = LogValidation.where(validation_name: "minimum").first @@ -30,8 +40,194 @@ RSpec.describe "generate_sales_documentation" do end it "skips if the validation already exists in the database" do - task.invoke - expect { task.invoke }.not_to change(LogValidation, :count) + task.invoke(2024) + expect { task.invoke(2024) }.not_to change(LogValidation, :count) + end + + context "with no year given" do + it "raises an error" do + expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake generate_sales_documentation:add_numeric_sales_validations['year']") + end + end + + context "with an invalid year given" do + it "raises an error" do + expect { task.invoke("abc") }.to raise_error(RuntimeError, "No form found for given year") + end + end + + context "with a year for non existing form" do + it "raises an error" do + expect { task.invoke("2022") }.to raise_error(RuntimeError, "No form found for given year") + end + end + end + end + + describe ":describe_sales_validations", type: :task do + subject(:task) { Rake::Task["generate_sales_documentation:describe_sales_validations"] } + + let(:documentation_generator) { instance_double(DocumentationGenerator, describe_bu_validations: nil) } + let(:client) { instance_double(OpenAI::Client) } + + before do + allow(OpenAI::Client).to receive(:new).and_return(client) + allow(DocumentationGenerator).to receive(:new).and_return(documentation_generator) + Timecop.freeze(Time.zone.local(2025, 1, 1)) + Singleton.__init__(FormHandler) + allow(FormHandler.instance).to receive(:forms).and_return({ "current_sales" => "2024_form", "previous_sales" => "2023_form", "next_sales" => "2025_form" }) + Rake.application.rake_require("tasks/generate_sales_documentation") + Rake::Task.define_task(:environment) + task.reenable + end + + after do + Timecop.return + Singleton.__init__(FormHandler) + end + + context "with a year given" do + it "gets the correct form for next year" do + allow(FormHandler.instance.forms).to receive(:[]).with("next_sales").and_return("2025_form") + expect(documentation_generator).to receive(:describe_hard_validations).with(client, "2025_form", anything, anything, "sales") + + task.invoke("2025") + end + + it "gets the correct form for current year" do + allow(FormHandler.instance.forms).to receive(:[]).with("current_sales").and_return("2024_form") + expect(documentation_generator).to receive(:describe_hard_validations).with(client, "2024_form", anything, anything, "sales") + task.invoke("2024") + end + end + + context "with no year given" do + it "raises an error" do + expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake generate_sales_documentation:describe_sales_validations['year']") + end + end + + context "with an invalid year given" do + it "raises an error" do + expect { task.invoke("abc") }.to raise_error(RuntimeError, "No form found for given year") + end + end + + context "with a year for non existing form" do + it "raises an error" do + expect { task.invoke("2022") }.to raise_error(RuntimeError, "No form found for given year") + end + end + end + + describe ":describe_bu_sales_validations", type: :task do + subject(:task) { Rake::Task["generate_sales_documentation:describe_bu_sales_validations"] } + + let(:documentation_generator) { instance_double(DocumentationGenerator, describe_bu_validations: nil) } + let(:client) { instance_double(OpenAI::Client) } + + before do + allow(OpenAI::Client).to receive(:new).and_return(client) + allow(DocumentationGenerator).to receive(:new).and_return(documentation_generator) + Timecop.freeze(Time.zone.local(2025, 1, 1)) + Singleton.__init__(FormHandler) + allow(FormHandler.instance).to receive(:forms).and_return({ "current_sales" => "2024_form", "previous_sales" => "2023_form", "next_sales" => "2025_form" }) + Rake.application.rake_require("tasks/generate_sales_documentation") + Rake::Task.define_task(:environment) + task.reenable + end + + after do + Timecop.return + Singleton.__init__(FormHandler) + end + + context "with a year given" do + it "gets the correct form for next year" do + allow(FormHandler.instance.forms).to receive(:[]).with("next_sales").and_return("2025_form") + expect(documentation_generator).to receive(:describe_bu_validations).with(client, "2025_form", anything, anything, anything, anything, "sales") + + task.invoke("2025") + end + + it "gets the correct form for current year" do + allow(FormHandler.instance.forms).to receive(:[]).with("current_sales").and_return("2024_form") + expect(documentation_generator).to receive(:describe_bu_validations).with(client, "2024_form", anything, anything, anything, anything, "sales") + task.invoke("2024") + end + end + + context "with no year given" do + it "raises an error" do + expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake generate_sales_documentation:describe_bu_sales_validations['year']") + end + end + + context "with an invalid year given" do + it "raises an error" do + expect { task.invoke("abc") }.to raise_error(RuntimeError, "No form found for given year") + end + end + + context "with a year for non existing form" do + it "raises an error" do + expect { task.invoke("2022") }.to raise_error(RuntimeError, "No form found for given year") + end + end + end + + describe ":describe_soft_sales_validations", type: :task do + subject(:task) { Rake::Task["generate_sales_documentation:describe_soft_sales_validations"] } + + let(:documentation_generator) { instance_double(DocumentationGenerator, describe_bu_validations: nil) } + let(:client) { instance_double(OpenAI::Client) } + + before do + allow(OpenAI::Client).to receive(:new).and_return(client) + allow(DocumentationGenerator).to receive(:new).and_return(documentation_generator) + Timecop.freeze(Time.zone.local(2025, 1, 1)) + Singleton.__init__(FormHandler) + allow(FormHandler.instance).to receive(:forms).and_return({ "current_sales" => "2024_form", "previous_sales" => "2023_form", "next_sales" => "2025_form" }) + Rake.application.rake_require("tasks/generate_sales_documentation") + Rake::Task.define_task(:environment) + task.reenable + end + + after do + Timecop.return + Singleton.__init__(FormHandler) + end + + context "with a year given" do + it "gets the correct form for next year" do + allow(FormHandler.instance.forms).to receive(:[]).with("next_sales").and_return("2025_form") + expect(documentation_generator).to receive(:describe_soft_validations).with(client, "2025_form", anything, anything, "sales") + + task.invoke("2025") + end + + it "gets the correct form for current year" do + allow(FormHandler.instance.forms).to receive(:[]).with("current_sales").and_return("2024_form") + expect(documentation_generator).to receive(:describe_soft_validations).with(client, "2024_form", anything, anything, "sales") + task.invoke("2024") + end + end + + context "with no year given" do + it "raises an error" do + expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake generate_sales_documentation:describe_soft_sales_validations['year']") + end + end + + context "with an invalid year given" do + it "raises an error" do + expect { task.invoke("abc") }.to raise_error(RuntimeError, "No form found for given year") + end + end + + context "with a year for non existing form" do + it "raises an error" do + expect { task.invoke("2022") }.to raise_error(RuntimeError, "No form found for given year") end end end