diff --git a/.gitignore b/.gitignore index 6607473215..8c3ebf892c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ app/public public/system public/stylesheets public/images +public/files public/spree public/assets config/abr.yml diff --git a/app/helpers/terms_and_conditions_helper.rb b/app/helpers/terms_and_conditions_helper.rb index ef50459edb..c9e907d228 100644 --- a/app/helpers/terms_and_conditions_helper.rb +++ b/app/helpers/terms_and_conditions_helper.rb @@ -1,6 +1,20 @@ # frozen_string_literal: true module TermsAndConditionsHelper + def render_terms_and_conditions + if platform_terms_required? && terms_and_conditions_activated? + render("checkout/all_terms_and_conditions") + elsif platform_terms_required? + render "checkout/platform_terms_of_service" + elsif terms_and_conditions_activated? + render "checkout/terms_and_conditions" + end + end + + def platform_terms_required? + Spree::Config.shoppers_require_tos + end + def terms_and_conditions_activated? current_order.distributor.terms_and_conditions.file? end diff --git a/app/models/spree/app_configuration.rb b/app/models/spree/app_configuration.rb index 6b4a57aa76..d30f0e6215 100644 --- a/app/models/spree/app_configuration.rb +++ b/app/models/spree/app_configuration.rb @@ -111,6 +111,7 @@ module Spree # Legal Preferences preference :footer_tos_url, :string, default: "/Terms-of-service.pdf" preference :enterprises_require_tos, :boolean, default: false + preference :shoppers_require_tos, :boolean, default: false preference :privacy_policy_url, :string, default: nil preference :cookies_consent_banner_toggle, :boolean, default: false preference :cookies_policy_matomo_section, :boolean, default: false diff --git a/app/views/checkout/_all_terms_and_conditions.html.haml b/app/views/checkout/_all_terms_and_conditions.html.haml new file mode 100644 index 0000000000..36314bdcfe --- /dev/null +++ b/app/views/checkout/_all_terms_and_conditions.html.haml @@ -0,0 +1,4 @@ +%p + %input{ type: 'checkbox', id: 'accept_terms', ng: { model: "terms_and_conditions_accepted", init: "terms_and_conditions_accepted=false" } } + %label.small{for: "accept_terms"} + = t('.message_html', terms_and_conditions_link: link_to( t(".terms_and_conditions"), current_order.distributor.terms_and_conditions.url, target: '_blank'), tos_link: link_to(t(".terms_of_service"), Spree::Config.footer_tos_url, target: "_blank")) diff --git a/app/views/checkout/_form.html.haml b/app/views/checkout/_form.html.haml index 362586974c..84601fd410 100644 --- a/app/views/checkout/_form.html.haml +++ b/app/views/checkout/_form.html.haml @@ -15,8 +15,8 @@ = render "checkout/shipping", f: f = render "checkout/payment", f: f = render "checkout/already_ordered", f: f if show_bought_items? - = render "checkout/terms_and_conditions", f: f + = render_terms_and_conditions %p - %button.button.primary{ type: :submit, ng: { disabled: "terms_and_conditions_activated && !terms_and_conditions_accepted" } } + %button.button.primary{ type: :submit, ng: { disabled: "terms_and_conditions_accepted == false || platform_tos_accepted == false" } } = t :checkout_send / {{ checkout.$valid }} diff --git a/app/views/checkout/_platform_terms_of_service.html.haml b/app/views/checkout/_platform_terms_of_service.html.haml new file mode 100644 index 0000000000..2fdc57dcb1 --- /dev/null +++ b/app/views/checkout/_platform_terms_of_service.html.haml @@ -0,0 +1,4 @@ +%p + %input{ type: "checkbox", id: "platform_tos_accepted", ng: { model: "platform_tos_accepted", init: "platform_tos_accepted = false" } } + %label.small{for: "platform_tos_accepted"} + = t(".message_html", tos_link: link_to(t(".terms_of_service"), Spree::Config.footer_tos_url, target: "_blank")) diff --git a/app/views/checkout/_terms_and_conditions.html.haml b/app/views/checkout/_terms_and_conditions.html.haml index 05e0122ae7..e84b4b9c81 100644 --- a/app/views/checkout/_terms_and_conditions.html.haml +++ b/app/views/checkout/_terms_and_conditions.html.haml @@ -1,4 +1,3 @@ -- if terms_and_conditions_activated? - %p - %input{ type: 'checkbox', id: 'accept_terms', ng: { model: "terms_and_conditions_accepted", init: "terms_and_conditions_activated=#{terms_and_conditions_activated?}; terms_and_conditions_accepted=#{terms_and_conditions_already_accepted?}" } } - %label.small{for: "accept_terms"}= t('.message_html', terms_and_conditions_link: link_to( t( '.link_text' ), current_order.distributor.terms_and_conditions.url, target: '_blank')) +%p + %input{ type: 'checkbox', id: 'accept_terms', ng: { model: "terms_and_conditions_accepted", init: "terms_and_conditions_accepted=#{terms_and_conditions_already_accepted?}" } } + %label.small{for: "accept_terms"}= t('.message_html', terms_and_conditions_link: link_to( t( '.link_text' ), current_order.distributor.terms_and_conditions.url, target: '_blank')) diff --git a/app/views/spree/admin/general_settings/edit.html.haml b/app/views/spree/admin/general_settings/edit.html.haml index 9201fa00cb..d7014627b7 100644 --- a/app/views/spree/admin/general_settings/edit.html.haml +++ b/app/views/spree/admin/general_settings/edit.html.haml @@ -32,6 +32,9 @@ .field = preference_field_tag(:enterprises_require_tos, Spree::Config[:enterprises_require_tos], :type => Spree::Config.preference_type(:enterprises_require_tos)) = label_tag(:enterprises_require_tos, t('.enterprises_require_tos')) + tag(:br) + .field + = preference_field_tag(:shoppers_require_tos, Spree::Config[:shoppers_require_tos], :type => Spree::Config.preference_type(:shoppers_require_tos)) + = label_tag(:shoppers_require_tos, t('.shoppers_require_tos')) + tag(:br) .field = preference_field_tag(:cookies_consent_banner_toggle, Spree::Config[:cookies_consent_banner_toggle], :type => Spree::Config.preference_type(:cookies_consent_banner_toggle)) = label_tag(:cookies_consent_banner_toggle, t('.cookies_consent_banner_toggle')) + tag(:br) diff --git a/config/locales/en.yml b/config/locales/en.yml index 8aefff8022..fe50504b40 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1246,6 +1246,13 @@ en: terms_and_conditions: message_html: "I agree to the seller's %{terms_and_conditions_link}." link_text: "Terms and Conditions" + platform_terms_of_service: + message_html: "I agree to the platform %{tos_link}." + terms_of_service: "Terms of Service" + all_terms_and_conditions: + message_html: "I agree to the seller's %{terms_and_conditions_link} and the platform %{tos_link}." + terms_and_conditions: "Terms and Conditions" + terms_of_service: "Terms of Service" failed: "The checkout failed. Please let us know so that we can process your order." shops: hubs: @@ -3582,6 +3589,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using cookies_consent_banner_toggle: "Display cookies consent banner" privacy_policy_url: "Privacy Policy URL" enterprises_require_tos: "Enterprises must accept Terms of Service" + shoppers_require_tos: "Shoppers must accept Terms of Service" cookies_policy_matomo_section: "Display Matomo section on cookies policy page" footer_tos_url: "Terms of Service URL" checkout: diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index 20e141e262..dc2b5832ce 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -119,12 +119,12 @@ feature "As a consumer I want to check out my cart", js: true do end end - it "doesn't tell about previous orders" do + it "shows only applicable content" do expect(page).to have_no_content("You have an order for this order cycle already.") - end - it "doesn't show link to terms and conditions" do expect(page).to have_no_link("Terms and Conditions") + + expect(page).to have_no_link("Terms of Service") end end @@ -171,6 +171,57 @@ feature "As a consumer I want to check out my cart", js: true do end end + context "when the platform's terms of service have to be accepted" do + let(:tos_url) { "https://example.org/tos" } + + before do + allow(Spree::Config).to receive(:shoppers_require_tos).and_return(true) + allow(Spree::Config).to receive(:footer_tos_url).and_return(tos_url) + end + + it "shows the terms which need to be accepted" do + visit checkout_path + expect(page).to have_link("Terms of Service", href: tos_url) + expect(find_link("Terms of Service")[:target]).to eq "_blank" + expect(page).to have_button("Place order now", disabled: true) + + check "Terms of Service" + expect(page).to have_button("Place order now", disabled: false) + + uncheck "Terms of Service" + expect(page).to have_button("Place order now", disabled: true) + end + end + + context "when the seller's terms and the platform's terms have to be accepted" do + let(:fake_terms_and_conditions_path) { Rails.root.join("app/assets/images/logo-white.png") } + let(:terms_and_conditions_file) { Rack::Test::UploadedFile.new(fake_terms_and_conditions_path, "application/pdf") } + let(:tos_url) { "https://example.org/tos" } + + before do + order.distributor.terms_and_conditions = terms_and_conditions_file + order.distributor.save! + + allow(Spree::Config).to receive(:shoppers_require_tos).and_return(true) + allow(Spree::Config).to receive(:footer_tos_url).and_return(tos_url) + end + + it "shows links to both terms and all need accepting" do + visit checkout_path + + expect(page).to have_link("Terms and Conditions", href: order.distributor.terms_and_conditions.url) + expect(page).to have_link("Terms of Service", href: tos_url) + expect(page).to have_button("Place order now", disabled: true) + + # Both Ts&Cs and TOS appear in the one label for the one checkbox. + check "Terms and Conditions" + expect(page).to have_button("Place order now", disabled: false) + + uncheck "Terms of Service" + expect(page).to have_button("Place order now", disabled: true) + end + end + context "with previous orders" do let!(:prev_order) { create(:completed_order_with_totals, order_cycle: order_cycle, distributor: distributor, user: order.user) } diff --git a/spec/helpers/terms_and_conditions_helper_spec.rb b/spec/helpers/terms_and_conditions_helper_spec.rb new file mode 100644 index 0000000000..3878891b28 --- /dev/null +++ b/spec/helpers/terms_and_conditions_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe TermsAndConditionsHelper, type: :helper do + describe "#platform_terms_required?" do + it "returns true" do + expect(Spree::Config).to receive(:shoppers_require_tos).and_return(true) + expect(helper.platform_terms_required?).to eq true + end + + it "returns false" do + expect(Spree::Config).to receive(:shoppers_require_tos).and_return(false) + expect(helper.platform_terms_required?).to eq false + end + end +end