diff --git a/app/controllers/admin/accounts_and_billing_settings_controller.rb b/app/controllers/admin/accounts_and_billing_settings_controller.rb new file mode 100644 index 0000000000..ff7e458d39 --- /dev/null +++ b/app/controllers/admin/accounts_and_billing_settings_controller.rb @@ -0,0 +1,30 @@ +require 'open_food_network/accounts_and_billing_settings' + +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], + collect_billing_information: Spree::Config[:collect_billing_information], + create_invoices_for_enterprise_users: Spree::Config[:create_invoices_for_enterprise_users] + }) + end + + def update + @settings = OpenFoodNetwork::AccountsAndBillingSettings.new(params[:settings]) + if @settings.valid? + Spree::Config.set(params[:settings]) + flash[:success] = t(:successfully_updated, :resource => t(:billing_and_account_settings)) + redirect_to main_app.edit_admin_accounts_and_billing_settings_path + else + render :edit + end + end + + private + + def load_distributors + @distributors = Enterprise.is_distributor.select([:id, :name]) + end +end diff --git a/app/models/spree/app_configuration_decorator.rb b/app/models/spree/app_configuration_decorator.rb index 5ad4a9a1c5..48165209a1 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/app/models/spree/app_configuration_decorator.rb @@ -7,4 +7,9 @@ Spree::AppConfiguration.class_eval do # Tax Preferences preference :products_require_tax_category, :boolean, default: false preference :shipping_tax_rate, :decimal, default: 0 + + # Accounts & Billing Preferences + preference :accounts_distributor_id, :integer, default: nil + preference :collect_billing_information, :boolean, default: false + preference :create_invoices_for_enterprise_users, :boolean, default: false end diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface new file mode 100644 index 0000000000..14f4925206 --- /dev/null +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface @@ -0,0 +1,4 @@ +// insert_bottom "[data-hook='admin_configurations_sidebar_menu']" + +%li + = link_to 'Accounts & Billing', main_app.edit_admin_accounts_and_billing_settings_path diff --git a/app/views/admin/accounts_and_billing_settings/edit.html.haml b/app/views/admin/accounts_and_billing_settings/edit.html.haml new file mode 100644 index 0000000000..2cfcbed8a0 --- /dev/null +++ b/app/views/admin/accounts_and_billing_settings/edit.html.haml @@ -0,0 +1,22 @@ += render :partial => 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t(:accounts_and_billing_settings) + += render 'spree/shared/error_messages', target: @settings + += form_for @settings, as: :settings, url: main_app.admin_accounts_and_billing_settings_path, :method => :put do |f| + .field + = f.label :accounts_administration_distributor, t(:accounts_administration_distributor) + = f.collection_select(:accounts_distributor_id, @distributors, :id, :name, { include_blank: true }, { class: "select2 fullwidth" }) + .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 + + = 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) + .form-buttons{"data-hook" => "buttons"} + = button t(:update), 'icon-refresh' diff --git a/config/routes.rb b/config/routes.rb index b5cd4612df..e25eec6555 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -102,7 +102,10 @@ Openfoodnetwork::Application.routes.draw do resources :customers, only: [:index, :update] + resource :content + + resource :accounts_and_billing_settings, only: [:edit, :update] end namespace :api do diff --git a/lib/open_food_network/accounts_and_billing_settings.rb b/lib/open_food_network/accounts_and_billing_settings.rb new file mode 100644 index 0000000000..d95ceb5b9f --- /dev/null +++ b/lib/open_food_network/accounts_and_billing_settings.rb @@ -0,0 +1,27 @@ +# This class is a lightweight model used to validate preferences for accounts and billing settings +# when they are submitted to the AccountsAndBillingSettingsController + +module OpenFoodNetwork + class AccountsAndBillingSettings + include ActiveModel::Validations + attr_accessor :accounts_distributor_id, :collect_billing_information, :create_invoices_for_enterprise_users + validate :ensure_accounts_distributor_set, unless: lambda { create_invoices_for_enterprise_users == '0' } + validate :ensure_billing_info_collected, unless: lambda { create_invoices_for_enterprise_users == '0' } + + def initialize(attr) + attr.each { |k,v| instance_variable_set("@#{k}", v) } + end + + def ensure_accounts_distributor_set + if Enterprise.find_by_id(accounts_distributor_id).blank? + errors.add(:accounts_distributor, "must be set if you wish to create invoices for enterprise users.") + end + end + + def ensure_billing_info_collected + unless collect_billing_information == '1' + errors.add(:billing_information, "must be collected if you wish to create invoices for enterprise users.") + end + end + end +end diff --git a/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb b/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb new file mode 100644 index 0000000000..02e4bd4dfa --- /dev/null +++ b/spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb @@ -0,0 +1,122 @@ +require 'spec_helper' + +describe Admin::AccountsAndBillingSettingsController, type: :controller do + let!(:accounts_distributor) { create(:distributor_enterprise) } + let!(:new_distributor) { create(:distributor_enterprise) } + let(:user) { create(:user) } + let(:admin) { create(:admin_user) } + + before do + Spree::Config.set({ + accounts_distributor_id: accounts_distributor.id, + collect_billing_information: true, + create_invoices_for_enterprise_users: false + }) + end + + describe "edit" do + context "as an enterprise user" do + before { allow(controller).to receive(:spree_current_user) { user } } + + it "does not allow access" do + spree_get :edit + expect(response).to redirect_to spree.unauthorized_path + end + end + + context "as super admin" do + before { allow(controller).to receive(:spree_current_user) { admin } } + + it "loads relevant global settings into a locally dummy class" do + spree_get :edit + settings = assigns(:settings) + + expect(settings.accounts_distributor_id).to eq accounts_distributor.id + expect(settings.collect_billing_information).to eq true + expect(settings.create_invoices_for_enterprise_users).to eq false + end + end + end + + describe "update" do + context "as an enterprise user" do + before { allow(controller).to receive(:spree_current_user) { user } } + + it "does not allow access" do + spree_get :update + expect(response).to redirect_to spree.unauthorized_path + end + end + + context "as super admin" do + before {allow(controller).to receive(:spree_current_user) { admin } } + let(:params) { { settings: { } } } + + context "when create_invoices_for_enterprise_users is false" do + before { params[:settings][:create_invoices_for_enterprise_users] = '0' } + + context "and account_distributor_id and collect_billing_information are not set" do + before do + params[:settings][:accounts_distributor_id] = '' + params[:settings][:collect_billing_information] = '0' + spree_get :update, params + end + + it "allows them to be empty/false" do + expect(Spree::Config.accounts_distributor_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 + end + + context "and account_distributor_id and collect_billing_information are set" do + before do + params[:settings][:accounts_distributor_id] = new_distributor.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.collect_billing_information).to be true + expect(Spree::Config.create_invoices_for_enterprise_users).to be false + end + end + end + + context "when create_invoices_for_enterprise_users is true" do + before { params[:settings][:create_invoices_for_enterprise_users] = '1' } + + context "and account_distributor_id and collect_billing_information are not set" do + before do + params[:settings][:accounts_distributor_id] = '' + params[:settings][:collect_billing_information] = '0' + spree_get :update, params + end + + it "does not allow them to be empty/false" do + expect(response).to render_template :edit + expect(assigns(:settings).errors.count).to be 2 + expect(Spree::Config.accounts_distributor_id).to eq accounts_distributor.id + expect(Spree::Config.collect_billing_information).to be true + expect(Spree::Config.create_invoices_for_enterprise_users).to be false + end + end + + context "and account_distributor_id and collect_billing_information are set" do + before do + params[:settings][:accounts_distributor_id] = new_distributor.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.collect_billing_information).to be true + expect(Spree::Config.create_invoices_for_enterprise_users).to be true + end + end + 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 new file mode 100644 index 0000000000..68e8410fdb --- /dev/null +++ b/spec/features/admin/accounts_and_billing_settings_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +feature 'Account and Billing Settings' do + include AuthenticationWorkflow + + describe "updating" do + let!(:admin) { create(:admin_user) } + let!(:accounts_distributor) { create(:distributor_enterprise) } + + before do + Spree::Config.set({ + accounts_distributor_id: 0, + 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" do + it "attributes can be changed" do + click_link "Configuration" + click_link "Accounts & Billing" + + select accounts_distributor.name, from: "settings_accounts_distributor_id" + 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.collect_billing_information).to be true + expect(Spree::Config.create_invoices_for_enterprise_users).to be true + end + end + end +end