diff --git a/app/controllers/admin/accounts_and_billing_settings_controller.rb b/app/controllers/admin/accounts_and_billing_settings_controller.rb index 9e22fb48b1..edb9a21882 100644 --- a/app/controllers/admin/accounts_and_billing_settings_controller.rb +++ b/app/controllers/admin/accounts_and_billing_settings_controller.rb @@ -1,32 +1,28 @@ -require 'open_food_network/accounts_and_billing_settings' +require 'open_food_network/accounts_and_billing_settings_validator' class Admin::AccountsAndBillingSettingsController < Spree::Admin::BaseController - before_filter :load_distributors, only: [:edit, :update] - - def edit - @settings = OpenFoodNetwork::AccountsAndBillingSettings.new({ - accounts_distributor_id: Spree::Config[:accounts_distributor_id], - default_accounts_payment_method_id: Spree::Config[:default_accounts_payment_method_id], - default_accounts_shipping_method_id: Spree::Config[:default_accounts_shipping_method_id], - collect_billing_information: Spree::Config[:collect_billing_information], - create_invoices_for_enterprise_users: Spree::Config[:create_invoices_for_enterprise_users] - }) - end + before_filter :load_distributors, only: [:edit, :update, :start_job] + before_filter :load_jobs, only: [:edit, :update, :start_job] + before_filter :load_settings, only: [:edit, :update, :start_job] + before_filter :require_valid_settings, only: [:update, :start_job] + before_filter :require_known_job, only: [:start_job] def update - @settings = OpenFoodNetwork::AccountsAndBillingSettings.new(params[:settings], params[:button]) - if @settings.valid? - Spree::Config.set(params[:settings]) + Spree::Config.set(params[:settings]) + flash[:success] = t(:successfully_updated, :resource => t(:billing_and_account_settings)) + redirect_to_edit + end - if params[:button] == "update_and_run_job" - Delayed::Job.enqueue UpdateBillablePeriods.new - end - - flash[:success] = t(:successfully_updated, :resource => t(:billing_and_account_settings)) - redirect_to main_app.edit_admin_accounts_and_billing_settings_path + def start_job + if @billing_period_job || @user_invoice_job + flash[:error] = "A task is already running, please wait until it has finished" else - render :edit + new_job = "update_#{params[:job_name]}".camelize.constantize.new + Delayed::Job.enqueue new_job + flash[:success] = "Task Queued" end + + redirect_to_edit end def show_methods @@ -38,7 +34,38 @@ class Admin::AccountsAndBillingSettingsController < Spree::Admin::BaseController private + def redirect_to_edit + redirect_to main_app.edit_admin_accounts_and_billing_settings_path + end + + def require_valid_settings + render :edit unless @settings.valid? + end + + def require_known_job + known_jobs = ['user_invoices', 'billable_periods'] + unless known_jobs.include?(params[:job_name]) + flash[:error] = "Unknown Task: #{params[:job_name].to_s}" + redirect_to_edit + end + end + + def load_settings + @settings = OpenFoodNetwork::AccountsAndBillingSettingsValidator.new(params[:settings] || { + accounts_distributor_id: Spree::Config[:accounts_distributor_id], + default_accounts_payment_method_id: Spree::Config[:default_accounts_payment_method_id], + default_accounts_shipping_method_id: Spree::Config[:default_accounts_shipping_method_id] + # collect_billing_information: Spree::Config[:collect_billing_information], + # create_invoices_for_enterprise_users: Spree::Config[:create_invoices_for_enterprise_users] + }) + end + def load_distributors @distributors = Enterprise.is_distributor.select([:id, :name]) end + + def load_jobs + @billing_period_job = Delayed::Job.where("handler LIKE (?)", "%Struct::UpdateBillablePeriods%").last + @user_invoice_job = Delayed::Job.where("handler LIKE (?)", "%Struct::UpdateUserInvoices%").last + end end diff --git a/app/views/admin/accounts_and_billing_settings/edit.html.haml b/app/views/admin/accounts_and_billing_settings/edit.html.haml index 71c21623e0..3182bb09a2 100644 --- a/app/views/admin/accounts_and_billing_settings/edit.html.haml +++ b/app/views/admin/accounts_and_billing_settings/edit.html.haml @@ -5,40 +5,68 @@ = render 'spree/shared/error_messages', target: @settings -%div{ ng: { app: 'admin.accounts_and_billing_settings' } } - = form_for @settings, as: :settings, url: main_app.admin_accounts_and_billing_settings_path, :method => :put do |f| - .row - .twelve.columns.alpha.omega +.row{ ng: { app: 'admin.accounts_and_billing_settings' } } + .twelve.columns.alpha.omega + = form_for @settings, as: :settings, url: main_app.admin_accounts_and_billing_settings_path, :method => :put do |f| + %fieldset.no-border-bottom + %legend Settings .field = f.label :accounts_distributor_id, t(:accounts_administration_distributor) = f.collection_select(:accounts_distributor_id, @distributors, :id, :name, { include_blank: true }, { class: "select2 fullwidth", 'watch-value-as' => "enterprise_id"}) - = f.hidden_field :default_accounts_payment_method_id, value: '' - = f.hidden_field :default_accounts_shipping_method_id, value: '' - %div{ 'method-settings-for' => 'enterprise_id' } + = f.hidden_field :default_accounts_payment_method_id, value: '' + = f.hidden_field :default_accounts_shipping_method_id, value: '' + %div{ 'method-settings-for' => 'enterprise_id' } - -# .row - -# .six.columns.alpha - -# %fieldset.no-border-bottom - -# %legend Billing Information - -# .field - -# = f.hidden_field :collect_billing_information, value: '0' - -# = f.check_box :collect_billing_information, value: '1' - -# = f.label :collect_billing_information, t(:collect_billing_information) - -# .field - -# = button t(:collect_now), 'icon-forward' + .form-buttons{"data-hook" => "buttons"} + = button t(:update), 'icon-refresh', value: "update" - -# .six.columns.omega - -# %fieldset.no-border-bottom - -# %legend User Invoices - -# .field - -# = f.hidden_field :create_invoices_for_enterprise_users, value: '0' - -# = f.check_box :create_invoices_for_enterprise_users, value: '1' - -# = f.label :create_invoices_for_enterprise_users, t(:create_invoices_for_enterprise_users) - -# .field - -# = button t(:create_now), 'icon-forward' +.row + .six.columns.alpha + %fieldset.no-border-bottom + %legend Billing Information - .form-buttons{"data-hook" => "buttons"} - = button t(:update), 'icon-refresh', value: "update" - or - = button t(:update_and_create_invoices_now), 'icon-undo', value: 'update_and_run_job' + %p + Use this button to calculate the billable total for the month to date for each enterprise in the system. Do this before generating invoices on the right. + + %br + + .form-buttons{"data-hook" => "buttons"} + = link_to_with_icon "icon-bar-chart", "Calculate Totals Now", main_app.start_job_admin_accounts_and_billing_settings_path(job_name: "billable_periods"), { class: 'button', disabled: @billing_period_job.present?} + + + - if @billing_period_job + %p.text-center + - if @billing_period_job.run_at < Time.now + %strong In Progress + %br + Started at: + - else + %strong Queued + %br + Scheduled for: + = @billing_period_job.run_at + + .six.columns.alpha + %fieldset.no-border-bottom + %legend User Invoices + + %p + Use this button to update invoices for the month to date for each enterprise user in the system. Do this after calculating totals on the left. + + %br + + .form-buttons{"data-hook" => "buttons"} + = link_to_with_icon "icon-undo", "Update Invoices Now", main_app.start_job_admin_accounts_and_billing_settings_path(job_name: "user_invoices"), class: 'button', disabled: @user_invoice_job.present? + + - if @user_invoice_job + %p.text-center + - if @user_invoice_job.run_at < Time.now + %strong In Progress + %br + Started at: + - else + %strong Queued + %br + Scheduled for: + = @user_invoice_job.run_at diff --git a/lib/open_food_network/accounts_and_billing_settings_validator.rb b/lib/open_food_network/accounts_and_billing_settings_validator.rb index 2bd5883886..a92a553235 100644 --- a/lib/open_food_network/accounts_and_billing_settings_validator.rb +++ b/lib/open_food_network/accounts_and_billing_settings_validator.rb @@ -2,14 +2,15 @@ # when they are submitted to the AccountsAndBillingSettingsController module OpenFoodNetwork - class AccountsAndBillingSettings + class AccountsAndBillingSettingsValidator include ActiveModel::Validations attr_accessor :accounts_distributor_id, :default_accounts_payment_method_id, :default_accounts_shipping_method_id # attr_accessor :collect_billing_information, :create_invoices_for_enterprise_users - validate :ensure_accounts_distributor_set, if: lambda { @button == 'update_and_run_job' } - validate :ensure_default_methods_set, if: lambda { @button == 'update_and_run_job' } + validate :ensure_accounts_distributor_set + validate :ensure_default_payment_method_set + validate :ensure_default_shipping_method_set # validate :ensure_billing_info_collected, unless: lambda { create_invoices_for_enterprise_users == '0' } def initialize(attr, button=nil) @@ -23,12 +24,14 @@ module OpenFoodNetwork end end - def ensure_default_methods_set + def ensure_default_payment_method_set unless Enterprise.find_by_id(accounts_distributor_id) && Enterprise.find_by_id(accounts_distributor_id).payment_methods.find_by_id(default_accounts_payment_method_id) errors.add(:default_payment_method, "must be set if you wish to create invoices for enterprise users.") end + end + def ensure_default_shipping_method_set unless Enterprise.find_by_id(accounts_distributor_id) && Enterprise.find_by_id(accounts_distributor_id).shipping_methods.find_by_id(default_accounts_shipping_method_id) errors.add(:default_shipping_method, "must be set if you wish to create invoices for enterprise users.") diff --git a/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb b/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb index c0af5fc7ea..c9f093e151 100644 --- a/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb +++ b/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb @@ -40,8 +40,8 @@ describe Admin::AccountsAndBillingSettingsController, type: :controller do expect(settings.accounts_distributor_id).to eq accounts_distributor.id expect(settings.default_accounts_payment_method_id).to eq pm1.id expect(settings.default_accounts_shipping_method_id).to eq sm1.id - expect(settings.collect_billing_information).to eq true - expect(settings.create_invoices_for_enterprise_users).to eq false + # expect(settings.collect_billing_information).to eq true + # expect(settings.create_invoices_for_enterprise_users).to eq false end end end @@ -60,89 +60,150 @@ describe Admin::AccountsAndBillingSettingsController, type: :controller do before {allow(controller).to receive(:spree_current_user) { admin } } let(:params) { { settings: { } } } - context "when we are not creating user invoices" do - before { params[:button] = 'update' } - - context "and settings have no values" do - before do - params[:settings][:accounts_distributor_id] = '' - params[:settings][:default_accounts_payment_method_id] = '0' - params[:settings][:default_accounts_shipping_method_id] = '0' - # params[:settings][:collect_billing_information] = '0' - spree_get :update, params - end - - it "allows them to be empty/false" do - expect(assigns(:settings).errors.count).to be 0 - expect(Spree::Config.accounts_distributor_id).to eq 0 - expect(Spree::Config.default_accounts_payment_method_id).to eq 0 - expect(Spree::Config.default_accounts_shipping_method_id).to eq 0 - # expect(Spree::Config.collect_billing_information).to be false - # expect(Spree::Config.create_invoices_for_enterprise_users).to be false - end + context "when settings have no values" do + before do + params[:settings][:accounts_distributor_id] = '' + params[:settings][:default_accounts_payment_method_id] = '0' + params[:settings][:default_accounts_shipping_method_id] = '0' + # params[:settings][:collect_billing_information] = '0' + spree_get :update, params end - context "and other settings are set" do - before do - params[:settings][:accounts_distributor_id] = new_distributor.id - params[:settings][:default_accounts_payment_method_id] = pm2.id - params[:settings][:default_accounts_shipping_method_id] = sm2.id - # params[:settings][:collect_billing_information] = '1' - spree_get :update, params - end - - it "sets global config to the specified values" do - expect(Spree::Config.accounts_distributor_id).to eq new_distributor.id - expect(Spree::Config.default_accounts_payment_method_id).to eq pm2.id - expect(Spree::Config.default_accounts_shipping_method_id).to eq sm2.id - # expect(Spree::Config.collect_billing_information).to be true - # expect(Spree::Config.create_invoices_for_enterprise_users).to be false - end + it "does not allow them to be empty/false" do + expect(response).to render_template :edit + expect(assigns(:settings).errors.count).to be 3 + expect(Spree::Config.accounts_distributor_id).to eq accounts_distributor.id + expect(Spree::Config.default_accounts_payment_method_id).to eq pm1.id + expect(Spree::Config.default_accounts_shipping_method_id).to eq sm1.id + # expect(Spree::Config.collect_billing_information).to be true + # expect(Spree::Config.create_invoices_for_enterprise_users).to be false end end - context "when we are creating user invoices" do - before { params[:button] = 'update_and_run_job' } + context "when settings have values" do + before do + params[:settings][:accounts_distributor_id] = new_distributor.id + params[:settings][:default_accounts_payment_method_id] = pm2.id + params[:settings][:default_accounts_shipping_method_id] = sm2.id + # params[:settings][:collect_billing_information] = '1' + end - context "and settings have no values" do + it "sets global config to the specified values" do + spree_get :update, params + expect(Spree::Config.accounts_distributor_id).to eq new_distributor.id + expect(Spree::Config.default_accounts_payment_method_id).to eq pm2.id + expect(Spree::Config.default_accounts_shipping_method_id).to eq sm2.id + # expect(Spree::Config.collect_billing_information).to be true + # expect(Spree::Config.create_invoices_for_enterprise_users).to be false + end + end + end + end + + describe "start_job" do + context "as an enterprise user" do + before do + allow(controller).to receive(:spree_current_user) { user } + spree_get :show_methods, enterprise_id: accounts_distributor.id + end + + it "does not allow access" do + expect(response).to redirect_to spree.unauthorized_path + end + end + + context "as super admin" do + before do + allow(controller).to receive(:spree_current_user) { admin } + end + + context "when settings are not valid" do + before do + Spree::Config.set({ accounts_distributor_id: "" }) + Spree::Config.set({ default_accounts_payment_method_id: "" }) + Spree::Config.set({ default_accounts_shipping_method_id: "" }) + spree_get :start_job, job_name: "" + end + + it "returns immediately and renders :edit" do + expect(assigns(:settings).errors.count).to eq 3 + expect(response).to render_template :edit + end + end + + context "when settings are valid" do + before do + Spree::Config.set({ accounts_distributor_id: accounts_distributor.id }) + Spree::Config.set({ default_accounts_payment_method_id: pm1.id }) + Spree::Config.set({ default_accounts_shipping_method_id: sm1.id }) + end + + context "and job_name is not billable_periods or user_invoices" do before do - params[:settings][:accounts_distributor_id] = '' - params[:settings][:default_accounts_payment_method_id] = '0' - params[:settings][:default_accounts_shipping_method_id] = '0' - # params[:settings][:collect_billing_information] = '0' - spree_get :update, params + spree_get :start_job, job_name: "" end - it "does not allow them to be empty/false" do - expect(response).to render_template :edit - expect(assigns(:settings).errors.count).to be 3 - expect(Spree::Config.accounts_distributor_id).to eq accounts_distributor.id - expect(Spree::Config.default_accounts_payment_method_id).to eq pm1.id - expect(Spree::Config.default_accounts_shipping_method_id).to eq sm1.id - # expect(Spree::Config.collect_billing_information).to be true - # expect(Spree::Config.create_invoices_for_enterprise_users).to be false + it "returns immediately with an error" do + expect(flash[:error]).to eq "Unknown Task: " + expect(response).to redirect_to edit_admin_accounts_and_billing_settings_path end end - context "and other settings are set" do - before do - params[:settings][:accounts_distributor_id] = new_distributor.id - params[:settings][:default_accounts_payment_method_id] = pm2.id - params[:settings][:default_accounts_shipping_method_id] = sm2.id - # params[:settings][:collect_billing_information] = '1' + context "and job_name is billable_periods" do + let!(:params) { { job_name: "billable_periods" } } + + context "and no jobs are currently running" do + before do + allow(controller).to receive(:load_jobs) + end + + it "runs the job" do + expect{spree_get :start_job, params}.to enqueue_job UpdateBillablePeriods + expect(flash[:success]).to eq "Task Queued" + expect(response).to redirect_to edit_admin_accounts_and_billing_settings_path + end end - it "sets global config to the specified values" do - spree_get :update, params - expect(Spree::Config.accounts_distributor_id).to eq new_distributor.id - expect(Spree::Config.default_accounts_payment_method_id).to eq pm2.id - expect(Spree::Config.default_accounts_shipping_method_id).to eq sm2.id - # expect(Spree::Config.collect_billing_information).to be true - # expect(Spree::Config.create_invoices_for_enterprise_users).to be false + context "and there are jobs currently running" do + before do + allow(controller).to receive(:load_jobs) + controller.instance_variable_set("@billing_period_job", double(:billing_period_job)) + end + + it "does not run the job" do + expect{spree_get :start_job, params}.to_not enqueue_job UpdateBillablePeriods + expect(flash[:error]).to eq "A task is already running, please wait until it has finished" + expect(response).to redirect_to edit_admin_accounts_and_billing_settings_path + end + end + end + + context "and job_name is user_invoices" do + let!(:params) { { job_name: "user_invoices" } } + + context "and no jobs are currently running" do + before do + allow(controller).to receive(:load_jobs) + end + + it "runs the job" do + expect{spree_get :start_job, params}.to enqueue_job UpdateUserInvoices + expect(flash[:success]).to eq "Task Queued" + expect(response).to redirect_to edit_admin_accounts_and_billing_settings_path + end end - it "runs the job" do - expect{spree_get :update, params}.to enqueue_job UpdateBillablePeriods + context "and there are jobs currently running" do + before do + allow(controller).to receive(:load_jobs) + controller.instance_variable_set("@user_invoice_job", double(:user_invoice_job)) + end + + it "does not run the job" do + expect{spree_get :start_job, params}.to_not enqueue_job UpdateUserInvoices + expect(flash[:error]).to eq "A task is already running, please wait until it has finished" + expect(response).to redirect_to edit_admin_accounts_and_billing_settings_path + end end end end diff --git a/spec/features/admin/accounts_and_billing_settings_spec.rb b/spec/features/admin/accounts_and_billing_settings_spec.rb index b19b13c155..31830507b6 100644 --- a/spec/features/admin/accounts_and_billing_settings_spec.rb +++ b/spec/features/admin/accounts_and_billing_settings_spec.rb @@ -15,34 +15,45 @@ feature 'Account and Billing Settings' do accounts_distributor_id: 0, default_accounts_payment_method_id: 0, default_accounts_shipping_method_id: 0, - collect_billing_information: false, - create_invoices_for_enterprise_users: false + # collect_billing_information: false, + # create_invoices_for_enterprise_users: false }) end before do quick_login_as_admin - visit spree.admin_path end context "as an admin user", js: true do - it "attributes can be changed" do + it "loads the page" do + visit spree.admin_path click_link "Configuration" click_link "Accounts & Billing" + expect(page).to have_select2 "settings_accounts_distributor_id" + select2_select accounts_distributor.name, from: "settings_accounts_distributor_id" + expect(page).to have_select "settings_default_accounts_payment_method_id" + expect(page).to have_select "settings_default_accounts_shipping_method_id" + expect(page).to have_link "Calculate Totals Now", href: start_job_admin_accounts_and_billing_settings_path(job_name: 'billable_periods') + expect(page).to have_link "Update Invoices Now", href: start_job_admin_accounts_and_billing_settings_path(job_name: 'user_invoices') + end + + it "attributes can be changed", js: true do + visit edit_admin_accounts_and_billing_settings_path + select2_select accounts_distributor.name, from: "settings_accounts_distributor_id" select pm1.name, from: "settings_default_accounts_payment_method_id" select sm1.name, from: "settings_default_accounts_shipping_method_id" - check "settings_collect_billing_information" - check "settings_create_invoices_for_enterprise_users" + # check "settings_collect_billing_information" + # check "settings_create_invoices_for_enterprise_users" click_button "Update" expect(Spree::Config.accounts_distributor_id).to eq accounts_distributor.id expect(Spree::Config.default_accounts_payment_method_id).to eq pm1.id expect(Spree::Config.default_accounts_shipping_method_id).to eq sm1.id - expect(Spree::Config.collect_billing_information).to be true - expect(Spree::Config.create_invoices_for_enterprise_users).to be true + # expect(Spree::Config.collect_billing_information).to be true + # expect(Spree::Config.create_invoices_for_enterprise_users).to be true end end end