diff --git a/app/controllers/spree/admin/tax_categories_controller.rb b/app/controllers/spree/admin/tax_categories_controller.rb new file mode 100644 index 00000000000..26cff4479f8 --- /dev/null +++ b/app/controllers/spree/admin/tax_categories_controller.rb @@ -0,0 +1,19 @@ +module Spree + module Admin + class TaxCategoriesController < ResourceController + def destroy + if @object.destroy + flash[:success] = flash_message_for(@object, :successfully_removed) + respond_with(@object) do |format| + format.html { redirect_to collection_url } + format.js { render partial: "spree/admin/shared/destroy" } + end + else + respond_with(@object) do |format| + format.html { redirect_to collection_url } + end + end + end + end + end +end diff --git a/app/controllers/spree/admin/tax_rates_controller.rb b/app/controllers/spree/admin/tax_rates_controller.rb new file mode 100644 index 00000000000..89d90988498 --- /dev/null +++ b/app/controllers/spree/admin/tax_rates_controller.rb @@ -0,0 +1,26 @@ +module Spree + module Admin + class TaxRatesController < ResourceController + before_filter :load_data + + update.after :update_after + create.after :create_after + + private + + def load_data + @available_zones = Zone.order(:name) + @available_categories = TaxCategory.order(:name) + @calculators = TaxRate.calculators.sort_by(&:name) + end + + def update_after + Rails.cache.delete('vat_rates') + end + + def create_after + Rails.cache.delete('vat_rates') + end + end + end +end diff --git a/app/controllers/spree/admin/tax_settings_controller.rb b/app/controllers/spree/admin/tax_settings_controller.rb new file mode 100644 index 00000000000..a66ad219fff --- /dev/null +++ b/app/controllers/spree/admin/tax_settings_controller.rb @@ -0,0 +1,15 @@ +module Spree + module Admin + class TaxSettingsController < Spree::Admin::BaseController + def update + Spree::Config.set(params[:preferences]) + + respond_to do |format| + format.html { + redirect_to edit_admin_tax_settings_path + } + end + end + end + end +end diff --git a/app/views/spree/admin/tax_categories/_form.html.haml b/app/views/spree/admin/tax_categories/_form.html.haml new file mode 100644 index 00000000000..b5070b35a10 --- /dev/null +++ b/app/views/spree/admin/tax_categories/_form.html.haml @@ -0,0 +1,15 @@ +.row + .alpha.four.columns + = f.field_container :name do + = f.label :name, t("spree.name") + = f.text_field :name, class: 'fullwidth' + .five.columns + = f.field_container :description do + = f.label :description, t("spree.description") + %br/ + = f.text_field :description, class: 'fullwidth' + .three.columns.omega + = f.field_container :is_default, class: ['checkbox'] do + %label + = f.check_box :is_default + = t("spree.default") diff --git a/app/views/spree/admin/tax_categories/edit.html.haml b/app/views/spree/admin/tax_categories/edit.html.haml new file mode 100644 index 00000000000..4d0abacedf0 --- /dev/null +++ b/app/views/spree/admin/tax_categories/edit.html.haml @@ -0,0 +1,14 @@ += render partial: 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t("spree.editing_tax_category") + +- content_for :page_actions do + %li= link_to_with_icon 'icon-arrow-left', t("spree.back_to_tax_categories_list"), admin_tax_categories_path, class: 'button' + += render partial: 'spree/shared/error_messages', locals: { target: @tax_category } + += form_for [:admin, @tax_category] do |f| + %fieldset.no-border-top + = render partial: 'form', locals: { f: f } + = render partial: 'spree/admin/shared/edit_resource_links' diff --git a/app/views/spree/admin/tax_categories/index.html.haml b/app/views/spree/admin/tax_categories/index.html.haml new file mode 100644 index 00000000000..44523eb5e8b --- /dev/null +++ b/app/views/spree/admin/tax_categories/index.html.haml @@ -0,0 +1,38 @@ += render :partial => 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t("spree.listing_tax_categories") + +- content_for :page_actions do + %ul.actions.inline-menu + %li + = button_link_to t("spree.new_tax_category"), new_object_url, :icon => 'icon-plus', :id => 'admin_new_tax_categories_link' + +%table#listing_tax_categories.index + %colgroup + %col{style: "width: 30%"}/ + %col{style: "width: 40%"}/ + %col{style: "width: 15%"}/ + %col{style: "width: 15%"}/ + %thead + %tr{"data-hook" => "tax_header"} + %th= t("spree.name") + %th= t("spree.description") + %th= t("spree.default") + %th.actions + %tbody + - @tax_categories.each do |tax_category| + - @edit_url = edit_admin_tax_category_path(tax_category) + - @delete_url = admin_tax_category_path(tax_category) + - tr_class = cycle('odd', 'even') + - tr_id = spree_dom_id(tax_category) + %tr{class: tr_class, id: tr_id} + %td= tax_category.name + %td= tax_category.description + %td.align-center= tax_category.is_default.to_s.titleize + %td.actions + = link_to_edit tax_category, no_text: true + = link_to_delete tax_category, no_text: true + - if @tax_categories.empty? + %tr + %td{colspan: "4"}= t("spree.none") diff --git a/app/views/spree/admin/tax_categories/new.html.haml b/app/views/spree/admin/tax_categories/new.html.haml new file mode 100644 index 00000000000..3ab47800ae9 --- /dev/null +++ b/app/views/spree/admin/tax_categories/new.html.haml @@ -0,0 +1,14 @@ += render partial: 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t("spree.new_tax_category") + +- content_for :page_actions do + %li= link_to_with_icon 'icon-arrow-left', t("spree.back_to_tax_categories_list"), admin_tax_categories_path, class: 'button' + += render partial: 'spree/shared/error_messages', locals: { target: @tax_category } + += form_for [:admin, @tax_category] do |f| + %fieldset.no-border-top + = render partial: 'form', locals: { f: f } + = render partial: 'spree/admin/shared/new_resource_links' diff --git a/app/views/spree/admin/tax_categories/show.html.haml b/app/views/spree/admin/tax_categories/show.html.haml new file mode 100644 index 00000000000..a84e4abc18e --- /dev/null +++ b/app/views/spree/admin/tax_categories/show.html.haml @@ -0,0 +1 @@ += render partial: 'spree/admin/shared/configuration_menu' diff --git a/app/views/spree/admin/tax_rates/_form.html.haml b/app/views/spree/admin/tax_rates/_form.html.haml new file mode 100644 index 00000000000..20dd74ca719 --- /dev/null +++ b/app/views/spree/admin/tax_rates/_form.html.haml @@ -0,0 +1,28 @@ +%div + .alpha.twelve.columns + %fieldset.no-border-bottom + %legend{align: "center"}= t("spree.general_settings") + .alpha.six.columns + .field + = f.label :name, t("spree.name") + = f.text_field :name, class: 'fullwidth' + .field + = f.label :amount, t("spree.rate") + = f.text_field :amount, class: 'fullwidth' + %p + %em= t("spree.tax_rate_amount_explanation") + .field + = f.check_box :included_in_price + = f.label :included_in_price, t("spree.included_in_price") + .omega.six.columns + .field + = f.label :zone, t("spree.zone") + = f.collection_select(:zone_id, @available_zones, :id, :name, {}, {class: 'select2 fullwidth'}) + .field + = f.label :tax_category_id, t("spree.tax_category") + = f.collection_select(:tax_category_id, @available_categories,:id, :name, {}, {class: 'select2 fullwidth'}) + .field + = f.check_box :show_rate_in_label + = f.label :show_rate_in_label, t("spree.show_rate_in_label") + .clear + = render partial: 'spree/admin/shared/calculator_fields', locals: { f: f } diff --git a/app/views/spree/admin/tax_rates/edit.html.haml b/app/views/spree/admin/tax_rates/edit.html.haml new file mode 100644 index 00000000000..191f93b9cbc --- /dev/null +++ b/app/views/spree/admin/tax_rates/edit.html.haml @@ -0,0 +1,16 @@ += render partial: 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t("spree.editing_tax_rate") + +- content_for :page_actions do + %li + = button_link_to t("spree.back_to_tax_rates_list"), spree.admin_tax_rates_path, icon: 'icon-arrow-left' + += render partial: 'spree/shared/error_messages', locals: { target: @tax_rate } + += form_for [:admin, @tax_rate] do |f| + %fieldset.no-border-top + = render partial: 'form', locals: { f: f } + .clear + = render partial: 'spree/admin/shared/edit_resource_links' diff --git a/app/views/spree/admin/tax_rates/index.html.haml b/app/views/spree/admin/tax_rates/index.html.haml new file mode 100644 index 00000000000..7217e992774 --- /dev/null +++ b/app/views/spree/admin/tax_rates/index.html.haml @@ -0,0 +1,48 @@ += render partial: 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t("spree.tax_rates") + +- content_for :page_actions do + %li + = button_link_to t("spree.new_tax_rate"), new_object_url, icon: 'icon-plus' + +- unless @tax_rates.any? + .no-objects-found + = t("spree.no_results") +- else + %table.index + %colgroup + %col{style: "width: 15%"}/ + %col{style: "width: 15%"}/ + %col{style: "width: 10%"}/ + %col{style: "width: 10%"}/ + %col{style: "width: 10%"}/ + %col{style: "width: 10%"}/ + %col{style: "width: 15%"}/ + %col{style: "width: 15%"}/ + %thead + %tr + %th= t("spree.zone") + %th= t("spree.name") + %th= t("spree.category") + %th= t("spree.amount") + %th= t("spree.included_in_price") + %th= t("spree.show_rate_in_label") + %th= t("spree.calculator") + %th.actions + %tbody + - @tax_rates.each do |tax_rate| + - tr_class = cycle('odd', 'even') + - tr_id = spree_dom_id(tax_rate) + %tr{class: tr_class, id: tr_id} + %td= tax_rate.zone.try(:name) || t("spree.not_available") + %td= tax_rate.name + %td= tax_rate.tax_category.try(:name) || t("spree.not_available") + %td.align-center= tax_rate.amount + %td.align-center= tax_rate.included_in_price + %td.align-center= tax_rate.show_rate_in_label + %td.align-center= tax_rate.calculator.to_s + %td.actions + = link_to_edit tax_rate, no_text: true + = link_to_delete tax_rate, no_text: true diff --git a/app/views/spree/admin/tax_rates/new.html.haml b/app/views/spree/admin/tax_rates/new.html.haml new file mode 100644 index 00000000000..cbf5986a99c --- /dev/null +++ b/app/views/spree/admin/tax_rates/new.html.haml @@ -0,0 +1,16 @@ += render partial: 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t("spree.new_tax_rate") + +- content_for :page_actions do + %li + = button_link_to t("spree.back_to_tax_rates_list"), spree.admin_tax_rates_path, icon: 'icon-arrow-left' + += render partial: 'spree/shared/error_messages', locals: { target: @tax_rate } + += form_for [:admin, @tax_rate] do |f| + %fieldset.no-border-top + = render partial: 'form', locals: { f: f } + .clear + = render partial: 'spree/admin/shared/new_resource_links' diff --git a/config/routes/spree.rb b/config/routes/spree.rb index a06644de8fe..c732615e875 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -89,6 +89,10 @@ end end + resources :tax_rates + resource :tax_settings + resources :tax_categories + resources :zones resources :countries do resources :states diff --git a/spec/features/admin/configuration/tax_categories_spec.rb b/spec/features/admin/configuration/tax_categories_spec.rb new file mode 100644 index 00000000000..4b9714241e0 --- /dev/null +++ b/spec/features/admin/configuration/tax_categories_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +describe "Tax Categories" do + include AuthenticationWorkflow + + before(:each) do + quick_login_as_admin + visit spree.admin_path + click_link "Configuration" + end + + context "admin visiting tax categories list" do + it "should display the existing tax categories" do + create(:tax_category, name: "Clothing", description: "For Clothing") + click_link "Tax Categories" + expect(page).to have_content("Listing Tax Categories") + within_row(1) do + expect(column_text(1)).to eq("Clothing") + expect(column_text(2)).to eq("For Clothing") + expect(column_text(3)).to eq("False") + end + end + end + + context "admin creating new tax category" do + before(:each) do + click_link "Tax Categories" + click_link "admin_new_tax_categories_link" + end + + it "should be able to create new tax category" do + expect(page).to have_content("New Tax Category") + fill_in "tax_category_name", with: "sports goods" + fill_in "tax_category_description", with: "sports goods desc" + click_button "Create" + expect(page).to have_content("successfully created!") + end + + it "should show validation errors if there are any" do + click_button "Create" + expect(page).to have_content("Name can't be blank") + end + end + + context "admin editing a tax category" do + it "should be able to update an existing tax category" do + create(:tax_category) + click_link "Tax Categories" + within_row(1) { click_icon :edit } + fill_in "tax_category_description", with: "desc 99" + click_button "Update" + expect(page).to have_content("successfully updated!") + expect(page).to have_content("desc 99") + end + end +end diff --git a/spec/features/admin/configuration/tax_rates_spec.rb b/spec/features/admin/configuration/tax_rates_spec.rb new file mode 100644 index 00000000000..1ed41381da6 --- /dev/null +++ b/spec/features/admin/configuration/tax_rates_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe "Tax Rates" do + include AuthenticationWorkflow + + let!(:calculator) { create(:calculator_per_item, calculable: create(:order)) } + let!(:tax_rate) { create(:tax_rate, calculator: calculator) } + + before do + quick_login_as_admin + visit spree.admin_path + click_link "Configuration" + end + + # Regression test for #535 + it "can see a tax rate in the list if the tax category has been deleted" do + tax_rate.tax_category.update_column(:deleted_at, Time.zone.now) + expect { click_link "Tax Rates" }.not_to raise_error + within("table tbody td:nth-child(3)") do + expect(page).to have_content("N/A") + end + end + + # Regression test for #1422 + it "can create a new tax rate" do + click_link "Tax Rates" + click_link "New Tax Rate" + fill_in "Rate", with: "0.05" + click_button "Create" + expect(page).to have_content("Tax Rate has been successfully created!") + end +end