diff --git a/app/controllers/stash_engine/journal_admin_controller.rb b/app/controllers/stash_engine/journal_admin_controller.rb index e5ffb95fda..25d60a42aa 100644 --- a/app/controllers/stash_engine/journal_admin_controller.rb +++ b/app/controllers/stash_engine/journal_admin_controller.rb @@ -119,7 +119,7 @@ def edit_params :preprint_server, :journal_code, :manuscript_number_regex, :peer_review_custom_text, :sponsor_id, :default_to_ppr, :allow_review_workflow, :flag, :note, flag_attributes: %i[id note _destroy], - payment_configuration_attributes: %i[id payment_plan covers_ldf ldf_limit yearly_ldf_limit]) + payment_configuration_attributes: %i[id payment_plan]) end end end diff --git a/app/controllers/stash_engine/journal_organization_admin_controller.rb b/app/controllers/stash_engine/journal_organization_admin_controller.rb index 036f926cad..b52cc765b2 100644 --- a/app/controllers/stash_engine/journal_organization_admin_controller.rb +++ b/app/controllers/stash_engine/journal_organization_admin_controller.rb @@ -26,6 +26,7 @@ def index def edit @org = authorize StashEngine::JournalOrganization.find(params[:id]) + @payment_configuration = @org.payment_configuration || @org.build_payment_configuration respond_to(&:js) end @@ -42,6 +43,7 @@ def update def new @org = authorize StashEngine::JournalOrganization.new + @payment_configuration = @org.build_payment_configuration respond_to(&:js) end @@ -73,7 +75,7 @@ def setup_sponsors end def update_hash - valid = %i[name parent_org_id] + valid = %i[name parent_org_id payment_configuration_attributes] update = edit_params.slice(*valid) update[:parent_org_id] = nil if edit_params.key?(:parent_org_id) && edit_params[:parent_org_id].blank? update[:contact] = edit_params[:contact].split("\n").map(&:strip).to_json if edit_params[:contact] @@ -81,7 +83,8 @@ def update_hash end def edit_params - params.permit(:id, :name, :contact, :parent_org_id) + params.permit(:id, :name, :contact, :parent_org_id, + payment_configuration_attributes: %i[id payment_plan covers_ldf ldf_limit yearly_ldf_limit]) end end diff --git a/app/models/stash_engine/journal_organization.rb b/app/models/stash_engine/journal_organization.rb index 30480944b0..0f47dda9f2 100644 --- a/app/models/stash_engine/journal_organization.rb +++ b/app/models/stash_engine/journal_organization.rb @@ -21,6 +21,8 @@ class JournalOrganization < ApplicationRecord has_many :journals_sponsored, class_name: 'StashEngine::Journal', foreign_key: :sponsor_id has_many :roles, class_name: 'StashEngine::Role', as: :role_object, dependent: :destroy has_many :users, through: :roles + has_one :payment_configuration, as: :partner, dependent: :destroy + accepts_nested_attributes_for(*%i[payment_configuration]) scope :has_children, -> { distinct.joins(:children) } diff --git a/app/services/sponsored_payments_service.rb b/app/services/sponsored_payments_service.rb index e607cb4ad0..57d2d82c10 100644 --- a/app/services/sponsored_payments_service.rb +++ b/app/services/sponsored_payments_service.rb @@ -47,4 +47,8 @@ def ldf_fees end FeeCalculatorService.new(payer_type).ldf_amount(resource: resource, payer: payer) end + + def sponsor_id + payer.sponsor_id + end end diff --git a/app/views/stash_engine/journal_admin/_form.html.erb b/app/views/stash_engine/journal_admin/_form.html.erb index 2294a0a04c..05659246b1 100644 --- a/app/views/stash_engine/journal_admin/_form.html.erb +++ b/app/views/stash_engine/journal_admin/_form.html.erb @@ -28,19 +28,6 @@
<% end %> - -

- <%= pf.check_box :covers_ldf, {checked: @payment_configuration.covers_ldf}, 1, 0 %> - <%= pf.label :covers_ldf, "When checked, journal covers Large Data Fees" %> -

-

- <%= pf.label :ldf_limit, "Covered Large Data Fee limit (GB)" %> - <%= pf.select :ldf_limit, ldf_pricing_tiers_options, { selected: @payment_configuration.ldf_limit }, class: 'c-input__select', disabled: !@payment_configuration.covers_ldf %> -

-

- <%= pf.label :yearly_ldf_limit, "Yearly Large Data Fee limit $" %> - <%= pf.number_field :yearly_ldf_limit, value: @payment_configuration.yearly_ldf_limit, class: 'c-input__text', disabled: !@payment_configuration.covers_ldf %> -

<% end %>

diff --git a/app/views/stash_engine/journal_organization_admin/_form.html.erb b/app/views/stash_engine/journal_organization_admin/_form.html.erb index 159d24430a..eed4246061 100644 --- a/app/views/stash_engine/journal_organization_admin/_form.html.erb +++ b/app/views/stash_engine/journal_organization_admin/_form.html.erb @@ -2,6 +2,34 @@ <%= form.label :name, "Name of publisher or society"%> <%= form.text_field(:name, required: true, value: @org.name, class: 'c-input__text', style: 'width:100%') %> +<%= fields_for :payment_configuration_attributes do |pf| %> + <%= pf.hidden_field :id, value: @payment_configuration.id %> + <% + plan_radios = [ ['', 'None'] ] + StashEngine::Journal::PAYMENT_PLANS.map {|p| [p, p.capitalize]} + %> +

Membership

+
+ Payment plan type: + <% plan_radios.each do |plan| %> + <%= pf.radio_button :payment_plan, plan.first, checked: plan.first == @payment_configuration.payment_plan %> + +
+ <% end %> +
+ +

+ <%= pf.check_box :covers_ldf, {checked: @payment_configuration.covers_ldf}, 1, 0 %> + <%= pf.label :covers_ldf, "When checked, journal covers Large Data Fees" %> +

+

+ <%= pf.label :ldf_limit, "Covered Large Data Fee limit (GB)" %> + <%= pf.select :ldf_limit, ldf_pricing_tiers_options, { selected: @payment_configuration.ldf_limit }, class: 'c-input__select', disabled: !@payment_configuration.covers_ldf %> +

+

+ <%= pf.label :yearly_ldf_limit, "Yearly Large Data Fee limit $" %> + <%= pf.number_field :yearly_ldf_limit, value: @payment_configuration.yearly_ldf_limit, class: 'c-input__text', disabled: !@payment_configuration.covers_ldf %> +

+<% end %>

Contacts

<%= form.label :contact, "Place each email address on a new line:"%> diff --git a/app/views/stash_engine/journal_organization_admin/edit.js.erb b/app/views/stash_engine/journal_organization_admin/edit.js.erb index ce04b520de..1b81dbefd4 100644 --- a/app/views/stash_engine/journal_organization_admin/edit.js.erb +++ b/app/views/stash_engine/journal_organization_admin/edit.js.erb @@ -5,3 +5,15 @@ document.getElementById('cancel_dialog').addEventListener('click', (e) => { e.preventDefault(); document.getElementById('genericModalDialog').close(); }); + +var ldf = document.getElementById('payment_configuration_attributes_covers_ldf') +ldf.addEventListener('change', () => { + var limit = document.getElementById('payment_configuration_attributes_ldf_limit') + limit.disabled = !ldf.checked + var amount_limit = document.getElementById('payment_configuration_attributes_yearly_ldf_limit') + amount_limit.disabled = !ldf.checked + if (!ldf.checked) { + limit.value = '' + amount_limit.value = '' + } +}) diff --git a/app/views/stash_engine/journal_organization_admin/new.js.erb b/app/views/stash_engine/journal_organization_admin/new.js.erb index 914b4cee3a..2f4c91ef77 100644 --- a/app/views/stash_engine/journal_organization_admin/new.js.erb +++ b/app/views/stash_engine/journal_organization_admin/new.js.erb @@ -5,3 +5,15 @@ document.getElementById('cancel_dialog').addEventListener('click', (e) => { e.preventDefault(); document.getElementById('genericModalDialog').close(); }); + +var ldf = document.getElementById('payment_configuration_attributes_covers_ldf') +ldf.addEventListener('change', () => { + var limit = document.getElementById('payment_configuration_attributes_ldf_limit') + limit.disabled = !ldf.checked + var amount_limit = document.getElementById('payment_configuration_attributes_yearly_ldf_limit') + amount_limit.disabled = !ldf.checked + if (!ldf.checked) { + limit.value = '' + amount_limit.value = '' + } +}) diff --git a/spec/services/payment_limits_service_spec.rb b/spec/services/payment_limits_service_spec.rb index fe579cd337..2b601c87f8 100644 --- a/spec/services/payment_limits_service_spec.rb +++ b/spec/services/payment_limits_service_spec.rb @@ -1,177 +1,358 @@ describe PaymentLimitsService do + describe 'when tenant is the payer' do + let(:identifier) { create(:identifier) } + let(:total_file_size) { 10_000_000_001 } + let!(:sponsor_tenant) { create(:tenant, id: 'sponsor') } + let!(:tenant) { create(:tenant, sponsor: sponsor_tenant, id: 'payer') } + let!(:other_tenant) { create(:tenant, sponsor: sponsor_tenant, id: 'other') } + let!(:payment_conf) do + create(:payment_configuration, + partner: tenant, + payment_plan: '2025', + covers_dpc: true, + covers_ldf: true, + ldf_limit: 1, + yearly_ldf_limit: 1_000) + end + let(:resource) { create(:resource, identifier: identifier, tenant: tenant, total_file_size: total_file_size) } + let(:payer) { tenant } - let(:identifier) { create(:identifier) } - let(:total_file_size) { 10_000_000_001 } - let!(:sponsor_tenant) { create(:tenant, id: 'sponsor') } - let!(:tenant) { create(:tenant, sponsor: sponsor_tenant, id: 'payer') } - let!(:other_tenant) { create(:tenant, sponsor: sponsor_tenant, id: 'other') } - let!(:payment_conf) do - create(:payment_configuration, - partner: tenant, - payment_plan: '2025', - covers_dpc: true, - covers_ldf: true, - ldf_limit: 1, - yearly_ldf_limit: 1_000) - end - let(:resource) { create(:resource, identifier: identifier, tenant: tenant, total_file_size: total_file_size) } - let(:payer) { tenant } - - let(:subject) { PaymentLimitsService.new(resource, payer) } + let(:subject) { PaymentLimitsService.new(resource, payer) } - describe '#initialize' do - it 'sets proper attributes' do - expect(subject.resource).to eq(resource) - expect(subject.payer).to eq(payer) + describe '#initialize' do + it 'sets proper attributes' do + expect(subject.resource).to eq(resource) + expect(subject.payer).to eq(payer) + end end - end - describe '#limits_exceeded?' do - let(:subject) { PaymentLimitsService.new(resource, payer).limits_exceeded? } + describe '#limits_exceeded?' do + let(:subject) { PaymentLimitsService.new(resource, payer).limits_exceeded? } - context 'when payer has a 2025 payment plan' do - context 'when payer amount limit is set' do - context 'but not reached' do - it { is_expected.to be_falsey } - end + context 'when payer has a 2025 payment plan' do + context 'when payer amount limit is set' do + context 'but not reached' do + it { is_expected.to be_falsey } + end - context 'when limit is already exceeded' do - let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 1_001) } + context 'when limit is already exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 1_001) } - it { is_expected.to be_truthy } + it { is_expected.to be_truthy } + + context 'but resource LDF is 0' do + let(:total_file_size) { 10_000 } + + it { is_expected.to be_falsey } + end + end + + context 'when limit is not reached but with current resource it will be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 999) } + + it { is_expected.to be_truthy } + end + + context 'when limit is not reached and with current resource it will not be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 100) } + + it { is_expected.to be_falsey } + end context 'but resource LDF is 0' do let(:total_file_size) { 10_000 } it { is_expected.to be_falsey } end - end - context 'when limit is not reached but with current resource it will be exceeded' do - let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 999) } + context 'with logs on previous year' do + let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 1_001, created_at: 1.year.ago) } - it { is_expected.to be_truthy } + it { is_expected.to be_falsey } + end end - context 'when limit is not reached and with current resource it will not be exceeded' do - let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 100) } + context 'when sponsor amount limit is set' do + let!(:payment_conf2) do + create(:payment_configuration, + partner: sponsor_tenant, + payment_plan: '2025', + covers_dpc: true, + covers_ldf: true, + yearly_ldf_limit: 1_000) + end - it { is_expected.to be_falsey } + context 'but not reached' do + it { is_expected.to be_falsey } + end + + context 'when limit is already exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: other_tenant, ldf: 1_001, sponsor_id: sponsor_tenant.id) } + + it { is_expected.to be_truthy } + + context 'but resource LDF is 0' do + let(:total_file_size) { 10_000 } + + it { is_expected.to be_falsey } + end + end + + context 'when limit is not reached but with current resource it will be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: other_tenant, ldf: 999, sponsor_id: sponsor_tenant.id) } + + it { is_expected.to be_truthy } + end + + context 'when limit is not reached and with current resource it will not be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: other_tenant, ldf: 100, sponsor_id: sponsor_tenant.id) } + + it { is_expected.to be_falsey } + end + + context 'but resource LDF is 0' do + let(:total_file_size) { 10_000 } + + it { is_expected.to be_falsey } + end + + context 'with logs on previous year' do + let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 1_001, created_at: 1.year.ago, sponsor_id: sponsor_tenant.id) } + let!(:log2) { create(:sponsored_payment_log, payer: other_tenant, ldf: 1_001, created_at: 1.year.ago, sponsor_id: sponsor_tenant.id) } + + it { is_expected.to be_falsey } + end end - context 'but resource LDF is 0' do - let(:total_file_size) { 10_000 } + context 'when dataset size limit is set' do + context 'but not reached' do + it { is_expected.to be_falsey } + end - it { is_expected.to be_falsey } + context 'when limit is not reached but with current version it will be exceeded' do + let(:total_file_size) { 50_000_000_001 } + + it { is_expected.to be_truthy } + end + + context 'when limit is not reached and with current resource it will not be exceeded' do + let(:total_file_size) { 50_000_000_000 } + + it { is_expected.to be_falsey } + end end - context 'with logs on previous year' do - let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 1_001, created_at: 1.year.ago) } + context 'when no limit is set' do + let!(:payment_conf) do + create(:payment_configuration, partner: tenant, payment_plan: '2025', covers_dpc: true, yearly_ldf_limit: nil) + end it { is_expected.to be_falsey } end end - context 'when sponsor amount limit is set' do - let!(:payment_conf2) do - create(:payment_configuration, - partner: sponsor_tenant, - payment_plan: '2025', - covers_dpc: true, - covers_ldf: true, - yearly_ldf_limit: 1_000) - end + context 'when payer is not set' do + let(:payer) { nil } + it { is_expected.to be_truthy } + end - context 'but not reached' do - it { is_expected.to be_falsey } - end + context 'when payer has different payment plan than 2025' do + let!(:payment_conf) { create(:payment_configuration, partner: tenant, payment_plan: 'TIERED', covers_dpc: true) } + + it { is_expected.to be_falsey } + end + end + + describe '#payment_allowed?' do + it 'returns true if limit is exceeded' do + expect(subject).to receive(:limits_exceeded?).and_return(true) + expect(subject.payment_allowed?).to be_falsey + end + + it 'returns false if limit is not exceeded' do + expect(subject).to receive(:limits_exceeded?).and_return(false) + expect(subject.payment_allowed?).to be_truthy + end + end + end - context 'when limit is already exceeded' do - let!(:log) { create(:sponsored_payment_log, payer: other_tenant, ldf: 1_001, sponsor_id: sponsor_tenant.id) } + describe 'when journal is the payer' do + let(:identifier) { create(:identifier) } + let(:total_file_size) { 10_000_000_001 } + let!(:tenant) { create(:tenant, sponsor: sponsor_tenant, id: 'payer') } + let!(:sponsor_journal_org) { create(:journal_organization) } + let!(:journal) { create(:journal, sponsor: sponsor_journal_org) } + let!(:other_journal) { create(:journal, sponsor: sponsor_journal_org) } + let!(:payment_conf) do + create(:payment_configuration, + partner: journal, + payment_plan: '2025', + covers_dpc: true, + covers_ldf: true, + ldf_limit: 1, + yearly_ldf_limit: 1_000) + end + let(:resource) { create(:resource, identifier: identifier, tenant: tenant, total_file_size: total_file_size) } + let(:payer) { journal } + + let(:subject) { PaymentLimitsService.new(resource, payer) } + + describe '#initialize' do + it 'sets proper attributes' do + expect(subject.resource).to eq(resource) + expect(subject.payer).to eq(payer) + end + end + + describe '#limits_exceeded?' do + let(:subject) { PaymentLimitsService.new(resource, payer).limits_exceeded? } + + context 'when payer has a 2025 payment plan' do + context 'when payer amount limit is set' do + context 'but not reached' do + it { is_expected.to be_falsey } + end + + context 'when limit is already exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: journal, ldf: 1_001) } + + it { is_expected.to be_truthy } + + context 'but resource LDF is 0' do + let(:total_file_size) { 10_000 } + + it { is_expected.to be_falsey } + end + end + + context 'when limit is not reached but with current resource it will be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: journal, ldf: 999) } + + it { is_expected.to be_truthy } + end + + context 'when limit is not reached and with current resource it will not be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: journal, ldf: 100) } - it { is_expected.to be_truthy } + it { is_expected.to be_falsey } + end context 'but resource LDF is 0' do let(:total_file_size) { 10_000 } it { is_expected.to be_falsey } end - end - context 'when limit is not reached but with current resource it will be exceeded' do - let!(:log) { create(:sponsored_payment_log, payer: other_tenant, ldf: 999, sponsor_id: sponsor_tenant.id) } + context 'with logs on previous year' do + let!(:log) { create(:sponsored_payment_log, payer: journal, ldf: 1_001, created_at: 1.year.ago) } - it { is_expected.to be_truthy } + it { is_expected.to be_falsey } + end end - context 'when limit is not reached and with current resource it will not be exceeded' do - let!(:log) { create(:sponsored_payment_log, payer: other_tenant, ldf: 100, sponsor_id: sponsor_tenant.id) } + context 'when sponsor amount limit is set' do + let!(:payment_conf2) do + create(:payment_configuration, + partner: sponsor_journal_org, + payment_plan: '2025', + covers_dpc: true, + covers_ldf: true, + yearly_ldf_limit: 1_000) + end - it { is_expected.to be_falsey } - end + context 'but not reached' do + it { is_expected.to be_falsey } + end - context 'but resource LDF is 0' do - let(:total_file_size) { 10_000 } + context 'when limit is already exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: other_journal, ldf: 1_001, sponsor_id: sponsor_journal_org.id) } - it { is_expected.to be_falsey } - end + it { is_expected.to be_truthy } - context 'with logs on previous year' do - let!(:log) { create(:sponsored_payment_log, payer: tenant, ldf: 1_001, created_at: 1.year.ago, sponsor_id: sponsor_tenant.id) } - let!(:log2) { create(:sponsored_payment_log, payer: other_tenant, ldf: 1_001, created_at: 1.year.ago, sponsor_id: sponsor_tenant.id) } + context 'but resource LDF is 0' do + let(:total_file_size) { 10_000 } - it { is_expected.to be_falsey } - end - end + it { is_expected.to be_falsey } + end + end - context 'when dataset size limit is set' do - context 'but not reached' do - it { is_expected.to be_falsey } + context 'when limit is not reached but with current resource it will be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: other_journal, ldf: 999, sponsor_id: sponsor_journal_org.id) } + + it { is_expected.to be_truthy } + end + + context 'when limit is not reached and with current resource it will not be exceeded' do + let!(:log) { create(:sponsored_payment_log, payer: other_journal, ldf: 100, sponsor_id: sponsor_journal_org.id) } + + it { is_expected.to be_falsey } + end + + context 'but resource LDF is 0' do + let(:total_file_size) { 10_000 } + + it { is_expected.to be_falsey } + end + + context 'with logs on previous year' do + let!(:log) { create(:sponsored_payment_log, payer: journal, ldf: 1_001, created_at: 1.year.ago, sponsor_id: sponsor_journal_org.id) } + let!(:log2) do + create(:sponsored_payment_log, payer: other_journal, ldf: 1_001, created_at: 1.year.ago, sponsor_id: sponsor_journal_org.id) + end + + it { is_expected.to be_falsey } + end end - context 'when limit is not reached but with current version it will be exceeded' do - let(:total_file_size) { 50_000_000_001 } + context 'when dataset size limit is set' do + context 'but not reached' do + it { is_expected.to be_falsey } + end + + context 'when limit is not reached but with current version it will be exceeded' do + let(:total_file_size) { 50_000_000_001 } - it { is_expected.to be_truthy } + it { is_expected.to be_truthy } + end + + context 'when limit is not reached and with current resource it will not be exceeded' do + let(:total_file_size) { 50_000_000_000 } + + it { is_expected.to be_falsey } + end end - context 'when limit is not reached and with current resource it will not be exceeded' do - let(:total_file_size) { 50_000_000_000 } + context 'when no limit is set' do + let!(:payment_conf) do + create(:payment_configuration, partner: journal, payment_plan: '2025', covers_dpc: true, yearly_ldf_limit: nil) + end it { is_expected.to be_falsey } end end - context 'when no limit is set' do - let!(:payment_conf) do - create(:payment_configuration, partner: tenant, payment_plan: '2025', covers_dpc: true, yearly_ldf_limit: nil) - end - - it { is_expected.to be_falsey } + context 'when payer is not set' do + let(:payer) { nil } + it { is_expected.to be_truthy } end - end - - context 'when payer is not set' do - let(:payer) { nil } - it { is_expected.to be_truthy } - end - context 'when payer has different payment plan than 2025' do - let!(:payment_conf) { create(:payment_configuration, partner: tenant, payment_plan: 'TIERED', covers_dpc: true) } + context 'when payer has different payment plan than 2025' do + let!(:payment_conf) { create(:payment_configuration, partner: tenant, payment_plan: 'TIERED', covers_dpc: true) } - it { is_expected.to be_falsey } + it { is_expected.to be_falsey } + end end - end - describe '#payment_allowed?' do - it 'returns true if limit is exceeded' do - expect(subject).to receive(:limits_exceeded?).and_return(true) - expect(subject.payment_allowed?).to be_falsey - end + describe '#payment_allowed?' do + it 'returns true if limit is exceeded' do + expect(subject).to receive(:limits_exceeded?).and_return(true) + expect(subject.payment_allowed?).to be_falsey + end - it 'returns false if limit is not exceeded' do - expect(subject).to receive(:limits_exceeded?).and_return(false) - expect(subject.payment_allowed?).to be_truthy + it 'returns false if limit is not exceeded' do + expect(subject).to receive(:limits_exceeded?).and_return(false) + expect(subject.payment_allowed?).to be_truthy + end end end end