diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index 7a1f7ff3..9a861bbe 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -57,13 +57,12 @@ class CampaignsController < ApplicationController if !params[:campaign][:parent_campaign_id] campaign = current_nonprofit.campaigns.create params[:campaign] + json_saved campaign, 'Campaign created! Well done.' else profile_id = params[:campaign][:profile_id] Profile.find(profile_id).update_attributes params[:profile] - campaign = create_peer_to_peer_campaign params[:campaign], profile_id + render json: CreatePeerToPeerCampaign.create(params[:campaign], profile_id) end - - json_saved campaign, 'Campaign created! Well done.' end def update @@ -120,41 +119,10 @@ class CampaignsController < ApplicationController private + # TODO: test if this can be passed by p2p campaign editor def check_nonprofit_status if !current_role?(:super_admin) && !current_nonprofit.published raise ActionController::RoutingError.new('Not Found') end end - - # TODO: refactor - def create_peer_to_peer_campaign(params, profile_id) - parent_campaign = Campaign.find(params[:parent_campaign_id]) - profile = Profile.find(profile_id) - - p2p_params = params.except(:nonprofit_id, :summary,:goal_amount) - p2p_params.merge!(parent_campaign.child_params) - - base_slug = Format::Url.convert_to_slug "#{p2p_params[:name]}-#{profile.name}" - algo = SlugP2pCampaignNamingAlgorithm.new(p2p_params[:nonprofit_id]) - p2p_params[:slug] = algo.create_copy_name(base_slug) - - campaign = Campaign.create(p2p_params) - - # campaign.remote_main_image_url = parent_campaign.main_image_url unless !parent_campaign.main_image rescue AWS::S3::Errors::NoSuchKey - # campaign.remote_background_image_url = parent_campaign.background_image_url unless !parent_campaign.background_image rescue AWS::S3::Errors::NoSuchKey - # campaign.remote_banner_image_url = parent_campaign.background_image_url unless !parent_campaign.background_image rescue AWS::S3::Errors::NoSuchKey - - campaign.published = true - campaign.save - - return campaign unless campaign.errors.empty? - - gift_option_params = [] - parent_campaign.campaign_gift_options.each do |option| - excluded_for_peer_to_peer = %w(id campaign_id created_at updated_at) - campaign.campaign_gift_options.create option.attributes.except(*excluded_for_peer_to_peer) - end - - campaign - end end diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 84c41175..aa88b0a5 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -173,7 +173,7 @@ class Campaign < ActiveRecord::Base excluded_for_peer_to_peer = %w( id created_at updated_at slug profile_id campaign_template_id url total_raised show_recurring_amount external_identifier parent_campaign_id - reason_for_supporting + reason_for_supporting metadata ) excluded_for_peer_to_peer.push(customizable_attributes_list) attributes.except(*excluded_for_peer_to_peer) diff --git a/lib/create/create_peer_to_peer_campaign.rb b/lib/create/create_peer_to_peer_campaign.rb new file mode 100644 index 00000000..b7502c90 --- /dev/null +++ b/lib/create/create_peer_to_peer_campaign.rb @@ -0,0 +1,39 @@ +# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later +module CreatePeerToPeerCampaign + def self.create(campaign_params, profile_id) + begin + parent_campaign = Campaign.find(campaign_params[:parent_campaign_id]) + + rescue ActiveRecord::RecordNotFound + return { errors: { parent_campaign_id: 'not found' } }.as_json + end + + p2p_params = campaign_params.except(:nonprofit_id, :summary,:goal_amount) + p2p_params.merge!(parent_campaign.child_params) + + profile = Profile.find(profile_id) + base_slug = Format::Url.convert_to_slug "#{p2p_params[:name]}-#{profile.name}" + algo = SlugP2pCampaignNamingAlgorithm.new(p2p_params[:nonprofit_id]) + p2p_params[:slug] = algo.create_copy_name(base_slug) + + campaign = Campaign.create(p2p_params) + + # campaign.remote_main_image_url = parent_campaign.main_image_url unless !parent_campaign.main_image rescue AWS::S3::Errors::NoSuchKey + # campaign.remote_background_image_url = parent_campaign.background_image_url unless !parent_campaign.background_image rescue AWS::S3::Errors::NoSuchKey + # campaign.remote_banner_image_url = parent_campaign.background_image_url unless !parent_campaign.background_image rescue AWS::S3::Errors::NoSuchKey + + campaign.published = true + campaign.profile = profile + campaign.save + + return { errors: campaign.errors.messages }.as_json unless campaign.errors.empty? + + gift_option_params = [] + parent_campaign.campaign_gift_options.each do |option| + excluded_for_peer_to_peer = %w(id campaign_id created_at updated_at) + campaign.campaign_gift_options.create option.attributes.except(*excluded_for_peer_to_peer) + end + + campaign.as_json + end +end diff --git a/spec/lib/create/create_peer_to_peer_campaign_spec.rb b/spec/lib/create/create_peer_to_peer_campaign_spec.rb new file mode 100644 index 00000000..fc4a6c04 --- /dev/null +++ b/spec/lib/create/create_peer_to_peer_campaign_spec.rb @@ -0,0 +1,78 @@ +# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later +require 'rails_helper' + +describe CreatePeerToPeerCampaign do + describe '.create' do + let!(:profile) { force_create(:profile, :user => force_create(:user)) } + let!(:parent_campaign) { force_create(:campaign, name: 'Parent campaign') } + + context 'on success' do + it 'returns a hash' do + campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" } + Timecop.freeze(2020, 4, 5) do + result = CreatePeerToPeerCampaign.create(campaign_params, profile.id) + + expect(result).to be_kind_of Hash + end + end + + it 'returns created peer-to-peer campaign' do + campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" } + Timecop.freeze(2020, 4, 5) do + result = CreatePeerToPeerCampaign.create(campaign_params, profile.id) + + expect(result).not_to include 'errors' + expect(result['parent_campaign_id']).to eq parent_campaign.id + expect(result['created_at']).to eq 'Sun, 05 Apr 2020 00:00:00 UTC +00:00' + end + end + + it 'assigns proper slug' do + campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" } + Timecop.freeze(2020, 4, 5) do + result = CreatePeerToPeerCampaign.create(campaign_params, profile.id) + + expect(result).not_to include 'errors' + expect(result['slug']).to eq 'child-campaign_000' + end + end + + it 'saves campaign' do + campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" } + Timecop.freeze(2020, 4, 5) do + expect { CreatePeerToPeerCampaign.create(campaign_params, profile.id) }.to change(Campaign, :count).by 1 + end + end + end + + context 'on failure' do + it "returns an error if parent campaign can't be found" do + campaign_params = {} + Timecop.freeze(2020, 4, 5) do + result = CreatePeerToPeerCampaign.create(campaign_params, profile.id) + + expect(result).to be_kind_of Hash + expect(result['errors']['parent_campaign_id']).to eq 'not found' + end + end + + it 'returns a list of error messages for attribute validation' do + campaign_params = { parent_campaign_id: parent_campaign.id } + Timecop.freeze(2020, 4, 5) do + result = CreatePeerToPeerCampaign.create(campaign_params, profile.id) + + expect(result).to be_kind_of Hash + expect(result).to include 'errors' + expect(result['errors']['goal_amount']).to match ["can't be blank", 'is not a number'] + end + end + + it "doesn't save campaign" do + campaign_params = {} + Timecop.freeze(2020, 4, 5) do + expect { CreatePeerToPeerCampaign.create(campaign_params, profile.id) }.not_to change(Campaign, :count) + end + end + end + end +end