style(format): run rubocop format autocorrect
This commit is contained in:
		
							parent
							
								
									04a5eb039f
								
							
						
					
					
						commit
						f0fd393be4
					
				
					 759 changed files with 14563 additions and 14380 deletions
				
			
		
							
								
								
									
										50
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								Gemfile
									
										
									
									
									
								
							|  | @ -1,14 +1,16 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| source 'https://rubygems.org' | ||||
| 
 | ||||
| ruby '2.5.1' | ||||
| gem 'rake' | ||||
| gem 'rails', '= 5.2.3' | ||||
| gem 'rake' | ||||
| # https://stripe.com/docs/api | ||||
| gem 'stripe' | ||||
| 
 | ||||
| # Compression of assets on heroku | ||||
| # https://github.com/romanbsd/heroku-deflater | ||||
| gem 'heroku-deflater', :group => :production | ||||
| gem 'heroku-deflater', group: :production | ||||
| 
 | ||||
| # json serialization | ||||
| # https://github.com/nesquena/rabl | ||||
|  | @ -16,17 +18,17 @@ gem 'rabl' | |||
| 
 | ||||
| gem 'parallel' | ||||
| 
 | ||||
| gem 'puma' | ||||
| gem 'bootsnap', require: false | ||||
| gem 'rack-timeout' | ||||
| gem 'rack-ssl' | ||||
| gem 'puma' | ||||
| gem 'puma_worker_killer' | ||||
| gem 'rack-ssl' | ||||
| gem 'rack-timeout' | ||||
| 
 | ||||
| gem 'test-unit', '~> 3.0' | ||||
| gem 'hamster' | ||||
| gem 'test-unit', '~> 3.0' | ||||
| 
 | ||||
| gem 'aws-ses' | ||||
| gem 'aws-sdk', '~> 1' | ||||
| gem 'aws-ses' | ||||
| # for blocking ip addressses | ||||
| gem 'rack-attack' | ||||
| 
 | ||||
|  | @ -44,7 +46,6 @@ gem 'qx', path: 'gems/ruby-qx' | |||
| gem 'dalli' | ||||
| gem 'memcachier' | ||||
| 
 | ||||
| 
 | ||||
| gem 'param_validation', path: 'gems/ruby-param-validation' | ||||
| 
 | ||||
| # Print colorized text lol | ||||
|  | @ -89,33 +90,32 @@ gem 'table_print' | |||
| 
 | ||||
| gem 'bunny', '>= 2.6.3' | ||||
| 
 | ||||
| gem 'rails-i18n' | ||||
| gem 'i18n-js' | ||||
| gem 'countries' | ||||
| 
 | ||||
| gem 'i18n-js' | ||||
| gem 'rails-i18n' | ||||
| 
 | ||||
| group :development, :ci do | ||||
|   gem 'traceroute' | ||||
|   gem 'debase' | ||||
|   gem 'ruby-debug-ide' | ||||
|   gem 'traceroute' | ||||
| end | ||||
| 
 | ||||
| group :development, :ci, :test do | ||||
| 	gem 'timecop' | ||||
| 	gem 'pry' | ||||
| 	#gem 'pry-byebug' | ||||
| 	gem 'binding_of_caller' | ||||
|   gem 'rspec' | ||||
| 	gem 'rspec-rails' | ||||
| 	gem 'database_cleaner' | ||||
|   gem 'pry' | ||||
|   gem 'timecop' | ||||
|   # gem 'pry-byebug' | ||||
|   gem 'action_mailer_matchers' | ||||
|   gem 'binding_of_caller' | ||||
|   gem 'database_cleaner' | ||||
|   gem 'dotenv-rails' | ||||
|   gem 'ruby-prof', '0.15.9' | ||||
| 	gem 'stripe-ruby-mock', '~> 2.4.1', :require => 'stripe_mock', git: 'https://github.com/commitchange/stripe-ruby-mock.git', :branch => '2.4.1' | ||||
|   gem 'factory_bot' | ||||
| 	gem 'factory_bot_rails' | ||||
| 	gem 'action_mailer_matchers' | ||||
|   gem 'factory_bot_rails' | ||||
|   gem 'rspec' | ||||
|   gem 'rspec-rails' | ||||
|   gem 'ruby-prof', '0.15.9' | ||||
|   gem 'simplecov', '~> 0.16.1', require: false | ||||
|   gem 'solargraph' | ||||
|   gem 'stripe-ruby-mock', '~> 2.4.1', require: 'stripe_mock', git: 'https://github.com/commitchange/stripe-ruby-mock.git', branch: '2.4.1' | ||||
| end | ||||
| 
 | ||||
| group :test do | ||||
|  | @ -139,6 +139,6 @@ gem 'grape' | |||
| gem 'grape-entity' | ||||
| gem 'grape-swagger' | ||||
| gem 'grape-swagger-entity' | ||||
| gem 'grape_url_validator' | ||||
| gem 'grape_logging' | ||||
| gem 'grape_devise', path: 'gems/grape_devise' | ||||
| gem 'grape_logging' | ||||
| gem 'grape_url_validator' | ||||
|  |  | |||
							
								
								
									
										4
									
								
								Rakefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Rakefile
									
										
									
									
									
								
							|  | @ -1,7 +1,9 @@ | |||
| #!/usr/bin/env rake | ||||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # Add your own tasks in files placed in lib/tasks ending in .rake, | ||||
| # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. | ||||
| 
 | ||||
| require File.expand_path('../config/application', __FILE__) | ||||
| require File.expand_path('config/application', __dir__) | ||||
| 
 | ||||
| Commitchange::Application.load_tasks | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::API < Grape::API | ||||
|   format :json | ||||
|   mount Houdini::V1::API => '/v1' | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,22 +1,24 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| require 'houdini/v1/validations' | ||||
| class Houdini::V1::API < Grape::API | ||||
| 	logger.formatter = GrapeLogging::Formatters::Rails.new | ||||
| 	use GrapeLogging::Middleware::RequestLogger, { logger: logger } | ||||
| 	content_type :json, 'application/json' | ||||
| 	default_format :json | ||||
| 	rescue_from Grape::Exceptions::ValidationErrors do |e| | ||||
| 		output = {errors: e} | ||||
| 		error! output, 400 | ||||
| 	end | ||||
|   logger.formatter = GrapeLogging::Formatters::Rails.new | ||||
|   use GrapeLogging::Middleware::RequestLogger, logger: logger | ||||
|   content_type :json, 'application/json' | ||||
|   default_format :json | ||||
|   rescue_from Grape::Exceptions::ValidationErrors do |e| | ||||
|     output = { errors: e } | ||||
|     error! output, 400 | ||||
|   end | ||||
| 
 | ||||
| 	#include Houdini::V1::Helpers::ApplicationHelper | ||||
| 	mount Houdini::V1::Nonprofit => '/nonprofit' | ||||
| 	# Additional mounts are added via generators above this line | ||||
|   # include Houdini::V1::Helpers::ApplicationHelper | ||||
|   mount Houdini::V1::Nonprofit => '/nonprofit' | ||||
|   # Additional mounts are added via generators above this line | ||||
|   # DON'T REMOVE THIS OR THE PREVIOUS LINES!!! | ||||
| 	uri_for_host = URI.parse(Settings.api_domain&.url || Settings.cdn.url) | ||||
| 	add_swagger_documentation \ | ||||
| 		host: "#{uri_for_host.host}#{uri_for_host.port ? ":#{uri_for_host.port}" : ""}", | ||||
| 		schemes: [uri_for_host.scheme], | ||||
| 		base_path: '/api/v1' | ||||
| end | ||||
|   uri_for_host = URI.parse(Settings.api_domain&.url || Settings.cdn.url) | ||||
|   add_swagger_documentation \ | ||||
|     host: "#{uri_for_host.host}#{uri_for_host.port ? ":#{uri_for_host.port}" : ''}", | ||||
|     schemes: [uri_for_host.scheme], | ||||
|     base_path: '/api/v1' | ||||
| end | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::V1::BaseAPI < Grape::API | ||||
|   #helpers ApplicationHelper | ||||
|   # helpers ApplicationHelper | ||||
|   # helpers do | ||||
|   #   def session | ||||
|   #     env['rack.session'] | ||||
|  | @ -27,4 +29,4 @@ class Houdini::V1::BaseAPI < Grape::API | |||
|   #     allow_forgery_protection.nil? || allow_forgery_protection | ||||
|   #   end | ||||
|   # end | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::V1::Entities::Nonprofit < Grape::Entity | ||||
|   expose :id | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::V1::Entities::ValidationError < Grape::Entity | ||||
|   expose :params, documentation: {type: 'String', desc: 'Params where the following had an error.', is_array: true} | ||||
|   expose :messages, documentation: {type:'String', desc: 'The validation messages for the params', is_array: true} | ||||
| end | ||||
|   expose :params, documentation: { type: 'String', desc: 'Params where the following had an error.', is_array: true } | ||||
|   expose :messages, documentation: { type: 'String', desc: 'The validation messages for the params', is_array: true } | ||||
| end | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::V1::Entities::ValidationErrors < Grape::Entity | ||||
|   expose :errors, documentation: {type: ValidationError, desc: 'errors', is_array:true} | ||||
| end | ||||
|   expose :errors, documentation: { type: ValidationError, desc: 'errors', is_array: true } | ||||
| end | ||||
|  |  | |||
|  | @ -1,22 +1,21 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Houdini::V1::Helpers::ApplicationHelper | ||||
|   extend Grape::API::Helpers | ||||
| 
 | ||||
| 
 | ||||
|   def session | ||||
|         env['rack.session'] | ||||
|     env['rack.session'] | ||||
|   end | ||||
| 
 | ||||
|   def protect_against_forgery | ||||
|     unless verified_request? | ||||
|       error!('Unauthorized', 401) | ||||
|     end | ||||
|     error!('Unauthorized', 401) unless verified_request? | ||||
|   end | ||||
| 
 | ||||
|   def verified_request? | ||||
|     !protect_against_forgery? || request.get? || request.head? || | ||||
|         form_authenticity_token == request.headers['X-CSRF-Token'] || | ||||
|         form_authenticity_token == request.headers['X-Csrf-Token'] | ||||
|       form_authenticity_token == request.headers['X-CSRF-Token'] || | ||||
|       form_authenticity_token == request.headers['X-Csrf-Token'] | ||||
|   end | ||||
| 
 | ||||
|   def form_authenticity_token | ||||
|  | @ -24,11 +23,10 @@ module Houdini::V1::Helpers::ApplicationHelper | |||
|   end | ||||
| 
 | ||||
|   def protect_against_forgery? | ||||
|     allow_forgery_protection =  Rails.configuration.action_controller.allow_forgery_protection | ||||
|     allow_forgery_protection = Rails.configuration.action_controller.allow_forgery_protection | ||||
|     allow_forgery_protection.nil? || allow_forgery_protection | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
|   # def rescue_ar_invalid( *class_to_hash) | ||||
|   #     rescue_with ActiveRecord::RecordInvalid do |error| | ||||
|   #       output = [] | ||||
|  | @ -40,6 +38,4 @@ module Houdini::V1::Helpers::ApplicationHelper | |||
|   # | ||||
|   #     end | ||||
|   # end | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,20 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| module Houdini::V1::Helpers::RescueHelper | ||||
|   require 'active_support/concern' | ||||
| 
 | ||||
|   extend ActiveSupport::Concern | ||||
|   include Grape::DSL::Configuration | ||||
|   module ClassMethods | ||||
|     def rescue_ar_invalid( *class_to_hash) | ||||
|     rescue_with ActiveRecord::RecordInvalid do |error| | ||||
|       output = [] | ||||
|       error.record.errors do |attr,message| | ||||
|         output.push({params: "#{class_to_hash[error.record.class]}['#{attr}']", | ||||
|                      message: message}) | ||||
|     def rescue_ar_invalid(*class_to_hash) | ||||
|       rescue_with ActiveRecord::RecordInvalid do |error| | ||||
|         output = [] | ||||
|         error.record.errors do |attr, message| | ||||
|           output.push(params: "#{class_to_hash[error.record.class]}['#{attr}']", | ||||
|                       message: message) | ||||
|         end | ||||
|         raise Grape::Exceptions::ValidationErrors, output | ||||
|       end | ||||
|       raise Grape::Exceptions::ValidationErrors.new(output) | ||||
| 
 | ||||
|     end | ||||
|   end | ||||
|   end | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,10 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::V1::Nonprofit < Houdini::V1::BaseAPI | ||||
|    helpers Houdini::V1::Helpers::ApplicationHelper, Houdini::V1::Helpers::RescueHelper | ||||
|   helpers Houdini::V1::Helpers::ApplicationHelper, Houdini::V1::Helpers::RescueHelper | ||||
| 
 | ||||
|    before do | ||||
|      protect_against_forgery | ||||
|    end | ||||
|   before do | ||||
|     protect_against_forgery | ||||
|   end | ||||
| 
 | ||||
|   desc 'Return a nonprofit.' do | ||||
|     success Houdini::V1::Entities::Nonprofit | ||||
|  | @ -18,103 +20,92 @@ class Houdini::V1::Nonprofit < Houdini::V1::BaseAPI | |||
|       present np, as: Houdini::V1::Entities::Nonprofit | ||||
|     end | ||||
|   end | ||||
|     | ||||
| 
 | ||||
|   desc 'Register a nonprofit' do | ||||
|     success Houdini::V1::Entities::Nonprofit | ||||
| 
 | ||||
|     #this needs to be a validation an array | ||||
|     failure [{code:400, message:'Validation Errors',  model: Houdini::V1::Entities::ValidationErrors}] | ||||
|     # this needs to be a validation an array | ||||
|     failure [{ code: 400, message: 'Validation Errors', model: Houdini::V1::Entities::ValidationErrors }] | ||||
|   end | ||||
| 
 | ||||
|   params do | ||||
| 
 | ||||
|     requires :nonprofit, type: Hash  do | ||||
|       requires :name, type:String, desc: 'Organization Name', allow_blank: false, documentation: { param_type: 'body' } | ||||
|       optional :website, type:String, desc: 'Organization website URL', allow_blank:true, regexp: URI::regexp, documentation: { param_type: 'body' }, coerce_with: ->(url) { | ||||
|     requires :nonprofit, type: Hash do | ||||
|       requires :name, type: String, desc: 'Organization Name', allow_blank: false, documentation: { param_type: 'body' } | ||||
|       optional :website, type: String, desc: 'Organization website URL', allow_blank: true, regexp: URI::DEFAULT_PARSER.make_regexp, documentation: { param_type: 'body' }, coerce_with: lambda { |url| | ||||
|         coerced_url = url | ||||
|         unless (url =~ /\Ahttp:\/\/.*/i || url =~ /\Ahttps:\/\/.*/i) | ||||
|           coerced_url = 'http://'+ coerced_url | ||||
|         unless url =~ %r{\Ahttp://.*}i || url =~ %r{\Ahttps://.*}i | ||||
|           coerced_url = 'http://' + coerced_url | ||||
|         end | ||||
|         coerced_url | ||||
|       } | ||||
|       requires :zip_code, type:String, allow_blank: false, desc: "Organization Address ZIP Code", documentation: { param_type: 'body' } | ||||
|       requires :state_code, type:String, allow_blank: false, desc: "Organization Address State Code", documentation: { param_type: 'body' } | ||||
|       requires :city, type:String, allow_blank: false, desc: "Organization Address City", documentation: { param_type: 'body' } | ||||
|       optional :email, type:String, desc: 'Organization email (public)', regexp: Email::Regex, documentation: { param_type: 'body' } | ||||
|       optional :phone, type:String, desc: 'Organization phone (public)', documentation: { param_type: 'body' } | ||||
|       requires :zip_code, type: String, allow_blank: false, desc: 'Organization Address ZIP Code', documentation: { param_type: 'body' } | ||||
|       requires :state_code, type: String, allow_blank: false, desc: 'Organization Address State Code', documentation: { param_type: 'body' } | ||||
|       requires :city, type: String, allow_blank: false, desc: 'Organization Address City', documentation: { param_type: 'body' } | ||||
|       optional :email, type: String, desc: 'Organization email (public)', regexp: Email::Regex, documentation: { param_type: 'body' } | ||||
|       optional :phone, type: String, desc: 'Organization phone (public)', documentation: { param_type: 'body' } | ||||
|     end | ||||
| 
 | ||||
|     requires :user, type: Hash do | ||||
|       requires :name, type:String, desc: 'Full name', allow_blank:false, documentation: { param_type: 'body' } | ||||
|       requires :email, type:String, desc: 'Username', allow_blank: false, documentation: { param_type: 'body' } | ||||
|       requires :password, type:String, desc: 'Password', allow_blank: false, is_equal_to: :password_confirmation, documentation: { param_type: 'body' } | ||||
|       requires :password_confirmation, type:String, desc: 'Password confirmation', allow_blank: false, documentation: { param_type: 'body' } | ||||
|       requires :name, type: String, desc: 'Full name', allow_blank: false, documentation: { param_type: 'body' } | ||||
|       requires :email, type: String, desc: 'Username', allow_blank: false, documentation: { param_type: 'body' } | ||||
|       requires :password, type: String, desc: 'Password', allow_blank: false, is_equal_to: :password_confirmation, documentation: { param_type: 'body' } | ||||
|       requires :password_confirmation, type: String, desc: 'Password confirmation', allow_blank: false, documentation: { param_type: 'body' } | ||||
|     end | ||||
| 
 | ||||
| 
 | ||||
|   end | ||||
|   post do | ||||
|     declared_params = declared(params) | ||||
|     np = nil | ||||
|     u = nil | ||||
|     Qx.transaction do | ||||
|       np = Nonprofit.new(OnboardAccounts.set_nonprofit_defaults(declared_params[:nonprofit])) | ||||
| 
 | ||||
|       begin | ||||
|         np = Nonprofit.new(OnboardAccounts.set_nonprofit_defaults(declared_params[:nonprofit])) | ||||
| 
 | ||||
|         begin | ||||
|           np.save! | ||||
|         rescue ActiveRecord::RecordInvalid => e | ||||
|           if (e.record.errors[:slug]) | ||||
|             begin | ||||
|               slug = SlugNonprofitNamingAlgorithm.new(np.state_code_slug, np.city_slug).create_copy_name(np.slug) | ||||
|               np.slug = slug | ||||
|               np.save! | ||||
|             rescue UnableToCreateNameCopyError | ||||
|               raise Grape::Exceptions::ValidationErrors.new(errors:[Grape::Exceptions::Validation.new( | ||||
| 
 | ||||
|                   params: ["nonprofit[name]"], | ||||
|                   message: "has an invalid slug. Contact support for help." | ||||
|               )]) | ||||
|             end | ||||
|           else | ||||
|             raise e | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         u = User.new(declared_params[:user]) | ||||
|         u.save! | ||||
| 
 | ||||
|         role = u.roles.build(host: np, name: 'nonprofit_admin') | ||||
|         role.save! | ||||
| 
 | ||||
|         billing_plan = BillingPlan.find(Settings.default_bp.id) | ||||
|         b_sub = np.build_billing_subscription(billing_plan: billing_plan, status: 'active') | ||||
|         b_sub.save! | ||||
|         np.save! | ||||
|       rescue ActiveRecord::RecordInvalid => e | ||||
|         class_to_name = {Nonprofit => 'nonprofit', User => 'user'} | ||||
|         if class_to_name[e.record.class] | ||||
|           errors = e.record.errors.keys.map {|k| | ||||
| 
 | ||||
|             errors = e.record.errors[k].uniq | ||||
|             errors.map{|error| Grape::Exceptions::Validation.new( | ||||
| 
 | ||||
|                 params: ["#{class_to_name[e.record.class]}[#{k.to_s}]"], | ||||
|                 message: error | ||||
| 
 | ||||
|             )} | ||||
|           } | ||||
| 
 | ||||
|           raise Grape::Exceptions::ValidationErrors.new(errors:errors.flatten) | ||||
|         if e.record.errors[:slug] | ||||
|           begin | ||||
|             slug = SlugNonprofitNamingAlgorithm.new(np.state_code_slug, np.city_slug).create_copy_name(np.slug) | ||||
|             np.slug = slug | ||||
|             np.save! | ||||
|           rescue UnableToCreateNameCopyError | ||||
|             raise Grape::Exceptions::ValidationErrors.new(errors: [Grape::Exceptions::Validation.new( | ||||
|               params: ['nonprofit[name]'], | ||||
|               message: 'has an invalid slug. Contact support for help.' | ||||
|             )]) | ||||
|           end | ||||
|         else | ||||
|           raise e | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|       u = User.new(declared_params[:user]) | ||||
|       u.save! | ||||
| 
 | ||||
|       role = u.roles.build(host: np, name: 'nonprofit_admin') | ||||
|       role.save! | ||||
| 
 | ||||
|       billing_plan = BillingPlan.find(Settings.default_bp.id) | ||||
|       b_sub = np.build_billing_subscription(billing_plan: billing_plan, status: 'active') | ||||
|       b_sub.save! | ||||
|     rescue ActiveRecord::RecordInvalid => e | ||||
|       class_to_name = { Nonprofit => 'nonprofit', User => 'user' } | ||||
|       if class_to_name[e.record.class] | ||||
|         errors = e.record.errors.keys.map do |k| | ||||
|           errors = e.record.errors[k].uniq | ||||
|           errors.map do |error| | ||||
|             Grape::Exceptions::Validation.new( | ||||
|               params: ["#{class_to_name[e.record.class]}[#{k}]"], | ||||
|               message: error | ||||
|             ) | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         raise Grape::Exceptions::ValidationErrors.new(errors: errors.flatten) | ||||
|       else | ||||
|         raise e | ||||
|       end | ||||
|     end | ||||
|     #onboard callback | ||||
|     # onboard callback | ||||
|     present np, with: Houdini::V1::Entities::Nonprofit | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,2 +1,4 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| require 'houdini/v1/validators/is_equal_to' | ||||
| require 'houdini/v1/validators/is_equal_to' | ||||
|  |  | |||
|  | @ -1,8 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Houdini::V1::Validators::IsEqualTo < Grape::Validations::Base | ||||
|   def validate_param!(attr_name, params) | ||||
|     if params[attr_name] != params[@option] | ||||
|       fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name), @scope.full_name(@option)], message: message(:is_equal_to) | ||||
|       raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name), @scope.full_name(@option)], message: message(:is_equal_to) | ||||
|     end | ||||
|   end | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ActivitiesController < ApplicationController | ||||
|   before_action :authenticate_user!, only: [:create] | ||||
| 
 | ||||
| 	before_action :authenticate_user!, only: [:create] | ||||
| 
 | ||||
| 	def create | ||||
| 		json_saved Activity.create(params[:activity]) | ||||
| 	end | ||||
| 
 | ||||
|   def create | ||||
|     json_saved Activity.create(params[:activity]) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,174 +1,178 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ApplicationController < ActionController::Base | ||||
| 	before_action :set_locale, :redirect_to_maintenance | ||||
|   before_action :set_locale, :redirect_to_maintenance | ||||
| 
 | ||||
| 	protect_from_forgery | ||||
|   protect_from_forgery | ||||
| 
 | ||||
| 	helper_method \ | ||||
| 		:current_role?, | ||||
| 		:current_nonprofit_user?, | ||||
| 		:administered_nonprofit, | ||||
|   helper_method \ | ||||
|     :current_role?, | ||||
|     :current_nonprofit_user?, | ||||
|     :administered_nonprofit, | ||||
|     :nonprofit_in_trial?, | ||||
| 		:current_plan_tier #int | ||||
|     :current_plan_tier # int | ||||
| 
 | ||||
| 	def set_locale | ||||
| 		if params[:locale] && Settings.available_locales.include?(params[:locale]) | ||||
| 			I18n.locale = params[:locale] | ||||
| 		else | ||||
| 	  	I18n.locale = Settings.language | ||||
| 		end | ||||
| 	end | ||||
|   def set_locale | ||||
|     if params[:locale] && Settings.available_locales.include?(params[:locale]) | ||||
|       I18n.locale = params[:locale] | ||||
|     else | ||||
|       I18n.locale = Settings.language | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def redirect_to_maintenance | ||||
| 		if (Settings&.maintenance&.maintenance_mode && !current_user) | ||||
| 			unless (self.class == Users::SessionsController && | ||||
| 							((Settings.maintenance.maintenance_token && params[:maintenance_token] == Settings.maintenance.maintenance_token) || params[:format] == 'json')) | ||||
| 				redirect_to Settings.maintenance.maintenance_page | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|   def redirect_to_maintenance | ||||
|     if Settings&.maintenance&.maintenance_mode && !current_user | ||||
|       unless self.class == Users::SessionsController && | ||||
|              ((Settings.maintenance.maintenance_token && params[:maintenance_token] == Settings.maintenance.maintenance_token) || params[:format] == 'json') | ||||
|         redirect_to Settings.maintenance.maintenance_page | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| protected | ||||
|   protected | ||||
| 
 | ||||
| 	def json_saved(model, msg=nil) | ||||
| 		if model.valid? | ||||
| 			flash[:notice] = msg if msg | ||||
| 			render json: model, status: 200 | ||||
| 		else | ||||
| 			render json: model.errors.full_messages, status: :unprocessable_entity | ||||
| 		end | ||||
| 	end | ||||
|   def json_saved(model, msg = nil) | ||||
|     if model.valid? | ||||
|       flash[:notice] = msg if msg | ||||
|       render json: model, status: 200 | ||||
|     else | ||||
|       render json: model.errors.full_messages, status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   # A response helper for use with the param_validation gem | ||||
|   # use like:   render_json{ UpdateUsers.update(params[:user]) } | ||||
|   # will catch and pretty print exceptions using the rails loggers | ||||
|   def render_json(&block) | ||||
|     begin | ||||
|       result = {status: 200, json: yield(block)} | ||||
|       result = { status: 200, json: yield(block) } | ||||
|     rescue ParamValidation::ValidationError => e | ||||
|       logger.info "422: #{e}".red.bold | ||||
|       #logger.info ">>".bold.red + " #{{'Failed key name' => e.data[:key], 'Value' => e.data[:val], 'Failed validator' => e.data[:name]}}".red | ||||
|       result = {status: 422, json: {error: e.message}} | ||||
| 		rescue CCOrgError => e | ||||
| 			logger.info "422: #{e}".red.bold | ||||
| 			result = {status: 422, json: {error: e.message}} | ||||
|       # logger.info ">>".bold.red + " #{{'Failed key name' => e.data[:key], 'Value' => e.data[:val], 'Failed validator' => e.data[:name]}}".red | ||||
|       result = { status: 422, json: { error: e.message } } | ||||
|     rescue CCOrgError => e | ||||
|       logger.info "422: #{e}".red.bold | ||||
|       result = { status: 422, json: { error: e.message } } | ||||
|     rescue ActiveRecord::RecordNotFound => e | ||||
|       logger.info "404: #{e}".red.bold | ||||
|       result = {status: 404, json: {error: e.message}} | ||||
| 		rescue AuthenticationError => e | ||||
| 			logger.info "401: #{e}".red.bold | ||||
| 			result = {status: 401, json: {error: e.message}} | ||||
| 		rescue ExpiredTokenError => e | ||||
| 			logger.info "422: #{e}".red.bold | ||||
| 			result = {status: 422, json: {error: e.message}} | ||||
|       result = { status: 404, json: { error: e.message } } | ||||
|     rescue AuthenticationError => e | ||||
|       logger.info "401: #{e}".red.bold | ||||
|       result = { status: 401, json: { error: e.message } } | ||||
|     rescue ExpiredTokenError => e | ||||
|       logger.info "422: #{e}".red.bold | ||||
|       result = { status: 422, json: { error: e.message } } | ||||
|     rescue Exception => e # a non-validation related exception | ||||
|       logger.error "500: #{e}".red.bold | ||||
|       logger.error e.backtrace.take(5).map{|l| ">>".red.bold + " #{l}"}.join("\n").red | ||||
|       result = {status: 500, json: {error: e.message, backtrace: e.backtrace}} | ||||
|       logger.error e.backtrace.take(5).map { |l| '>>'.red.bold + " #{l}" }.join("\n").red | ||||
|       result = { status: 500, json: { error: e.message, backtrace: e.backtrace } } | ||||
|     end | ||||
|     render result | ||||
|   end | ||||
| 
 | ||||
| 	# Test that within the last 5 minutes, the user has confirmed their password | ||||
| 	def password_was_confirmed(token) | ||||
| 		session[:pw_token] == token && Chronic.parse(session[:pw_timestamp]) >= 5.minutes.ago.utc | ||||
| 	end | ||||
|   # Test that within the last 5 minutes, the user has confirmed their password | ||||
|   def password_was_confirmed(token) | ||||
|     session[:pw_token] == token && Chronic.parse(session[:pw_timestamp]) >= 5.minutes.ago.utc | ||||
|   end | ||||
| 
 | ||||
| 	def store_location | ||||
| 		referrer = request.fullpath | ||||
| 		no_redirects = ['/users', '/signup', '/signin', '/users/sign_in', '/users/sign_up', '/users/password', '/users/sign_out', /.*\.json.*/, /.*auth\/facebook.*/] | ||||
| 		unless request.format.symbol == :json || no_redirects.map{|p| referrer.match(p)}.any? | ||||
| 			session[:previous_url] = referrer | ||||
| 		end | ||||
| 	end | ||||
|   def store_location | ||||
|     referrer = request.fullpath | ||||
|     no_redirects = ['/users', '/signup', '/signin', '/users/sign_in', '/users/sign_up', '/users/password', '/users/sign_out', /.*\.json.*/, %r{.*auth/facebook.*}] | ||||
|     unless request.format.symbol == :json || no_redirects.map { |p| referrer.match(p) }.any? | ||||
|       session[:previous_url] = referrer | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def block_with_sign_in(msg=nil) | ||||
| 		store_location | ||||
|   def block_with_sign_in(msg = nil) | ||||
|     store_location | ||||
|     if current_user | ||||
|       flash[:notice] = "It looks like you're not allowed to access that page. If this seems like a mistake, please contact #{Settings.mailer.email}" | ||||
|       redirect_to root_path | ||||
|     else | ||||
|       msg ||= 'We need to sign you in before you can do that.' | ||||
|       redirect_to new_user_session_path, :flash => {:error => msg} | ||||
|       redirect_to new_user_session_path, flash: { error: msg } | ||||
|     end | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
| 	def authenticate_user!(options={}) | ||||
| 		block_with_sign_in unless current_user | ||||
| 	end | ||||
|   def authenticate_user!(_options = {}) | ||||
|     block_with_sign_in unless current_user | ||||
|   end | ||||
| 
 | ||||
| 	def authenticate_confirmed_user! | ||||
| 		if !current_user | ||||
| 			block_with_sign_in | ||||
| 		elsif !current_user.confirmed? && !current_role?([:super_associate, :super_admin]) | ||||
| 			redirect_to new_user_confirmation_path, flash: {error: 'You need to confirm your account to do that.'} | ||||
| 		end | ||||
| 	end | ||||
|   def authenticate_confirmed_user! | ||||
|     if !current_user | ||||
|       block_with_sign_in | ||||
|     elsif !current_user.confirmed? && !current_role?(%i[super_associate super_admin]) | ||||
|       redirect_to new_user_confirmation_path, flash: { error: 'You need to confirm your account to do that.' } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def authenticate_super_associate! | ||||
| 		unless current_role?(:super_admin) || current_role?(:super_associate) | ||||
| 			block_with_sign_in 'Please login.' | ||||
| 		end | ||||
| 	end | ||||
|   def authenticate_super_associate! | ||||
|     unless current_role?(:super_admin) || current_role?(:super_associate) | ||||
|       block_with_sign_in 'Please login.' | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def authenticate_super_admin! | ||||
| 		unless current_role?(:super_admin) | ||||
| 			block_with_sign_in 'Please login.' | ||||
| 		end | ||||
| 	end | ||||
|   def authenticate_super_admin! | ||||
|     block_with_sign_in 'Please login.' unless current_role?(:super_admin) | ||||
|   end | ||||
| 
 | ||||
| 	def current_role?(role_names, host_id = nil) | ||||
|   def current_role?(role_names, host_id = nil) | ||||
|     return false unless current_user | ||||
|     role_names = Array(role_names) | ||||
| 		key = "current_role_user_#{current_user_id}_names_#{role_names.join("_")}_host_#{host_id}" | ||||
|     QueryRoles.user_has_role?(current_user.id, role_names, host_id) | ||||
| 	end | ||||
| 
 | ||||
|   def nonprofit_in_trial?(npo_id=nil) | ||||
|     role_names = Array(role_names) | ||||
|     key = "current_role_user_#{current_user_id}_names_#{role_names.join('_')}_host_#{host_id}" | ||||
|     QueryRoles.user_has_role?(current_user.id, role_names, host_id) | ||||
|   end | ||||
| 
 | ||||
|   def nonprofit_in_trial?(npo_id = nil) | ||||
|     return false if !npo_id && !administered_nonprofit | ||||
| 
 | ||||
|     npo_id ||= administered_nonprofit.id | ||||
|     key = "in_trial_user_#{current_user_id}_nonprofit_#{npo_id}" | ||||
|     QueryBillingSubscriptions.currently_in_trial?(npo_id) | ||||
|   end | ||||
| 
 | ||||
| 	def current_plan_tier(npo_id=nil) | ||||
|   def current_plan_tier(npo_id = nil) | ||||
|     return 0 if !npo_id && !administered_nonprofit | ||||
| 
 | ||||
|     npo_id ||= administered_nonprofit.id | ||||
| 		return 2 if current_role?(:super_admin) | ||||
| 		key = "plan_tier_user_#{current_user_id}_nonprofit_#{npo_id}" | ||||
|     return 2 if current_role?(:super_admin) | ||||
| 
 | ||||
|     key = "plan_tier_user_#{current_user_id}_nonprofit_#{npo_id}" | ||||
|     administered_nonprofit ? QueryBillingSubscriptions.plan_tier(npo_id) : 0 | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
| 	def administered_nonprofit | ||||
| 		return nil unless current_user | ||||
| 		key = "administered_nonprofit_user_#{current_user_id}_nonprofit" | ||||
|     Nonprofit.where(id: QueryRoles.host_ids(current_user_id, [:nonprofit_admin, :nonprofit_associate])).last | ||||
| 	end | ||||
|   def administered_nonprofit | ||||
|     return nil unless current_user | ||||
| 
 | ||||
| 	# devise config | ||||
|     key = "administered_nonprofit_user_#{current_user_id}_nonprofit" | ||||
|     Nonprofit.where(id: QueryRoles.host_ids(current_user_id, %i[nonprofit_admin nonprofit_associate])).last | ||||
|   end | ||||
| 
 | ||||
| 	def after_sign_in_path_for(resource) | ||||
| 		request.env['omniauth.origin'] || session[:previous_url] || root_path | ||||
| 	end | ||||
|   # devise config | ||||
| 
 | ||||
| 	def after_sign_up_path_for(resource) | ||||
| 		request.env['omniauth.origin'] || session[:previous_url] || root_path | ||||
| 	end | ||||
|   def after_sign_in_path_for(_resource) | ||||
|     request.env['omniauth.origin'] || session[:previous_url] || root_path | ||||
|   end | ||||
| 
 | ||||
| 	def after_update_path_for(resource) | ||||
| 		profile_path(current_user.profile) | ||||
| 	end | ||||
|   def after_sign_up_path_for(_resource) | ||||
|     request.env['omniauth.origin'] || session[:previous_url] || root_path | ||||
|   end | ||||
| 
 | ||||
| 	def after_inactive_sign_up_path_for(resource) | ||||
| 		profile_path(current_user.profile) | ||||
| 	end | ||||
|   def after_update_path_for(_resource) | ||||
|     profile_path(current_user.profile) | ||||
|   end | ||||
| 
 | ||||
| 	# /devise config | ||||
|   def after_inactive_sign_up_path_for(_resource) | ||||
|     profile_path(current_user.profile) | ||||
|   end | ||||
| 
 | ||||
| private | ||||
|   # /devise config | ||||
| 
 | ||||
| 	def current_user_id | ||||
| 		current_user && current_user.id | ||||
| 	end | ||||
|   private | ||||
| 
 | ||||
|   def current_user_id | ||||
|     current_user&.id | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class AwsPresignedPostsController < ApplicationController | ||||
|   before_action :authenticate_user! | ||||
|  | @ -7,12 +9,12 @@ class AwsPresignedPostsController < ApplicationController | |||
|   # http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/PresignedPost.html | ||||
|   def create | ||||
|     uuid = SecureRandom.uuid | ||||
|     p = S3Bucket.presigned_post({ | ||||
|     p = S3Bucket.presigned_post( | ||||
|       key: "tmp/#{uuid}/${filename}", | ||||
|       success_action_status: 201, | ||||
|       acl: 'public-read', | ||||
|       expiration: 30.days.from_now | ||||
|     }) | ||||
|     ) | ||||
| 
 | ||||
|     render json: { | ||||
|       s3_presigned_post: p.fields.to_json, | ||||
|  | @ -20,5 +22,4 @@ class AwsPresignedPostsController < ApplicationController | |||
|       s3_uuid: uuid | ||||
|     } | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,30 +1,32 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class BillingSubscriptionsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_admin! | ||||
|   before_action :authenticate_nonprofit_admin! | ||||
| 
 | ||||
|   def create_trial | ||||
|     render JsonResp.new(params){|params| | ||||
|     render JsonResp.new(params) do |_params| | ||||
|       requires(:nonprofit_id).as_int | ||||
|       requires(:stripe_plan_id).as_string | ||||
|     }.when_valid{|params|  | ||||
|     end.when_valid do |params| | ||||
|       InsertBillingSubscriptions.trial(params[:nonprofit_id], params[:stripe_plan_id]) | ||||
|     } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def create | ||||
|   def create | ||||
|     @nonprofit ||= Nonprofit.find(params[:nonprofit_id]) | ||||
| 		@subscription = BillingSubscription.create_with_stripe(@nonprofit, params[:billing_subscription]) | ||||
| 		json_saved(@subscription, "Success! You are subscribed to #{Settings.general.name}.") | ||||
| 	end | ||||
|     @subscription = BillingSubscription.create_with_stripe(@nonprofit, params[:billing_subscription]) | ||||
|     json_saved(@subscription, "Success! You are subscribed to #{Settings.general.name}.") | ||||
|   end | ||||
| 
 | ||||
|   # post /nonprofits/:nonprofit_id/billing_subscription/cancel | ||||
| 	def cancel | ||||
| 		@result = CancelBillingSubscription.with_stripe(@nonprofit) | ||||
| 		flash[:notice] = "Your subscription has been cancelled. We'll email you soon with exports." | ||||
|   def cancel | ||||
|     @result = CancelBillingSubscription.with_stripe(@nonprofit) | ||||
|     flash[:notice] = "Your subscription has been cancelled. We'll email you soon with exports." | ||||
|     redirect_to root_url | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
|   # get nonprofits/:nonprofit_id/billing_subscription/cancellation | ||||
|   def cancellation | ||||
|  |  | |||
|  | @ -1,12 +1,14 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ButtonDebugController < ApplicationController | ||||
|   def embedded | ||||
|     @np = params[:id] || 1 | ||||
|     respond_to { |format| format.html{render layout: 'layouts/empty'} } | ||||
|     respond_to { |format| format.html { render layout: 'layouts/empty' } } | ||||
|   end | ||||
| 
 | ||||
|   def button | ||||
|     @np = params[:id] || 1 | ||||
|     respond_to { |format| format.html{render layout: 'layouts/empty'} } | ||||
|     respond_to { |format| format.html { render layout: 'layouts/empty' } } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,29 +1,31 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class CampaignGiftOptionsController < ApplicationController | ||||
| 	include Controllers::CampaignHelper | ||||
|   include Controllers::CampaignHelper | ||||
| 
 | ||||
| 	before_action :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order] | ||||
|   before_action :authenticate_campaign_editor!, only: %i[create destroy update update_order] | ||||
| 
 | ||||
| 	def index | ||||
| 		@gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') | ||||
| 		render json: {data: @gift_options} | ||||
| 	end | ||||
|   def index | ||||
|     @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') | ||||
|     render json: { data: @gift_options } | ||||
|   end | ||||
| 
 | ||||
| 	def show | ||||
| 		render json: {data: current_campaign.campaign_gift_options.find(params[:id])} | ||||
| 	end | ||||
|   def show | ||||
|     render json: { data: current_campaign.campaign_gift_options.find(params[:id]) } | ||||
|   end | ||||
| 
 | ||||
| 	def create | ||||
| 		campaign = current_campaign | ||||
| 		json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), | ||||
| 			'Gift option successfully created!' | ||||
| 	end | ||||
|   def create | ||||
|     campaign = current_campaign | ||||
|     json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), | ||||
|                'Gift option successfully created!' | ||||
|   end | ||||
| 
 | ||||
| 	def update | ||||
| 		@campaign = current_campaign | ||||
| 		gift_option = @campaign.campaign_gift_options.find params[:id] | ||||
| 		json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' | ||||
| 	end | ||||
|   def update | ||||
|     @campaign = current_campaign | ||||
|     gift_option = @campaign.campaign_gift_options.find params[:id] | ||||
|     json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' | ||||
|   end | ||||
| 
 | ||||
|   # put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order | ||||
|   # Pass in {data: [{id: 1, order: 1}]} | ||||
|  | @ -32,9 +34,9 @@ class CampaignGiftOptionsController < ApplicationController | |||
|     render json: updated_gift_options | ||||
|   end | ||||
| 
 | ||||
| 	def destroy | ||||
| 		@campaign = current_campaign | ||||
|   def destroy | ||||
|     @campaign = current_campaign | ||||
| 
 | ||||
| 		render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id])} | ||||
| 	end | ||||
|     render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id]) } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class CampaignGiftsController < ApplicationController | ||||
| 
 | ||||
|   # post /campaign_gifts | ||||
| 	def create | ||||
| 		json_saved CreateCampaignGift.create params[:campaign_gift] | ||||
| 	end | ||||
|   def create | ||||
|     json_saved CreateCampaignGift.create params[:campaign_gift] | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,51 +1,51 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Campaigns; class CampaignGiftOptionsController < ApplicationController | ||||
| 	include Controllers::CampaignHelper | ||||
| module Campaigns | ||||
|   class CampaignGiftOptionsController < ApplicationController | ||||
|     include Controllers::CampaignHelper | ||||
| 
 | ||||
| 	before_action :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order, :report] | ||||
|     before_action :authenticate_campaign_editor!, only: %i[create destroy update update_order report] | ||||
| 
 | ||||
| 	def report | ||||
| 		respond_to do |format| | ||||
| 			format.json do | ||||
| 				render json: QueryCampaignGifts.report_metrics(current_campaign.id) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|     def report | ||||
|       respond_to do |format| | ||||
|         format.json do | ||||
|           render json: QueryCampaignGifts.report_metrics(current_campaign.id) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     def index | ||||
|       @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') | ||||
|       render json: { data: @gift_options } | ||||
|     end | ||||
| 
 | ||||
|     def show | ||||
|       render json: { data: current_campaign.campaign_gift_options.find(params[:id]) } | ||||
|     end | ||||
| 
 | ||||
| 	def index | ||||
| 		@gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') | ||||
| 		render json: {data: @gift_options} | ||||
| 	end | ||||
|     def create | ||||
|       campaign = current_campaign | ||||
|       json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), | ||||
|                  'Gift option successfully created!' | ||||
|     end | ||||
| 
 | ||||
| 	def show | ||||
| 		render json: {data: current_campaign.campaign_gift_options.find(params[:id])} | ||||
| 	end | ||||
|     def update | ||||
|       @campaign = current_campaign | ||||
|       gift_option = @campaign.campaign_gift_options.find params[:id] | ||||
|       json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' | ||||
|     end | ||||
| 
 | ||||
| 	def create | ||||
| 		campaign = current_campaign | ||||
| 		json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), | ||||
| 							 'Gift option successfully created!' | ||||
| 	end | ||||
|     # put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order | ||||
|     # Pass in {data: [{id: 1, order: 1}]} | ||||
|     def update_order | ||||
|       updated_gift_options = UpdateOrder.with_data('campaign_gift_options', params[:data]) | ||||
|       render json: updated_gift_options | ||||
|     end | ||||
| 
 | ||||
| 	def update | ||||
| 		@campaign = current_campaign | ||||
| 		gift_option = @campaign.campaign_gift_options.find params[:id] | ||||
| 		json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' | ||||
| 	end | ||||
| 
 | ||||
| 	# put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order | ||||
| 	# Pass in {data: [{id: 1, order: 1}]} | ||||
| 	def update_order | ||||
| 		updated_gift_options = UpdateOrder.with_data('campaign_gift_options', params[:data]) | ||||
| 		render json: updated_gift_options | ||||
| 	end | ||||
| 
 | ||||
| 	def destroy | ||||
| 		@campaign = current_campaign | ||||
| 
 | ||||
| 		render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id])} | ||||
| 	end | ||||
|     def destroy | ||||
|       @campaign = current_campaign | ||||
| 
 | ||||
|       render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id]) } | ||||
|     end | ||||
| end; end | ||||
|  |  | |||
|  | @ -1,19 +1,20 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Campaigns | ||||
| class DonationsController < ApplicationController | ||||
| 	include Controllers::CampaignHelper | ||||
|   class DonationsController < ApplicationController | ||||
|     include Controllers::CampaignHelper | ||||
| 
 | ||||
| 	before_action :authenticate_campaign_editor!, only: [:index] | ||||
| 
 | ||||
| 	def index | ||||
| 		respond_to do |format| | ||||
| 			format.csv do | ||||
| 				file_date = Date.today.strftime("%m-%d-%Y") | ||||
| 				donations = QueryDonations.campaign_export(current_campaign.id) | ||||
| 				send_data(Format::Csv.from_vectors(donations), filename: "campaign-donations-#{file_date}.csv") | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|     before_action :authenticate_campaign_editor!, only: [:index] | ||||
| 
 | ||||
| end | ||||
|     def index | ||||
|       respond_to do |format| | ||||
|         format.csv do | ||||
|           file_date = Date.today.strftime('%m-%d-%Y') | ||||
|           donations = QueryDonations.campaign_export(current_campaign.id) | ||||
|           send_data(Format::Csv.from_vectors(donations), filename: "campaign-donations-#{file_date}.csv") | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,22 +1,23 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Campaigns | ||||
| class SupportersController < ApplicationController | ||||
| 	include Controllers::CampaignHelper | ||||
|   class SupportersController < ApplicationController | ||||
|     include Controllers::CampaignHelper | ||||
| 
 | ||||
| 	before_action :authenticate_campaign_editor!, only: [:index] | ||||
|     before_action :authenticate_campaign_editor!, only: [:index] | ||||
| 
 | ||||
| 	def index | ||||
| 		@panels_layout = true | ||||
| 		@nonprofit = current_nonprofit | ||||
| 		@campaign  = current_campaign | ||||
| 
 | ||||
| 		respond_to do |format| | ||||
| 			format.json do | ||||
| 				render json: QuerySupporters.campaign_list(@nonprofit.id, @campaign.id, params) | ||||
| 			end | ||||
| 			format.html | ||||
| 		end | ||||
| 	end | ||||
|     def index | ||||
|       @panels_layout = true | ||||
|       @nonprofit = current_nonprofit | ||||
|       @campaign  = current_campaign | ||||
| 
 | ||||
| end | ||||
|       respond_to do |format| | ||||
|         format.json do | ||||
|           render json: QuerySupporters.campaign_list(@nonprofit.id, @campaign.id, params) | ||||
|         end | ||||
|         format.html | ||||
|       end | ||||
|     end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,15 +1,17 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class CampaignsController < ApplicationController | ||||
|   include Controllers::CampaignHelper | ||||
| 
 | ||||
|   helper_method :current_campaign_editor? | ||||
|   before_action :authenticate_confirmed_user!, only: [:create, :name_and_id, :duplicate] | ||||
|   before_action :authenticate_campaign_editor!, only: [:update, :soft_delete] | ||||
|   before_action :check_nonprofit_status, only: [:index, :show] | ||||
|   before_action :authenticate_confirmed_user!, only: %i[create name_and_id duplicate] | ||||
|   before_action :authenticate_campaign_editor!, only: %i[update soft_delete] | ||||
|   before_action :check_nonprofit_status, only: %i[index show] | ||||
| 
 | ||||
|   def index | ||||
|     @nonprofit = current_nonprofit | ||||
|     if (current_nonprofit_user?) | ||||
|     if current_nonprofit_user? | ||||
|       @campaigns = @nonprofit.campaigns.includes(:nonprofit).not_deleted.order('created_at desc') | ||||
|       @deleted_campaigns = @nonprofit.campaigns.includes(:nonprofit).deleted.order('created_at desc') | ||||
|     else | ||||
|  | @ -70,14 +72,11 @@ class CampaignsController < ApplicationController | |||
| 
 | ||||
|   # post 'nonprofits/:np_id/campaigns/:campaign_id/duplicate' | ||||
|   def duplicate | ||||
| 
 | ||||
|     render_json { | ||||
|     render_json do | ||||
|       InsertDuplicate.campaign(current_campaign.id, current_user.profile.id) | ||||
|     } | ||||
| 
 | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
|   def soft_delete | ||||
|     current_campaign.update_attribute(:deleted, params[:delete]) | ||||
|     render json: {} | ||||
|  | @ -101,17 +100,17 @@ class CampaignsController < ApplicationController | |||
|   end | ||||
| 
 | ||||
|   def peer_to_peer | ||||
|     session[:donor_signup_url] = request.env["REQUEST_URI"] | ||||
|     session[:donor_signup_url] = request.env['REQUEST_URI'] | ||||
|     @nonprofit = Nonprofit.find_by_id(params[:npo_id]) | ||||
|     @parent_campaign = Campaign.find_by_id(params[:campaign_id]) | ||||
| 
 | ||||
|     if params[:campaign_id].present? && !@parent_campaign | ||||
|       raise ActionController::RoutingError.new('Not Found') | ||||
|       raise ActionController::RoutingError, 'Not Found' | ||||
|     end | ||||
| 
 | ||||
|     if current_user | ||||
|       @profile = current_user.profile | ||||
|       if (@parent_campaign) | ||||
|       if @parent_campaign | ||||
|         @child_campaign = Campaign.where( | ||||
|           profile_id: @profile.id, | ||||
|           parent_campaign_id: @parent_campaign.id | ||||
|  | @ -124,7 +123,7 @@ class CampaignsController < ApplicationController | |||
| 
 | ||||
|   def check_nonprofit_status | ||||
|     if !current_role?(:super_admin) && !current_nonprofit.published | ||||
|       raise ActionController::RoutingError.new('Not Found') | ||||
|       raise ActionController::RoutingError, 'Not Found' | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,22 +1,22 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class CardsController < ApplicationController | ||||
|   before_action :authenticate_user!, except: [:create] | ||||
| 
 | ||||
| 	before_action :authenticate_user!, :except => [:create] | ||||
| 
 | ||||
| 	# post /cards | ||||
| 	def create | ||||
|   # post /cards | ||||
|   def create | ||||
|     acct = Supporter.find(params[:card][:holder_id]).nonprofit.stripe_account_id | ||||
|     render( | ||||
|       JsonResp.new(params) do |d| | ||||
|       JsonResp.new(params) do |_d| | ||||
|         requires(:card).nested do | ||||
|           requires(:name, :stripe_card_token).as_string | ||||
|           requires(:holder_id).as_int | ||||
|           requires(:holder_type).one_of('Supporter') | ||||
|         end | ||||
|       end.when_valid do |d| | ||||
|         InsertCard.with_stripe(d[:card], acct,  params[:event_id], current_user) | ||||
|         InsertCard.with_stripe(d[:card], acct, params[:event_id], current_user) | ||||
|       end | ||||
|     ) | ||||
| 	end | ||||
| 
 | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,19 +1,19 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class DirectDebitDetailsController < ApplicationController | ||||
| 
 | ||||
| 
 | ||||
|   # POST /sepa | ||||
|   # This endpoint is used for saving direct debit account details | ||||
|   # when SEPA payment is selected in the donation widget. Actual charge is | ||||
|   # happening offline, after donations are exported to an external CRM. | ||||
|   def create | ||||
|     render( | ||||
|       JsonResp.new(params) do |data| | ||||
|       JsonResp.new(params) do |_data| | ||||
|         requires(:supporter_id).as_int | ||||
|         requires(:sepa_params).nested do | ||||
|           requires(:iban, :name, :bic).as_string | ||||
|         end | ||||
|       end.when_valid do |data| | ||||
|       end.when_valid do |_data| | ||||
|         InsertDirectDebitDetail.execute(params) | ||||
|       end | ||||
|     ) | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class EmailSettingsController < ApplicationController | ||||
|   include Controllers::NonprofitHelper | ||||
|  | @ -15,6 +17,4 @@ class EmailSettingsController < ApplicationController | |||
|     user = current_role?(:super_admin) ? User.find(params[:user_id]) : current_user | ||||
|     render json: UpdateEmailSettings.save(params[:nonprofit_id], user.id, params[:email_settings]) | ||||
|   end | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class EmailsController < ApplicationController | ||||
| 	before_action :authenticate_user! | ||||
| 
 | ||||
| 	def create | ||||
| 		email = params[:email] | ||||
| 		GenericMailer.delay.generic_mail(email[:from_email], email[:from_name], email[:message], email[:subject], email[:to_email], email[:to_name]) | ||||
| 		render :json => {:notification => 'Email successfully sent'}, :status => :created | ||||
| 	end | ||||
|   before_action :authenticate_user! | ||||
| 
 | ||||
|   def create | ||||
|     email = params[:email] | ||||
|     GenericMailer.delay.generic_mail(email[:from_email], email[:from_name], email[:message], email[:subject], email[:to_email], email[:to_name]) | ||||
|     render json: { notification: 'Email successfully sent' }, status: :created | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,17 +1,19 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class EventDiscountsController < ApplicationController | ||||
|   include Controllers::EventHelper | ||||
| 	before_action :authenticate_event_editor!, :except => [:index] | ||||
|   before_action :authenticate_event_editor!, except: [:index] | ||||
| 
 | ||||
|   def create | ||||
|     params[:event_discount][:event_id] = current_event.id | ||||
| 
 | ||||
|     render JsonResp.new(params[:event_discount]){|data| | ||||
|     render JsonResp.new(params[:event_discount]) do |_data| | ||||
|       requires(:code, :name).as_string | ||||
|       requires(:event_id, :percent).as_int | ||||
|     }.when_valid{|data| | ||||
|     end.when_valid do |data| | ||||
|       { status: 200, json: { event_discount: current_event.event_discounts.create(data) } } | ||||
|     } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def index | ||||
|  | @ -26,15 +28,14 @@ class EventDiscountsController < ApplicationController | |||
|         .returning('*') | ||||
|       ).first | ||||
|     ) | ||||
|     render json: {status: 200, data: discount }  | ||||
|     render json: { status: 200, data: discount } | ||||
|   end | ||||
| 
 | ||||
|   def destroy | ||||
|     Psql.execute( | ||||
|       Qexpr.new.delete_from("event_discounts") | ||||
|         .where("event_discounts.event_id=$id", id: params["event_id"]) | ||||
|         .where("event_discounts.id=$id", id: params["id"]) | ||||
|       Qexpr.new.delete_from('event_discounts') | ||||
|         .where('event_discounts.event_id=$id', id: params['event_id']) | ||||
|         .where('event_discounts.id=$id', id: params['id']) | ||||
|     ) | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,21 +1,22 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class EventsController < ApplicationController | ||||
| 	include Controllers::EventHelper | ||||
|   include Controllers::EventHelper | ||||
| 
 | ||||
| 	helper_method :current_event_editor? | ||||
|   helper_method :current_event_editor? | ||||
|   before_action :authenticate_nonprofit_user!, only: :name_and_id | ||||
| 	before_action :authenticate_event_editor!, only: [:update, :soft_delete, :stats, :create, :duplicate] | ||||
|   before_action :authenticate_event_editor!, only: %i[update soft_delete stats create duplicate] | ||||
| 
 | ||||
| 
 | ||||
| 	def index | ||||
|   def index | ||||
|     @nonprofit = current_nonprofit | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
|   def listings | ||||
|     render json: QueryEventMetrics.for_listings('nonprofit', current_nonprofit.id, params) | ||||
|   end | ||||
| 
 | ||||
| 	def show | ||||
|   def show | ||||
|     @event = params[:event_slug] ? Event.find_by_slug!(params[:event_slug]) : Event.find_by_id!(params[:id]) | ||||
|     @event_background_image = FetchBackgroundImage.with_model(@event) | ||||
|     @nonprofit = @event.nonprofit | ||||
|  | @ -24,10 +25,10 @@ class EventsController < ApplicationController | |||
|       flash[:notice] = "Sorry, we couldn't find that event" | ||||
|       return | ||||
|     end | ||||
| 		@organizer = QueryEventOrganizer.with_event(@event.id) | ||||
| 	end | ||||
|     @organizer = QueryEventOrganizer.with_event(@event.id) | ||||
|   end | ||||
| 
 | ||||
| 	def create | ||||
|   def create | ||||
|     render_json do | ||||
|       Time.use_zone(current_nonprofit.timezone || 'UTC') do | ||||
|         params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present? | ||||
|  | @ -35,22 +36,22 @@ class EventsController < ApplicationController | |||
|       end | ||||
|       flash[:notice] = 'Your draft event has been created! Well done.' | ||||
|       ev = current_nonprofit.events.create(params[:event]) | ||||
|       {url: "/events/#{ev.slug}", event: ev} | ||||
|       { url: "/events/#{ev.slug}", event: ev } | ||||
|     end | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
| 	def update | ||||
|   def update | ||||
|     Time.use_zone(current_nonprofit.timezone || 'UTC') do | ||||
|       params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present? | ||||
|       params[:event][:end_datetime] = Chronic.parse(params[:event][:end_datetime]) if params[:event][:end_datetime].present? | ||||
|     end | ||||
| 		current_event.update_attributes(params[:event]) | ||||
| 		json_saved current_event, 'Successfully updated' | ||||
| 	end | ||||
|     current_event.update_attributes(params[:event]) | ||||
|     json_saved current_event, 'Successfully updated' | ||||
|   end | ||||
| 
 | ||||
|   # post 'nonprofits/:np_id/events/:event_id/duplicate' | ||||
|   def duplicate | ||||
|     render_json { InsertDuplicate.event(current_event.id, current_user.profile.id)} | ||||
|     render_json { InsertDuplicate.event(current_event.id, current_user.profile.id) } | ||||
|   end | ||||
| 
 | ||||
|   def activities | ||||
|  | @ -58,24 +59,22 @@ class EventsController < ApplicationController | |||
|   end | ||||
| 
 | ||||
|   def soft_delete | ||||
| 		current_event.update_attribute(:deleted, params[:delete]) | ||||
| 		render json: {} | ||||
| 	end | ||||
|     current_event.update_attribute(:deleted, params[:delete]) | ||||
|     render json: {} | ||||
|    end | ||||
| 
 | ||||
| 	def metrics | ||||
|   def metrics | ||||
|     render json: QueryEventMetrics.with_event_ids([current_event.id]).first | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
| 	def stats | ||||
| 		@event = current_event | ||||
| 		@url = Format::Url.concat(root_url, @event.url) | ||||
| 		@event_background_image = FetchBackgroundImage.with_model(@event) | ||||
| 		render layout: 'layouts/embed' | ||||
| 	end | ||||
|   def stats | ||||
|     @event = current_event | ||||
|     @url = Format::Url.concat(root_url, @event.url) | ||||
|     @event_background_image = FetchBackgroundImage.with_model(@event) | ||||
|     render layout: 'layouts/embed' | ||||
|   end | ||||
| 
 | ||||
|   def name_and_id | ||||
|     render json: QueryEvents.name_and_id(current_nonprofit.id) | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,14 +1,16 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class FrontController < ApplicationController | ||||
|   def index | ||||
| 		if !Nonprofit.any? | ||||
| 			redirect_to onboard_path | ||||
| 		elsif current_role?([:nonprofit_admin,:nonprofit_associate]) | ||||
| 			redirect_to NonprofitPath.dashboard(administered_nonprofit) | ||||
| 		elsif current_user | ||||
| 			redirect_to '/profiles/' + current_user.profile.id.to_s | ||||
| 		else | ||||
| 			redirect_to new_user_session_path | ||||
| 		end | ||||
| 	end | ||||
|     if Nonprofit.none? | ||||
|       redirect_to onboard_path | ||||
|     elsif current_role?(%i[nonprofit_admin nonprofit_associate]) | ||||
|       redirect_to NonprofitPath.dashboard(administered_nonprofit) | ||||
|     elsif current_user | ||||
|       redirect_to '/profiles/' + current_user.profile.id.to_s | ||||
|     else | ||||
|       redirect_to new_user_session_path | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,24 +1,26 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ImageAttachmentsController < ApplicationController | ||||
| 	before_action :authenticate_confirmed_user! | ||||
| 	def create | ||||
| 		# must return json with a link attr | ||||
| 		# http://editor.froala.com/server-integrations/php-image-upload | ||||
| 		@image = ImageAttachment.new(:file => params[:file]) | ||||
| 		if @image.save | ||||
| 			render :json => {:link => @image.file_url} | ||||
| 		else | ||||
| 			render :json => @image.errors.full_messages, :status => :unprocessable_entity | ||||
| 		end | ||||
| 	end | ||||
|   before_action :authenticate_confirmed_user! | ||||
|   def create | ||||
|     # must return json with a link attr | ||||
|     # http://editor.froala.com/server-integrations/php-image-upload | ||||
|     @image = ImageAttachment.new(file: params[:file]) | ||||
|     if @image.save | ||||
|       render json: { link: @image.file_url } | ||||
|     else | ||||
|       render json: @image.errors.full_messages, status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def remove | ||||
| 		@image = ImageAttachment.select{|img| img.file_url == params[:src]}.first | ||||
| 		if @image | ||||
| 			@image.destroy | ||||
| 			render :json => @image | ||||
| 		else | ||||
| 			render :json => {}, :status => :unprocessable_entity | ||||
| 		end | ||||
| 	end | ||||
|   def remove | ||||
|     @image = ImageAttachment.select { |img| img.file_url == params[:src] }.first | ||||
|     if @image | ||||
|       @image.destroy | ||||
|       render json: @image | ||||
|     else | ||||
|       render json: {}, status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,34 +1,34 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class MapsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_super_associate!, only: :all_supporters | ||||
| 	before_action :authenticate_nonprofit_user!, only: [:all_npo_supporters, :specific_npo_supporters] | ||||
|   before_action :authenticate_super_associate!, only: :all_supporters | ||||
|   before_action :authenticate_nonprofit_user!, only: %i[all_npo_supporters specific_npo_supporters] | ||||
| 
 | ||||
| 	# used on admin/nonprofits_map and front page | ||||
| 	def all_npos | ||||
| 		respond_to do |format| | ||||
| 			format.html { redirect_to :root } | ||||
| 			format.json { @map_data = Nonprofit.where("latitude IS NOT NULL").last(1000) } | ||||
| 		end | ||||
| 	end | ||||
|   # used on admin/nonprofits_map and front page | ||||
|   def all_npos | ||||
|     respond_to do |format| | ||||
|       format.html { redirect_to :root } | ||||
|       format.json { @map_data = Nonprofit.where('latitude IS NOT NULL').last(1000) } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	# used on admin/supporters_map | ||||
| 	def all_supporters | ||||
| 		@map_data = Supporter.where("latitude IS NOT NULL").last(1000) | ||||
| 	end | ||||
| 
 | ||||
| 	# used on npo dashboard  | ||||
| 	def all_npo_supporters | ||||
| 		@map_data =  Nonprofit.find(params['npo_id']).supporters.where("latitude IS NOT NULL").last(100) | ||||
| 	end | ||||
| 
 | ||||
| 	# used on supporter dashboard  | ||||
| 	def specific_npo_supporters | ||||
| 		supporter_ids = params['supporter_ids'].split(",").map { |s| s.to_i } | ||||
| 		supporters = Nonprofit.find(params['npo_id']).supporters.find(supporter_ids).last(500) | ||||
| 		@map_data =  supporters.map{|s| s if s.latitude != ''} | ||||
| 	end | ||||
|   # used on admin/supporters_map | ||||
|   def all_supporters | ||||
|     @map_data = Supporter.where('latitude IS NOT NULL').last(1000) | ||||
|   end | ||||
| 
 | ||||
|   # used on npo dashboard | ||||
|   def all_npo_supporters | ||||
|     @map_data = Nonprofit.find(params['npo_id']).supporters.where('latitude IS NOT NULL').last(100) | ||||
|   end | ||||
| 
 | ||||
|   # used on supporter dashboard | ||||
|   def specific_npo_supporters | ||||
|     supporter_ids = params['supporter_ids'].split(',').map(&:to_i) | ||||
|     supporters = Nonprofit.find(params['npo_id']).supporters.find(supporter_ids).last(500) | ||||
|     @map_data =  supporters.map { |s| s if s.latitude != '' } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class ActivitiesController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|   class ActivitiesController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
|     # get /nonprofits/:nonprofit_id/supporters/:supporter_id/activities | ||||
|     def index | ||||
|       render json: QueryActivities.for_timeline(params[:nonprofit_id], params[:supporter_id]) | ||||
|     end | ||||
| 
 | ||||
| 	end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,64 +1,65 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class BankAccountsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class BankAccountsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_admin! | ||||
|     before_action :authenticate_nonprofit_admin! | ||||
| 
 | ||||
| 	# post /nonprofits/:nonprofit_id/bank_account | ||||
| 	# must pass in the user's password as params[:password] | ||||
| 	def create | ||||
| 		if password_was_confirmed(params[:pw_token]) | ||||
| 			render_json { InsertBankAccount.with_stripe(current_nonprofit, current_user, params[:bank_account]) } | ||||
| 		else | ||||
| 			render json: ["Please confirm your password"], status: :unprocessable_entity | ||||
| 		end | ||||
| 	end | ||||
|     # post /nonprofits/:nonprofit_id/bank_account | ||||
|     # must pass in the user's password as params[:password] | ||||
|     def create | ||||
|       if password_was_confirmed(params[:pw_token]) | ||||
|         render_json { InsertBankAccount.with_stripe(current_nonprofit, current_user, params[:bank_account]) } | ||||
|       else | ||||
|         render json: ['Please confirm your password'], status: :unprocessable_entity | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
| 	# get /nonprofits/:nonprofit_id/bank_account/confirmation | ||||
| 	def confirmation | ||||
| 		@nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
| 		@bank_account = @nonprofit.bank_account | ||||
| 	end | ||||
|     # get /nonprofits/:nonprofit_id/bank_account/confirmation | ||||
|     def confirmation | ||||
|       @nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
|       @bank_account = @nonprofit.bank_account | ||||
|     end | ||||
| 
 | ||||
| 	# post /nonprofits/:nonprofit_id/bank_account/confirmation | ||||
| 	def confirm | ||||
| 		npo = current_nonprofit | ||||
| 		ba = npo.bank_account | ||||
| 		if params[:token] == ba.confirmation_token | ||||
| 			ba.update_attribute(:pending_verification, false) | ||||
| 			flash[:notice] = "Your bank account is now confirmed!" | ||||
| 			redirect_to nonprofits_payouts_path(npo) | ||||
| 		else | ||||
| 			redirect_to(nonprofits_donations_path(npo), {:flash => {:error => "We could not confirm this bank account. Please follow the exact link provided in the confirmation email."}}) | ||||
| 		end | ||||
| 	end | ||||
|     # post /nonprofits/:nonprofit_id/bank_account/confirmation | ||||
|     def confirm | ||||
|       npo = current_nonprofit | ||||
|       ba = npo.bank_account | ||||
|       if params[:token] == ba.confirmation_token | ||||
|         ba.update_attribute(:pending_verification, false) | ||||
|         flash[:notice] = 'Your bank account is now confirmed!' | ||||
|         redirect_to nonprofits_payouts_path(npo) | ||||
|       else | ||||
|         redirect_to(nonprofits_donations_path(npo), flash: { error: 'We could not confirm this bank account. Please follow the exact link provided in the confirmation email.' }) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
| 	# get /nonprofits/:nonprofit_id/bank_account/cancellation | ||||
| 	def cancellation | ||||
| 		@nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
| 		@bank_account = @nonprofit.bank_account | ||||
| 	end | ||||
|     # get /nonprofits/:nonprofit_id/bank_account/cancellation | ||||
|     def cancellation | ||||
|       @nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
|       @bank_account = @nonprofit.bank_account | ||||
|     end | ||||
| 
 | ||||
| 	# post /nonprofits/:nonprofit_id/bank_account/cancel | ||||
| 	def cancel | ||||
| 		npo = current_nonprofit | ||||
| 		ba = npo.bank_account | ||||
| 		if params[:token] == ba.confirmation_token | ||||
| 			ba.destroy | ||||
| 			flash[:notice] = "Your bank account has been removed." | ||||
| 			redirect_to nonprofits_donations_path(npo) | ||||
| 		else | ||||
| 			redirect_to(nonprofits_donations_path(npo), {:flash => {:error => "We could not remove this bank account. Please follow the exact link provided in the email."}}) | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def resend_confirmation | ||||
| 		npo = current_nonprofit | ||||
| 		ba = npo.bank_account | ||||
| 		NonprofitMailer.delay.new_bank_account_notification(ba) if ba.valid? | ||||
| 		respond_to{|format| format.json{render json: {}}} | ||||
| 	end | ||||
|     # post /nonprofits/:nonprofit_id/bank_account/cancel | ||||
|     def cancel | ||||
|       npo = current_nonprofit | ||||
|       ba = npo.bank_account | ||||
|       if params[:token] == ba.confirmation_token | ||||
|         ba.destroy | ||||
|         flash[:notice] = 'Your bank account has been removed.' | ||||
|         redirect_to nonprofits_donations_path(npo) | ||||
|       else | ||||
|         redirect_to(nonprofits_donations_path(npo), flash: { error: 'We could not remove this bank account. Please follow the exact link provided in the email.' }) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
| end | ||||
|     def resend_confirmation | ||||
|       npo = current_nonprofit | ||||
|       ba = npo.bank_account | ||||
|       NonprofitMailer.delay.new_bank_account_notification(ba) if ba.valid? | ||||
|       respond_to { |format| format.json { render json: {} } } | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,28 +1,27 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class ButtonController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class ButtonController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
|     before_action :authenticate_user! | ||||
| 
 | ||||
| 	before_action :authenticate_user! | ||||
|     def send_code | ||||
|       NonprofitMailer.button_code(current_nonprofit, params[:to_email], params[:to_name], params[:from_email], params[:message], params[:code]).deliver | ||||
|       render json: {}, status: 200 | ||||
|   end | ||||
| 
 | ||||
|     def basic | ||||
|       @nonprofit = current_nonprofit | ||||
|     end | ||||
| 
 | ||||
| 	def send_code | ||||
| 		NonprofitMailer.button_code(current_nonprofit, params[:to_email], params[:to_name], params[:from_email], params[:message], params[:code]).deliver | ||||
| 		render json: {}, status: 200 | ||||
| 	end | ||||
|     def guided | ||||
|       @nonprofit = current_nonprofit | ||||
|     end | ||||
| 
 | ||||
| 	def basic | ||||
| 		@nonprofit = current_nonprofit | ||||
| 	end | ||||
| 
 | ||||
| 	def guided | ||||
| 		@nonprofit = current_nonprofit | ||||
| 	end | ||||
| 
 | ||||
| 	def advanced | ||||
| 		@nonprofit = current_nonprofit | ||||
| 	end | ||||
| 	 | ||||
| end | ||||
|     def advanced | ||||
|       @nonprofit = current_nonprofit | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,9 +1,11 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class CardsController < ApplicationController | ||||
|   class CardsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
|     def edit | ||||
|       @nonprofit = current_nonprofit | ||||
|  | @ -12,7 +14,7 @@ module Nonprofits | |||
|     # POST /nonprofits/:nonprofit_id/card | ||||
|     def create | ||||
|       render( | ||||
|         JsonResp.new(params) do |d| | ||||
|         JsonResp.new(params) do |_d| | ||||
|           requires(:nonprofit_id).as_int | ||||
|           requires(:card).nested do | ||||
|             requires(:name, :stripe_card_token, :stripe_card_id).as_string | ||||
|  | @ -25,6 +27,5 @@ module Nonprofits | |||
|         end | ||||
|       ) | ||||
|     end | ||||
| 
 | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,14 +1,15 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class ChargesController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
|   class ChargesController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 		before_action :authenticate_nonprofit_user!, only: :index | ||||
|     before_action :authenticate_nonprofit_user!, only: :index | ||||
| 
 | ||||
| 		# get /nonprofit/:nonprofit_id/charges | ||||
| 		def index | ||||
| 			redirect_to controller: :payments, action: :index | ||||
| 		end # def index | ||||
| 
 | ||||
| 	end | ||||
|     # get /nonprofit/:nonprofit_id/charges | ||||
|     def index | ||||
|       redirect_to controller: :payments, action: :index | ||||
|     end # def index | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,41 +1,39 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class CustomFieldJoinsController < ApplicationController | ||||
|   class CustomFieldJoinsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
| 		include Controllers::NonprofitHelper | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|     def index | ||||
|       @custom_field_joins = current_nonprofit | ||||
|                             .supporters.find(params[:supporter_id]) | ||||
|                             .custom_field_joins | ||||
|                             .order('created_at DESC') | ||||
|     end | ||||
| 
 | ||||
| 		def index | ||||
| 			@custom_field_joins = current_nonprofit | ||||
| 				.supporters.find(params[:supporter_id]) | ||||
| 				.custom_field_joins | ||||
| 				.order('created_at DESC') | ||||
| 		end | ||||
|     # used for modify a single supporter's custom fields or a group of | ||||
|     # selected supporters' CFs or all supporters' CFs | ||||
|     def modify | ||||
|       if params[:custom_fields].blank? || params[:custom_fields].empty? | ||||
|         render json: {} | ||||
|         return | ||||
|       end | ||||
| 
 | ||||
| 		# used for modify a single supporter's custom fields or a group of  | ||||
| 		# selected supporters' CFs or all supporters' CFs | ||||
| 		def modify | ||||
| 			if params[:custom_fields].blank? || params[:custom_fields].empty? | ||||
| 				render json: {} | ||||
| 				return | ||||
| 			end | ||||
| 			 | ||||
| 			if params[:selecting_all] | ||||
| 				supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select("supporters.id").execute.map{|h| h['id']} | ||||
| 			else | ||||
| 				supporter_ids = params[:supporter_ids]. map(&:to_i) | ||||
| 			end | ||||
|       if params[:selecting_all] | ||||
|         supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select('supporters.id').execute.map { |h| h['id'] } | ||||
|       else | ||||
|         supporter_ids = params[:supporter_ids]. map(&:to_i) | ||||
|       end | ||||
| 
 | ||||
| 			render InsertCustomFieldJoins.in_bulk(current_nonprofit.id, supporter_ids, params[:custom_fields]) | ||||
| 		end | ||||
|       render InsertCustomFieldJoins.in_bulk(current_nonprofit.id, supporter_ids, params[:custom_fields]) | ||||
|     end | ||||
| 
 | ||||
| 
 | ||||
| 		def destroy | ||||
| 			supporter = current_nonprofit.supporters.find(params[:supporter_id]) | ||||
| 			supporter.custom_field_joins.find(params[:id]).destroy | ||||
| 			render json: {}, status: :ok | ||||
| 		end | ||||
| 
 | ||||
| 	end | ||||
|     def destroy | ||||
|       supporter = current_nonprofit.supporters.find(params[:supporter_id]) | ||||
|       supporter.custom_field_joins.find(params[:id]).destroy | ||||
|       render json: {}, status: :ok | ||||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,27 +1,27 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class CustomFieldMastersController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|   class CustomFieldMastersController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
| 		def index | ||||
| 			@custom_field_masters = current_nonprofit | ||||
| 				.custom_field_masters | ||||
| 				.order('id DESC') | ||||
| 				.not_deleted | ||||
| 		end | ||||
|     def index | ||||
|       @custom_field_masters = current_nonprofit | ||||
|                               .custom_field_masters | ||||
|                               .order('id DESC') | ||||
|                               .not_deleted | ||||
|     end | ||||
| 
 | ||||
| 		def create | ||||
| 			json_saved CreateCustomFieldMaster.create(current_nonprofit, params[:custom_field_master]) | ||||
| 		end | ||||
|     def create | ||||
|       json_saved CreateCustomFieldMaster.create(current_nonprofit, params[:custom_field_master]) | ||||
|     end | ||||
| 
 | ||||
| 		def destroy | ||||
| 			custom_field_master = current_nonprofit.custom_field_masters.find(params[:id]) | ||||
| 			custom_field_master.update_attribute(:deleted, true) | ||||
| 			custom_field_master.custom_field_joins.destroy_all | ||||
| 			render json: {}, status: :ok | ||||
| 		end | ||||
| 
 | ||||
| 	end | ||||
|     def destroy | ||||
|       custom_field_master = current_nonprofit.custom_field_masters.find(params[:id]) | ||||
|       custom_field_master.update_attribute(:deleted, true) | ||||
|       custom_field_master.custom_field_joins.destroy_all | ||||
|       render json: {}, status: :ok | ||||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,84 +1,83 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class DonationsController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
|   class DonationsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 		before_action :authenticate_nonprofit_user!, only: [:index, :update] | ||||
| 		before_action :authenticate_campaign_editor!, only: [:create_offsite] | ||||
|     before_action :authenticate_nonprofit_user!, only: %i[index update] | ||||
|     before_action :authenticate_campaign_editor!, only: [:create_offsite] | ||||
| 
 | ||||
| 		# get /nonprofit/:nonprofit_id/donations | ||||
| 		def index | ||||
| 			redirect_to controller: :payments, action: :index | ||||
| 		end # def index | ||||
|     # get /nonprofit/:nonprofit_id/donations | ||||
|     def index | ||||
|       redirect_to controller: :payments, action: :index | ||||
|     end # def index | ||||
| 
 | ||||
| 		# post /nonprofits/:nonprofit_id/donations | ||||
| 		def create | ||||
|     # post /nonprofits/:nonprofit_id/donations | ||||
|     def create | ||||
|       if params[:token] | ||||
|         params[:donation][:token] = params[:token] | ||||
|         render_json { InsertDonation.with_stripe(params[:donation], current_user) } | ||||
|       elsif params[:direct_debit_detail_id] | ||||
|         render JsonResp.new(params[:donation]) do |_data| | ||||
|           requires(:amount).as_int | ||||
|           requires(:supporter_id, :nonprofit_id) | ||||
|           # TODO | ||||
|           # requires_either(:card_id, :direct_debit_detail_id).as_int | ||||
|           optional(:dedication, :designation).as_string | ||||
|           optional(:campaign_id, :event_id).as_int | ||||
|         end.when_valid do |data| | ||||
| 
 | ||||
| 		if params[:token] | ||||
| 					params[:donation][:token] = params[:token] | ||||
| 			return render_json{ InsertDonation.with_stripe(params[:donation], current_user) } | ||||
| 		elsif params[:direct_debit_detail_id] | ||||
| 				render JsonResp.new(params[:donation]){|data| | ||||
| 					requires(:amount).as_int | ||||
| 					requires(:supporter_id, :nonprofit_id) | ||||
| 					# TODO | ||||
| 					# requires_either(:card_id, :direct_debit_detail_id).as_int | ||||
| 					optional(:dedication, :designation).as_string | ||||
| 					optional(:campaign_id, :event_id).as_int | ||||
| 				}.when_valid{|data| | ||||
|           InsertDonation.with_sepa(data) | ||||
|         end | ||||
|         end | ||||
|     end | ||||
| 
 | ||||
| 
 | ||||
| 						InsertDonation.with_sepa(data) | ||||
| 
 | ||||
| 				} | ||||
| 			end | ||||
| 		end | ||||
| 
 | ||||
| 		# post /nonprofits/:nonprofit_id/donations/create_offsite | ||||
| 		def create_offsite | ||||
|       render JsonResp.new(params[:donation]){|data| | ||||
|     # post /nonprofits/:nonprofit_id/donations/create_offsite | ||||
|     def create_offsite | ||||
|       render JsonResp.new(params[:donation]) do |_data| | ||||
|         requires(:amount).as_int.min(1) | ||||
|         requires(:supporter_id, :nonprofit_id).as_int | ||||
|         optional(:dedication, :designation).as_string | ||||
|         optional(:campaign_id, :event_id).as_int | ||||
|         optional(:date).as_date | ||||
|         optional(:offsite_payment).nested{ | ||||
|         optional(:offsite_payment).nested do | ||||
|           optional(:kind).one_of('cash', 'check') | ||||
|           optional(:check_number) | ||||
|         } | ||||
|       }.when_valid{|data| InsertDonation.offsite(data)} | ||||
| 		end | ||||
|         end | ||||
|       end.when_valid { |data| InsertDonation.offsite(data) } | ||||
|     end | ||||
| 
 | ||||
| 		def update | ||||
|       render_json{ UpdateDonation.update_payment(params[:id], params[:donation]) } | ||||
| 		end | ||||
|     def update | ||||
|       render_json { UpdateDonation.update_payment(params[:id], params[:donation]) } | ||||
|     end | ||||
| 
 | ||||
| 		# put /nonprofits/:nonprofit_id/donations/:id | ||||
| 		# update designation, dedication, or comment on a donation in the followup | ||||
| 		def followup | ||||
| 			nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
| 			donation = nonprofit.donations.find(params[:id]) | ||||
| 			json_saved UpdateDonation.from_followup(donation, params[:donation]) | ||||
| 		end | ||||
|     # put /nonprofits/:nonprofit_id/donations/:id | ||||
|     # update designation, dedication, or comment on a donation in the followup | ||||
|     def followup | ||||
|       nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
|       donation = nonprofit.donations.find(params[:id]) | ||||
|       json_saved UpdateDonation.from_followup(donation, params[:donation]) | ||||
|     end | ||||
| 
 | ||||
| 		# this is a special, weird case | ||||
| 		private | ||||
|     # this is a special, weird case | ||||
|     private | ||||
| 
 | ||||
| 		def current_campaign | ||||
| 			if !@campaign && params[:donation] && params[:donation][:campaign_id] | ||||
| 				@campaign = Campaign.where('id = ? ', params[:donation][:campaign_id]).first | ||||
| 			end | ||||
| 			return @campaign | ||||
| 		end | ||||
|     def current_campaign | ||||
|       if !@campaign && params[:donation] && params[:donation][:campaign_id] | ||||
|         @campaign = Campaign.where('id = ? ', params[:donation][:campaign_id]).first | ||||
|       end | ||||
|       @campaign | ||||
|     end | ||||
| 
 | ||||
| 		def current_campaign_editor? | ||||
| 			!params[:preview] && (current_nonprofit_user? || (current_campaign && current_role?(:campaign_editor, current_campaign.id)) || current_role?(:super_admin)) | ||||
| 		end | ||||
|     def current_campaign_editor? | ||||
|       !params[:preview] && (current_nonprofit_user? || (current_campaign && current_role?(:campaign_editor, current_campaign.id)) || current_role?(:super_admin)) | ||||
|     end | ||||
| 
 | ||||
| 		def authenticate_campaign_editor! | ||||
| 			unless current_campaign_editor? | ||||
| 				block_with_sign_in 'You need to be a campaign editor to do that.' | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|     def authenticate_campaign_editor! | ||||
|       unless current_campaign_editor? | ||||
|         block_with_sign_in 'You need to be a campaign editor to do that.' | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,17 +1,19 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class EmailListsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class EmailListsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
|   before_action :authenticate_nonprofit_user! | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
|   def index | ||||
|     render_json{ Qx.fetch(:email_lists, nonprofit_id: params[:nonprofit_id]) } | ||||
|   end | ||||
|     def index | ||||
|       render_json { Qx.fetch(:email_lists, nonprofit_id: params[:nonprofit_id]) } | ||||
|     end | ||||
| 
 | ||||
|   def create | ||||
|     tag_master_ids = params['tag_masters'].values.map(&:to_i) | ||||
|     render_json{ InsertEmailLists.for_mailchimp(params[:nonprofit_id], tag_master_ids) } | ||||
|     def create | ||||
|       tag_master_ids = params['tag_masters'].values.map(&:to_i) | ||||
|       render_json { InsertEmailLists.for_mailchimp(params[:nonprofit_id], tag_master_ids) } | ||||
|     end | ||||
|   end | ||||
| end | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
|   class ImportsController < ApplicationController | ||||
|  | @ -6,15 +8,15 @@ module Nonprofits | |||
|     before_action :authenticate_nonprofit_user! | ||||
|     # post /nonprofits/:nonprofit_id/imports | ||||
|     def create | ||||
|       render_json{ | ||||
|         InsertImport.delay.from_csv_safe({ | ||||
|       render_json do | ||||
|         InsertImport.delay.from_csv_safe( | ||||
|           nonprofit_id: params[:nonprofit_id], | ||||
|           user_id: current_user.id, | ||||
|           user_email: current_user.email, | ||||
|           file_uri: params[:file_uri], | ||||
|           header_matches: params[:header_matches] | ||||
|         }) | ||||
|       } | ||||
|         ) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
|   class MiscellaneousNpInfosController < ApplicationController | ||||
|  | @ -12,18 +14,17 @@ module Nonprofits | |||
|           render_json { FetchMiscellaneousNpInfo.fetch(params[:nonprofit_id]) } | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|     end | ||||
| 
 | ||||
|     def update | ||||
|       respond_to do |format| | ||||
|         format.json { | ||||
|           render_json { | ||||
|         format.json do | ||||
|           render_json do | ||||
|             update = UpdateMiscellaneousNpInfo.update(params[:nonprofit_id], params[:miscellaneous_np_info]) | ||||
|             #flash[:notice] = "Your Miscellaneous Settings have been saved" | ||||
|             # flash[:notice] = "Your Miscellaneous Settings have been saved" | ||||
|             update | ||||
|           } | ||||
|         } | ||||
|           end | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -1,38 +1,39 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| 
 | ||||
| module Nonprofits | ||||
| class NonprofitKeysController < ApplicationController | ||||
|   include Controllers::NonprofitHelper | ||||
|   before_action :authenticate_nonprofit_user! | ||||
|   class NonprofitKeysController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
|   # get /nonprofits/:nonprofit_id/nonprofit_keys | ||||
|   # pass in the :select query param, which is the name of the column of the specific token you want | ||||
|   def index | ||||
|     render_json{QueryNonprofitKeys.get_key(current_nonprofit.id, params[:select])} | ||||
|   end | ||||
| 
 | ||||
|   # Redirects to the mailchimp OAuth2 landing page, first setting the nonprofit id in the session | ||||
|   # GET /nonprofits/:nonprofit_id/nonprofit_keys/mailchimp_login | ||||
|   def mailchimp_login | ||||
|     session[:current_mailchimp_nonprofit_id] = current_nonprofit.id | ||||
|     redirect_to "https://login.mailchimp.com/oauth2/authorize?response_type=code&client_id=#{ENV['MAILCHIMP_OAUTH_CLIENT_ID']}" | ||||
|   end | ||||
| 
 | ||||
|   # After the user OAuths mailchimp, they are redirected to /mailchimp-landing | ||||
|   # This action then redirects them back to /settings | ||||
|   # GET /mailchimp-landing | ||||
|   def mailchimp_landing | ||||
|     @nonprofit = Nonprofit.find(session[:current_mailchimp_nonprofit_id]) | ||||
|     session.delete(:current_mailchimp_nonprofit_id) | ||||
|     begin | ||||
|       session[:mailchimp_access_token] = InsertNonprofitKeys.insert_mailchimp_access_token(@nonprofit.id, params[:code]) | ||||
|     rescue Exception => e | ||||
|       flash[:notice] = "Unable to connect to your Mailchimp account, please try again. (Error: #{e})" | ||||
|       redirect_to '/settings' | ||||
|       return | ||||
|     # get /nonprofits/:nonprofit_id/nonprofit_keys | ||||
|     # pass in the :select query param, which is the name of the column of the specific token you want | ||||
|     def index | ||||
|       render_json { QueryNonprofitKeys.get_key(current_nonprofit.id, params[:select]) } | ||||
|     end | ||||
|     redirect_to nonprofits_supporters_path @nonprofit, 'show-modal' => 'mailchimpSettingsModal' | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|     # Redirects to the mailchimp OAuth2 landing page, first setting the nonprofit id in the session | ||||
|     # GET /nonprofits/:nonprofit_id/nonprofit_keys/mailchimp_login | ||||
|     def mailchimp_login | ||||
|       session[:current_mailchimp_nonprofit_id] = current_nonprofit.id | ||||
|       redirect_to "https://login.mailchimp.com/oauth2/authorize?response_type=code&client_id=#{ENV['MAILCHIMP_OAUTH_CLIENT_ID']}" | ||||
|     end | ||||
| 
 | ||||
|     # After the user OAuths mailchimp, they are redirected to /mailchimp-landing | ||||
|     # This action then redirects them back to /settings | ||||
|     # GET /mailchimp-landing | ||||
|     def mailchimp_landing | ||||
|       @nonprofit = Nonprofit.find(session[:current_mailchimp_nonprofit_id]) | ||||
|       session.delete(:current_mailchimp_nonprofit_id) | ||||
|       begin | ||||
|         session[:mailchimp_access_token] = InsertNonprofitKeys.insert_mailchimp_access_token(@nonprofit.id, params[:code]) | ||||
|       rescue Exception => e | ||||
|         flash[:notice] = "Unable to connect to your Mailchimp account, please try again. (Error: #{e})" | ||||
|         redirect_to '/settings' | ||||
|         return | ||||
|       end | ||||
|       redirect_to nonprofits_supporters_path @nonprofit, 'show-modal' => 'mailchimpSettingsModal' | ||||
|     end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,32 +1,33 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class PaymentsController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
|   class PaymentsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
| 
 | ||||
| 		# get /nonprofit/:nonprofit_id/payments | ||||
| 		def index | ||||
| 			@nonprofit = current_nonprofit | ||||
| 			respond_to do |format| | ||||
| 				format.html do | ||||
|     # get /nonprofit/:nonprofit_id/payments | ||||
|     def index | ||||
|       @nonprofit = current_nonprofit | ||||
|       respond_to do |format| | ||||
|         format.html do | ||||
|           @panels_layout = true | ||||
|         end | ||||
| 
 | ||||
| 				format.json do | ||||
| 					@response = QueryPayments.full_search(params[:nonprofit_id], params) | ||||
|         format.json do | ||||
|           @response = QueryPayments.full_search(params[:nonprofit_id], params) | ||||
|           render json: @response, status: :ok | ||||
| 				end | ||||
| 			end | ||||
| 		end # def index | ||||
|         end | ||||
|       end | ||||
|     end # def index | ||||
| 
 | ||||
|     def export | ||||
|       begin | ||||
|         @nonprofit = current_nonprofit | ||||
|         @user = current_user_id | ||||
|         ExportPayments::initiate_export(@nonprofit.id, params, @user) | ||||
|       rescue => e | ||||
|         ExportPayments.initiate_export(@nonprofit.id, params, @user) | ||||
|       rescue StandardError => e | ||||
|         e | ||||
|       end | ||||
|       if e.nil? | ||||
|  | @ -37,10 +38,10 @@ module Nonprofits | |||
|       end | ||||
|     end | ||||
| 
 | ||||
| 		def show | ||||
| 			@nonprofit = current_nonprofit | ||||
| 			@payment = @nonprofit.payments.find(params[:id]) | ||||
| 		end # def show | ||||
|     def show | ||||
|       @nonprofit = current_nonprofit | ||||
|       @payment = @nonprofit.payments.find(params[:id]) | ||||
|     end # def show | ||||
| 
 | ||||
|     def update | ||||
|       @payment = current_nonprofit.payments.find(params[:id]) | ||||
|  | @ -68,11 +69,12 @@ module Nonprofits | |||
|       PaymentMailer.resend_donor_receipt(params[:id]) | ||||
|       render json: {} | ||||
|     end | ||||
| 
 | ||||
|     # post /nonprofits/:nonprofit_id/payments/:id/resend_admin_receipt | ||||
|     # pass user_id of the admin to send to | ||||
|     def resend_admin_receipt | ||||
|       PaymentMailer.resend_admin_receipt(params[:id], current_user.id) | ||||
|       render json: {} | ||||
|     end | ||||
| 	end # class PaymentsController | ||||
|   end # class PaymentsController | ||||
| end # module Nonprofits | ||||
|  |  | |||
|  | @ -1,49 +1,50 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class PayoutsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class PayoutsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_admin!, only: :create | ||||
| 	before_action :authenticate_nonprofit_user!, only: [:index, :show] | ||||
|     before_action :authenticate_nonprofit_admin!, only: :create | ||||
|     before_action :authenticate_nonprofit_user!, only: %i[index show] | ||||
| 
 | ||||
| 	def create | ||||
| 		payout = InsertPayout.with_stripe(current_nonprofit.id, { | ||||
|       stripe_account_id: current_nonprofit.stripe_account_id, | ||||
|       email: current_user.email, | ||||
|       user_ip: current_user.current_sign_in_ip, | ||||
|       bank_name: current_nonprofit.bank_account.name | ||||
|     }, {before_date: params[:before_date]}) | ||||
|     def create | ||||
|       payout = InsertPayout.with_stripe(current_nonprofit.id, { | ||||
|                                           stripe_account_id: current_nonprofit.stripe_account_id, | ||||
|                                           email: current_user.email, | ||||
|                                           user_ip: current_user.current_sign_in_ip, | ||||
|                                           bank_name: current_nonprofit.bank_account.name | ||||
|                                         }, before_date: params[:before_date]) | ||||
| 
 | ||||
| 		if payout['failure_message'].present? | ||||
| 			flash[:notice] = "The payout failed: #{payout['failure_message']}" | ||||
| 			render json: payout, status: :unprocessable_entity | ||||
| 		else | ||||
| 			flash[:notice] = 'We successfully submitted your payout! View status and receipts below.' | ||||
| 			render json: payout, status: :ok | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def index | ||||
| 		@nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
| 		@payouts = @nonprofit.payouts.order('created_at DESC') | ||||
|     balances = QueryPayments.nonprofit_balances(params[:nonprofit_id]) | ||||
| 		@available_total = balances['available_gross'] | ||||
|     @pending_total = balances['pending_gross'] | ||||
| 		@can_make_payouts = @nonprofit.can_make_payouts | ||||
| 	end | ||||
| 
 | ||||
|   # get /nonprofits/:nonprofit_id/payouts/:id | ||||
|   def show | ||||
|     payout = current_nonprofit.payouts.find(params[:id]) | ||||
|     respond_to do |format| | ||||
|       format.json{render json: payout} | ||||
|       format.csv do | ||||
|         payments = QueryPayments.for_payout(params[:nonprofit_id], params[:id]) | ||||
|         filename = "payout-#{payout.created_at.strftime("%m-%d-%Y")}" | ||||
|         send_data(Format::Csv.from_vectors(payments), filename: "#{filename}.csv") | ||||
|       if payout['failure_message'].present? | ||||
|         flash[:notice] = "The payout failed: #{payout['failure_message']}" | ||||
|         render json: payout, status: :unprocessable_entity | ||||
|       else | ||||
|         flash[:notice] = 'We successfully submitted your payout! View status and receipts below.' | ||||
|         render json: payout, status: :ok | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|     def index | ||||
|       @nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
|       @payouts = @nonprofit.payouts.order('created_at DESC') | ||||
|       balances = QueryPayments.nonprofit_balances(params[:nonprofit_id]) | ||||
|       @available_total = balances['available_gross'] | ||||
|       @pending_total = balances['pending_gross'] | ||||
|       @can_make_payouts = @nonprofit.can_make_payouts | ||||
|     end | ||||
| 
 | ||||
|     # get /nonprofits/:nonprofit_id/payouts/:id | ||||
|     def show | ||||
|       payout = current_nonprofit.payouts.find(params[:id]) | ||||
|       respond_to do |format| | ||||
|         format.json { render json: payout } | ||||
|         format.csv do | ||||
|           payments = QueryPayments.for_payout(params[:nonprofit_id], params[:id]) | ||||
|           filename = "payout-#{payout.created_at.strftime('%m-%d-%Y')}" | ||||
|           send_data(Format::Csv.from_vectors(payments), filename: "#{filename}.csv") | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,94 +1,95 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class RecurringDonationsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class RecurringDonationsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_user!, except: [:create] | ||||
|     before_action :authenticate_nonprofit_user!, except: [:create] | ||||
| 
 | ||||
| 	# get /nonprofits/:nonprofit_id/recurring_donations | ||||
| 	def index | ||||
|     @nonprofit = current_nonprofit | ||||
| 		@panels_layout = true | ||||
| 		respond_to do |format| | ||||
| 			format.html | ||||
| 			format.json do | ||||
| 				# set dashboard params include externally active and failed | ||||
| 				#TODO move into javascript | ||||
| 				params[:active] = true | ||||
|     # get /nonprofits/:nonprofit_id/recurring_donations | ||||
|     def index | ||||
|       @nonprofit = current_nonprofit | ||||
|       @panels_layout = true | ||||
|       respond_to do |format| | ||||
|         format.html | ||||
|         format.json do | ||||
|           # set dashboard params include externally active and failed | ||||
|           # TODO move into javascript | ||||
|           params[:active] = true | ||||
| 
 | ||||
|         render json: QueryRecurringDonations.full_list(params[:nonprofit_id], params) | ||||
|           render json: QueryRecurringDonations.full_list(params[:nonprofit_id], params) | ||||
|         end | ||||
|       end | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def export | ||||
| 		begin | ||||
| 			@nonprofit = current_nonprofit | ||||
| 			@user = current_user_id | ||||
| 			#TODO move into javascript | ||||
| 			if params.key?(:active_and_not_failed) | ||||
| 				params.delete(:active) if params.key?(:active) | ||||
| 				params.delete(:failed) if params.key?(:failed) | ||||
| 			end | ||||
| 
 | ||||
| 			[:active_and_not_failed, :active, :failed].each do |k| | ||||
| 				if (params.key?(k)) | ||||
| 					params[k] = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(params[k]) | ||||
| 				end | ||||
| 			end | ||||
| 
 | ||||
| 			params[:root_url] = root_url | ||||
| 
 | ||||
| 			ExportRecurringDonations::initiate_export(@nonprofit.id, params, current_user.id) | ||||
| 		rescue => e | ||||
| 			e | ||||
| 		end | ||||
| 		if e.nil? | ||||
| 			flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." | ||||
| 			render json: {}, status: :ok | ||||
| 		else | ||||
| 			render json: e, status: :ok | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def show | ||||
| 		@recurring_donation = current_recurring_donation | ||||
| 		respond_to {|format| format.json} | ||||
| 	end | ||||
| 
 | ||||
| 	def destroy | ||||
|     UpdateRecurringDonations.cancel(params[:id], current_user.email) | ||||
| 		json_saved current_recurring_donation | ||||
| 	end | ||||
| 
 | ||||
| 	def update | ||||
| 		json_saved UpdateRecurringDonations | ||||
| 			.update(current_recurring_donation, params[:recurring_donation]) | ||||
| 	end | ||||
| 
 | ||||
|   # post /nonprofits/:nonprofit_id/recurring_donations | ||||
|   def create | ||||
|     if params[:recurring_donation][:token] | ||||
|       render_json{ InsertRecurringDonation.with_stripe(params[:recurring_donation]) } | ||||
|     elsif params[:recurring_donation][:direct_debit_detail_id] | ||||
|       render JsonResp.new(params[:recurring_donation]){|data| | ||||
|         requires(:amount).as_int | ||||
|         requires(:supporter_id, :nonprofit_id, :direct_debit_detail_id).as_int | ||||
|         optional(:dedication, :designation).as_string | ||||
|         optional(:campaign_id, :event_id).as_int | ||||
|       }.when_valid{|data| | ||||
|         InsertRecurringDonation.with_sepa(data) | ||||
|       } | ||||
|     else | ||||
|       render json: {}, status: 422 | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| private | ||||
|     def export | ||||
|       begin | ||||
|         @nonprofit = current_nonprofit | ||||
|         @user = current_user_id | ||||
|         # TODO: move into javascript | ||||
|         if params.key?(:active_and_not_failed) | ||||
|           params.delete(:active) if params.key?(:active) | ||||
|           params.delete(:failed) if params.key?(:failed) | ||||
|         end | ||||
| 
 | ||||
| 	def current_recurring_donation | ||||
| 		@recurring_donation ||= current_nonprofit.recurring_donations.find params[:id] | ||||
| 	end | ||||
|         %i[active_and_not_failed active failed].each do |k| | ||||
|           if params.key?(k) | ||||
|             params[k] = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(params[k]) | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
| end | ||||
|         params[:root_url] = root_url | ||||
| 
 | ||||
|         ExportRecurringDonations.initiate_export(@nonprofit.id, params, current_user.id) | ||||
|       rescue StandardError => e | ||||
|         e | ||||
|       end | ||||
|       if e.nil? | ||||
|         flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." | ||||
|         render json: {}, status: :ok | ||||
|       else | ||||
|         render json: e, status: :ok | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     def show | ||||
|       @recurring_donation = current_recurring_donation | ||||
|       respond_to { |format| format.json } | ||||
|     end | ||||
| 
 | ||||
|     def destroy | ||||
|       UpdateRecurringDonations.cancel(params[:id], current_user.email) | ||||
|       json_saved current_recurring_donation | ||||
|     end | ||||
| 
 | ||||
|     def update | ||||
|       json_saved UpdateRecurringDonations | ||||
|         .update(current_recurring_donation, params[:recurring_donation]) | ||||
|     end | ||||
| 
 | ||||
|     # post /nonprofits/:nonprofit_id/recurring_donations | ||||
|     def create | ||||
|       if params[:recurring_donation][:token] | ||||
|         render_json { InsertRecurringDonation.with_stripe(params[:recurring_donation]) } | ||||
|       elsif params[:recurring_donation][:direct_debit_detail_id] | ||||
|         render JsonResp.new(params[:recurring_donation]) do |_data| | ||||
|           requires(:amount).as_int | ||||
|           requires(:supporter_id, :nonprofit_id, :direct_debit_detail_id).as_int | ||||
|           optional(:dedication, :designation).as_string | ||||
|           optional(:campaign_id, :event_id).as_int | ||||
|         end.when_valid do |data| | ||||
|           InsertRecurringDonation.with_sepa(data) | ||||
|         end | ||||
|       else | ||||
|         render json: {}, status: 422 | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|       private | ||||
| 
 | ||||
|     def current_recurring_donation | ||||
|       @recurring_donation ||= current_nonprofit.recurring_donations.find params[:id] | ||||
|     end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,21 +1,22 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class RefundsController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
|   class RefundsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
| 		# post /charges/:charge_id/refunds | ||||
| 		def create | ||||
|       charge = Qx.select("*").from("charges").where(id: params[:charge_id]).execute.first | ||||
| 			params[:refund][:user_id] = current_user.id | ||||
|       render_json{ InsertRefunds.with_stripe(charge, params['refund']) } | ||||
| 		end | ||||
|     # post /charges/:charge_id/refunds | ||||
|     def create | ||||
|       charge = Qx.select('*').from('charges').where(id: params[:charge_id]).execute.first | ||||
|       params[:refund][:user_id] = current_user.id | ||||
|       render_json { InsertRefunds.with_stripe(charge, params['refund']) } | ||||
|     end | ||||
| 
 | ||||
| 		def index | ||||
| 			charge = current_nonprofit.charges.find(params[:charge_id]) | ||||
| 			@refunds = charge.refunds | ||||
| 		end | ||||
| 	end | ||||
|     def index | ||||
|       charge = current_nonprofit.charges.find(params[:charge_id]) | ||||
|       @refunds = charge.refunds | ||||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
|   class ReportsController < ApplicationController | ||||
|  | @ -8,7 +10,7 @@ module Nonprofits | |||
|       respond_to do |format| | ||||
|         format.csv do | ||||
|           filename = "end-of-year-report-#{params[:year]}.csv" | ||||
|           data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], {:year => params[:year]}) | ||||
|           data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], year: params[:year]) | ||||
|           send_data(Format::Csv.from_array(data), filename: filename) | ||||
|         end | ||||
|       end | ||||
|  | @ -18,17 +20,15 @@ module Nonprofits | |||
|       respond_to do |format| | ||||
|         format.csv do | ||||
|           name_description = nil | ||||
|           if (params[:year]) | ||||
|           if params[:year] | ||||
|             name_description = params[:year] | ||||
|           elsif (params[:start]) | ||||
|           elsif params[:start] | ||||
|             name_description = "from-#{params[:start]}" | ||||
|             if (params[:end]) | ||||
|               name_description += "-to-#{params[:end]}" | ||||
|             end | ||||
|             name_description += "-to-#{params[:end]}" if params[:end] | ||||
|           end | ||||
| 
 | ||||
|           filename = "aggregate-report-#{name_description}.csv" | ||||
|           data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], {:year => params[:year], :start => params[:start], :end => params[:end]}) | ||||
|           data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], year: params[:year], start: params[:start], end: params[:end]) | ||||
|           send_data(Format::Csv.from_array(data), filename: filename) | ||||
|         end | ||||
|       end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
|   class SupporterEmailsController < ApplicationController | ||||
|  | @ -7,19 +9,19 @@ module Nonprofits | |||
|     def create | ||||
|       if params[:selecting_all] | ||||
|         ids = QuerySupporters.full_filter_expr(params[:nonprofit_id], params[:query]) | ||||
|           .select("supporters.id") | ||||
|           .execute(format: 'csv')[1..-1].flatten | ||||
|                              .select('supporters.id') | ||||
|                              .execute(format: 'csv')[1..-1].flatten | ||||
|       elsif params[:supporter_ids] | ||||
|         ids = params[:supporter_ids] | ||||
|       end | ||||
| 
 | ||||
|       if ids.nil? || ids.empty? | ||||
|         render json: {errors: 'Supporters not found'}, status: :unprocessable_entity | ||||
|         render json: { errors: 'Supporters not found' }, status: :unprocessable_entity | ||||
|         return | ||||
|       end | ||||
| 
 | ||||
|       DelayedJobHelper.enqueue_job(EmailSupporters, :deliver, [ids, params[:supporter_email]]) | ||||
|       render json: {count: ids.count}, status: :ok  | ||||
|       render json: { count: ids.count }, status: :ok | ||||
|     end | ||||
| 
 | ||||
|     def gmail | ||||
|  | @ -29,4 +31,3 @@ module Nonprofits | |||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,27 +1,28 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class SupporterNotesController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class SupporterNotesController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_user!, except: [:create] | ||||
|     before_action :authenticate_nonprofit_user!, except: [:create] | ||||
| 
 | ||||
| 	# post /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes | ||||
| 	def create | ||||
|     params[:supporter_note][:user_id] ||= current_user && current_user.id | ||||
|     render_json{ InsertSupporterNotes.create([params[:supporter_note]]) } | ||||
| 	end | ||||
|     # post /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes | ||||
|     def create | ||||
|       params[:supporter_note][:user_id] ||= current_user&.id | ||||
|       render_json { InsertSupporterNotes.create([params[:supporter_note]]) } | ||||
|     end | ||||
| 
 | ||||
|   # put /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id | ||||
|   def update | ||||
|     params[:supporter_note][:user_id] ||= current_user && current_user.id | ||||
|     params[:supporter_note][:id] = params[:id]  | ||||
|     render_json{ UpdateSupporterNotes.update(params[:supporter_note]) } | ||||
|   end | ||||
| 
 | ||||
|   # delete /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id | ||||
|   def destroy | ||||
|     render_json{ UpdateSupporterNotes.delete(params[:id]) } | ||||
|   end | ||||
|     # put /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id | ||||
|     def update | ||||
|       params[:supporter_note][:user_id] ||= current_user&.id | ||||
|       params[:supporter_note][:id] = params[:id] | ||||
|       render_json { UpdateSupporterNotes.update(params[:supporter_note]) } | ||||
|     end | ||||
| 
 | ||||
| end | ||||
|     # delete /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id | ||||
|     def destroy | ||||
|       render_json { UpdateSupporterNotes.delete(params[:id]) } | ||||
|     end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,114 +1,114 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| class SupportersController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   class SupportersController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_user!, except: [:new, :create] | ||||
| 	#before_action(except: [:create, :mailchimp_landing]){authenticate_min_nonprofit_plan(2)} | ||||
|     before_action :authenticate_nonprofit_user!, except: %i[new create] | ||||
|     # before_action(except: [:create, :mailchimp_landing]){authenticate_min_nonprofit_plan(2)} | ||||
| 
 | ||||
| 	# get /nonprofit/:nonprofit_id/supporters | ||||
| 	def index | ||||
| 		@panels_layout = true | ||||
|     @nonprofit = current_nonprofit | ||||
| 		respond_to do |format| | ||||
| 			format.html | ||||
| 			format.json do | ||||
|         render json: QuerySupporters.full_search(params[:nonprofit_id], params) | ||||
| 			end | ||||
| 
 | ||||
| 			format.csv do | ||||
|         file_date = Date.today.strftime("%m-%d-%Y") | ||||
|         supporters = QuerySupporters.for_export(params[:nonprofit_id], params) | ||||
| 				send_data(Format::Csv.from_vectors(supporters), filename: "supporters-#{file_date}.csv") | ||||
| 			end | ||||
| 		end | ||||
|   end | ||||
| 
 | ||||
|   def export | ||||
|     begin | ||||
|     # get /nonprofit/:nonprofit_id/supporters | ||||
|     def index | ||||
|       @panels_layout = true | ||||
|       @nonprofit = current_nonprofit | ||||
|       @user = current_user_id | ||||
|       ExportSupporters::initiate_export(@nonprofit.id, params, @user) | ||||
|     rescue => e | ||||
|       e | ||||
|       respond_to do |format| | ||||
|         format.html | ||||
|         format.json do | ||||
|           render json: QuerySupporters.full_search(params[:nonprofit_id], params) | ||||
|         end | ||||
| 
 | ||||
|         format.csv do | ||||
|           file_date = Date.today.strftime('%m-%d-%Y') | ||||
|           supporters = QuerySupporters.for_export(params[:nonprofit_id], params) | ||||
|           send_data(Format::Csv.from_vectors(supporters), filename: "supporters-#{file_date}.csv") | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|     if e.nil? | ||||
|       flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." | ||||
|       render json: {}, status: :ok | ||||
|     else | ||||
|       render json: e, status: :ok | ||||
| 
 | ||||
|     def export | ||||
|       begin | ||||
|         @nonprofit = current_nonprofit | ||||
|         @user = current_user_id | ||||
|         ExportSupporters.initiate_export(@nonprofit.id, params, @user) | ||||
|       rescue StandardError => e | ||||
|         e | ||||
|       end | ||||
|       if e.nil? | ||||
|         flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." | ||||
|         render json: {}, status: :ok | ||||
|       else | ||||
|         render json: e, status: :ok | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def index_metrics | ||||
|     render_json do | ||||
|       QuerySupporters.full_search_metrics(params[:nonprofit_id], params) | ||||
|     def index_metrics | ||||
|       render_json do | ||||
|         QuerySupporters.full_search_metrics(params[:nonprofit_id], params) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def show | ||||
|     render json: {data: QuerySupporters.for_crm_profile(params[:nonprofit_id], [params[:id]]).first} | ||||
| 	end | ||||
| 
 | ||||
|   def email_address | ||||
|     render json: Supporter.find(params[:supporter_id]).email | ||||
|   end | ||||
| 
 | ||||
|   def full_contact | ||||
|     fc = FullContactInfo.where("supporter_id=#{params[:supporter_id]}").first | ||||
|     if fc | ||||
|       render json: {full_contact: QueryFullContactInfos.fetch_associated_tables(fc.id )} | ||||
|     else | ||||
|       render json: {full_contact: nil} | ||||
|     def show | ||||
|       render json: { data: QuerySupporters.for_crm_profile(params[:nonprofit_id], [params[:id]]).first } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def info_card | ||||
|     render json: QuerySupporters.for_info_card(params[:supporter_id]) | ||||
|   end | ||||
| 
 | ||||
| 	 | ||||
|   # post /nonprofits/:nonprofit_id/supporters | ||||
| 	def create | ||||
|     render_json{ InsertSupporter.create_or_update(params[:nonprofit_id], params[:supporter]) } | ||||
| 	end | ||||
| 
 | ||||
| 	# put /nonprofits/:nonprofit_id/supporters/:id | ||||
| 	def update | ||||
| 		@supporter = current_nonprofit.supporters.find(params[:id]) | ||||
| 		json_saved UpdateSupporter.from_info(@supporter, params[:supporter]) | ||||
| 	end | ||||
| 
 | ||||
| 	def bulk_delete | ||||
|     if params[:selecting_all] | ||||
|       supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select("supporters.id").execute.map{|h| h['id']} | ||||
|     else | ||||
|       supporter_ids = params[:supporter_ids]. map(&:to_i) | ||||
|     def email_address | ||||
|       render json: Supporter.find(params[:supporter_id]).email | ||||
|     end | ||||
| 		render_json {UpdateSupporter.bulk_delete(current_nonprofit.id, supporter_ids ) } | ||||
| 	end | ||||
| 
 | ||||
| 	# get /nonprofits/:nonprofit_id/supporters/merge_data | ||||
|   # returns the info required to merge two supporters | ||||
|   def merge_data | ||||
|     render json: QuerySupporters.merge_data(params[:ids]) | ||||
|   end | ||||
|     def full_contact | ||||
|       fc = FullContactInfo.where("supporter_id=#{params[:supporter_id]}").first | ||||
|       if fc | ||||
|         render json: { full_contact: QueryFullContactInfos.fetch_associated_tables(fc.id) } | ||||
|       else | ||||
|         render json: { full_contact: nil } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
| 	# post /nonprofits/:nonprofit_id/supporters/merge | ||||
| 	def merge | ||||
|     render JsonResp.new(params){|params| | ||||
|       requires(:supporter) | ||||
|       requires(:nonprofit_id).as_int | ||||
|       requires(:supporter_ids).as_array | ||||
|     }.when_valid{|params| | ||||
|       params[:supporter][:nonprofit_id] = params[:nonprofit_id] | ||||
|       MergeSupporters.selected(params[:supporter], params[:supporter_ids], params[:nonprofit_id], current_user.id) | ||||
|     } | ||||
| 	end | ||||
|     def info_card | ||||
|       render json: QuerySupporters.for_info_card(params[:supporter_id]) | ||||
|     end | ||||
| 
 | ||||
| 	# def new | ||||
| 	# 	@nonprofit = current_nonprofit | ||||
| 	# end | ||||
|     # post /nonprofits/:nonprofit_id/supporters | ||||
|     def create | ||||
|       render_json { InsertSupporter.create_or_update(params[:nonprofit_id], params[:supporter]) } | ||||
|     end | ||||
| 
 | ||||
| end | ||||
|     # put /nonprofits/:nonprofit_id/supporters/:id | ||||
|     def update | ||||
|       @supporter = current_nonprofit.supporters.find(params[:id]) | ||||
|       json_saved UpdateSupporter.from_info(@supporter, params[:supporter]) | ||||
|     end | ||||
| 
 | ||||
|     def bulk_delete | ||||
|       if params[:selecting_all] | ||||
|         supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select('supporters.id').execute.map { |h| h['id'] } | ||||
|       else | ||||
|         supporter_ids = params[:supporter_ids]. map(&:to_i) | ||||
|       end | ||||
|       render_json { UpdateSupporter.bulk_delete(current_nonprofit.id, supporter_ids) } | ||||
|     end | ||||
| 
 | ||||
|     # get /nonprofits/:nonprofit_id/supporters/merge_data | ||||
|     # returns the info required to merge two supporters | ||||
|     def merge_data | ||||
|       render json: QuerySupporters.merge_data(params[:ids]) | ||||
|     end | ||||
| 
 | ||||
|     # post /nonprofits/:nonprofit_id/supporters/merge | ||||
|     def merge | ||||
|       render JsonResp.new(params) do |_params| | ||||
|         requires(:supporter) | ||||
|         requires(:nonprofit_id).as_int | ||||
|         requires(:supporter_ids).as_array | ||||
|       end.when_valid do |params| | ||||
|         params[:supporter][:nonprofit_id] = params[:nonprofit_id] | ||||
|         MergeSupporters.selected(params[:supporter], params[:supporter_ids], params[:nonprofit_id], current_user.id) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|       # def new | ||||
|       #   @nonprofit = current_nonprofit | ||||
|       # end | ||||
|     end | ||||
| end | ||||
|  |  | |||
|  | @ -1,36 +1,32 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
| 	class TagJoinsController < ApplicationController | ||||
| 		include Controllers::NonprofitHelper | ||||
| 		before_action :authenticate_nonprofit_user! | ||||
|   class TagJoinsController < ApplicationController | ||||
|     include Controllers::NonprofitHelper | ||||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
|     def index | ||||
|       render_json do | ||||
|         {data: QuerySupporters.tag_joins(params['nonprofit_id'], params['supporter_id'])} | ||||
|         { data: QuerySupporters.tag_joins(params['nonprofit_id'], params['supporter_id']) } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
| 		# used for modify a single supporter's tags or a group of  | ||||
| 		# selected supporters' tags or all supporters' tags | ||||
| 		def modify | ||||
| 
 | ||||
|     # used for modify a single supporter's tags or a group of | ||||
|     # selected supporters' tags or all supporters' tags | ||||
|     def modify | ||||
|       if params[:selecting_all] | ||||
|         supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select("supporters.id").execute.map{|h| h['id']} | ||||
|         supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select('supporters.id').execute.map { |h| h['id'] } | ||||
|       else | ||||
|         supporter_ids = params[:supporter_ids]. map(&:to_i) | ||||
|       end | ||||
|      render InsertTagJoins.in_bulk(current_nonprofit.id, current_user.profile.id, supporter_ids, params[:tags]) | ||||
|       render InsertTagJoins.in_bulk(current_nonprofit.id, current_user.profile.id, supporter_ids, params[:tags]) | ||||
|     end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 		end | ||||
| 
 | ||||
| 		def destroy | ||||
| 			supporter = current_nonprofit.supporters.find(params[:supporter_id]) | ||||
| 			supporter.tag_joins.find(params[:id]).destroy | ||||
| 			render json: {}, status: :ok | ||||
| 		end | ||||
| 
 | ||||
| 	end | ||||
|     def destroy | ||||
|       supporter = current_nonprofit.supporters.find(params[:supporter_id]) | ||||
|       supporter.tag_joins.find(params[:id]).destroy | ||||
|       render json: {}, status: :ok | ||||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
|   class TagMastersController < ApplicationController | ||||
|  | @ -5,14 +7,14 @@ module Nonprofits | |||
|     before_action :authenticate_nonprofit_user! | ||||
| 
 | ||||
|     def index | ||||
|       render json: {data:  | ||||
|         Qx.select('id', 'name', 'created_at')  | ||||
|       render json: { data: | ||||
|         Qx.select('id', 'name', 'created_at') | ||||
|           .from('tag_masters') | ||||
|           .where( | ||||
|             ['tag_masters.nonprofit_id = $id', id: current_nonprofit.id], | ||||
|             ["coalesce(deleted, FALSE) = FALSE"]) | ||||
|           .execute  | ||||
|         } | ||||
|             ['coalesce(deleted, FALSE) = FALSE'] | ||||
|           ) | ||||
|           .execute } | ||||
|     end | ||||
| 
 | ||||
|     def create | ||||
|  | @ -25,7 +27,5 @@ module Nonprofits | |||
|       tag_master.tag_joins.destroy_all | ||||
|       render json: {}, status: :ok | ||||
|     end | ||||
| 
 | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,14 +1,16 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module Nonprofits | ||||
|   class TrackingsController < ApplicationController | ||||
|     # POST /nonprofits/:nonprofit_id/tracking | ||||
|     def create | ||||
|       render JsonResp.new(params){|data| | ||||
|       render JsonResp.new(params) do |_data| | ||||
|         requires(:donation_id).as_int | ||||
|         optional(:utm_campaign, :utm_content, :utm_medium, :utm_source).as_string | ||||
|       }.when_valid{|data| | ||||
|       end.when_valid do |_data| | ||||
|         InsertTracking.create(params) | ||||
|       } | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,67 +1,69 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
|  class NonprofitsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
| class NonprofitsController < ApplicationController | ||||
|   include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	helper_method :current_nonprofit_user? | ||||
| 	before_action :authenticate_nonprofit_user!, only: [:dashboard, :dashboard_metrics, :dashboard_todos, :payment_history, :profile_todos, :recurring_donation_stats, :update, :verify_identity] | ||||
| 	before_action :authenticate_super_admin!, only: [:destroy] | ||||
|   helper_method :current_nonprofit_user? | ||||
|   before_action :authenticate_nonprofit_user!, only: %i[dashboard dashboard_metrics dashboard_todos payment_history profile_todos recurring_donation_stats update verify_identity] | ||||
|   before_action :authenticate_super_admin!, only: [:destroy] | ||||
| 
 | ||||
| 	# get /nonprofits/:id | ||||
| 	# get /:state_code/:city/:name | ||||
| 	def show | ||||
|   # get /nonprofits/:id | ||||
|   # get /:state_code/:city/:name | ||||
|   def show | ||||
|     if !current_nonprofit.published && !current_role?(:super_admin) | ||||
|        block_with_sign_in | ||||
|       block_with_sign_in | ||||
|       return | ||||
|     end | ||||
| 		@nonprofit = current_nonprofit | ||||
| 		@url = Format::Url.concat(root_url, @nonprofit.url) | ||||
| 		@supporters = @nonprofit.supporters.not_deleted | ||||
| 		@profiles = @nonprofit.profiles.order('total_raised DESC').limit(5).includes(:user).uniq | ||||
|     @nonprofit = current_nonprofit | ||||
|     @url = Format::Url.concat(root_url, @nonprofit.url) | ||||
|     @supporters = @nonprofit.supporters.not_deleted | ||||
|     @profiles = @nonprofit.profiles.order('total_raised DESC').limit(5).includes(:user).uniq | ||||
| 
 | ||||
|     events = @nonprofit.events.not_deleted.order('start_datetime desc') | ||||
|     campaigns = @nonprofit.campaigns.not_deleted.not_a_child.order('created_at desc') | ||||
| 
 | ||||
| 		@events = events.upcoming | ||||
| 		@any_past_events = events.past.any? | ||||
| 		@active_campaigns = campaigns.active | ||||
| 		@any_past_campaigns = campaigns.past.any? | ||||
|     @events = events.upcoming | ||||
|     @any_past_events = events.past.any? | ||||
|     @active_campaigns = campaigns.active | ||||
|     @any_past_campaigns = campaigns.past.any? | ||||
| 
 | ||||
| 		@nonprofit_background_image =  FetchBackgroundImage.with_model(@nonprofit) | ||||
|     @nonprofit_background_image = FetchBackgroundImage.with_model(@nonprofit) | ||||
| 
 | ||||
| 		respond_to do |format| | ||||
| 			format.html | ||||
| 			format.json {@nonprofit} | ||||
| 		end | ||||
| 	end | ||||
|     respond_to do |format| | ||||
|       format.html | ||||
|       format.json { @nonprofit } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def recurring_donation_stats | ||||
|     render json: QueryRecurringDonations.overall_stats(params[:nonprofit_id]) | ||||
|   end | ||||
| 
 | ||||
| 	def profile_todos | ||||
| 		render json: FetchTodoStatus.for_profile(current_nonprofit) | ||||
| 	end | ||||
|   def profile_todos | ||||
|     render json: FetchTodoStatus.for_profile(current_nonprofit) | ||||
|   end | ||||
| 
 | ||||
| 	def dashboard_todos | ||||
| 		render json: FetchTodoStatus.for_dashboard(current_nonprofit) | ||||
| 	end | ||||
|   def dashboard_todos | ||||
|     render json: FetchTodoStatus.for_dashboard(current_nonprofit) | ||||
|   end | ||||
| 
 | ||||
| 	def create | ||||
|   def create | ||||
|     current_user ||= User.find(params[:user_id]) | ||||
| 		json_saved Nonprofit.register(current_user, params[:nonprofit]) | ||||
| 	end | ||||
|     json_saved Nonprofit.register(current_user, params[:nonprofit]) | ||||
|   end | ||||
| 
 | ||||
| 	def update | ||||
| 		flash[:notice] = 'Update successful!' | ||||
|   def update | ||||
|     flash[:notice] = 'Update successful!' | ||||
|     current_nonprofit.update_attributes params[:nonprofit].except(:verification_status) | ||||
| 		json_saved current_nonprofit | ||||
| 	end | ||||
|     json_saved current_nonprofit | ||||
|   end | ||||
| 
 | ||||
| 	def destroy | ||||
| 		current_nonprofit.destroy | ||||
| 		flash[:notice] = 'Nonprofit removed' | ||||
| 		render json: {} | ||||
| 	end | ||||
|   def destroy | ||||
|     current_nonprofit.destroy | ||||
|     flash[:notice] = 'Nonprofit removed' | ||||
|     render json: {} | ||||
|   end | ||||
| 
 | ||||
|   # get /nonprofits/:id/donate | ||||
|   def donate | ||||
|  | @ -69,18 +71,18 @@ | |||
|     @referer = params[:origin] || request.env['HTTP_REFERER'] | ||||
|     @campaign = current_nonprofit.campaigns.find_by_id(params[:campaign_id]) if params[:campaign_id] | ||||
|     @countries_translations = countries_list(I18n.locale) | ||||
|     respond_to { |format| format.html{render layout: 'layouts/embed'} } | ||||
|     respond_to { |format| format.html { render layout: 'layouts/embed' } } | ||||
|   end | ||||
| 
 | ||||
| 	def btn | ||||
| 		@nonprofit = current_nonprofit | ||||
| 		respond_to { |format| format.html{render layout: 'layouts/embed'} } | ||||
| 	end | ||||
|   def btn | ||||
|     @nonprofit = current_nonprofit | ||||
|     respond_to { |format| format.html { render layout: 'layouts/embed' } } | ||||
|   end | ||||
| 
 | ||||
|   # get /nonprofits/:id/supporter_form | ||||
|   def supporter_form | ||||
| 		@nonprofit = current_nonprofit | ||||
| 		respond_to { |format| format.html{render layout: 'layouts/embed'} } | ||||
|     @nonprofit = current_nonprofit | ||||
|     respond_to { |format| format.html { render layout: 'layouts/embed' } } | ||||
|   end | ||||
| 
 | ||||
|   # post /nonprofits/:id/supporter_with_tag | ||||
|  | @ -89,21 +91,21 @@ | |||
|     render json: InsertSupporter.with_tags_and_fields(@nonprofit.id, params[:supporter]) | ||||
|   end | ||||
| 
 | ||||
| 	def dashboard | ||||
| 		@nonprofit = current_nonprofit | ||||
| 		respond_to { |format| format.html } | ||||
| 	end | ||||
|   def dashboard | ||||
|     @nonprofit = current_nonprofit | ||||
|     respond_to { |format| format.html } | ||||
|   end | ||||
| 
 | ||||
| 	def dashboard_metrics | ||||
| 		render json: Hamster::Hash[data: NonprofitMetrics.all_metrics(current_nonprofit.id)] | ||||
| 	end | ||||
|   def dashboard_metrics | ||||
|     render json: Hamster::Hash[data: NonprofitMetrics.all_metrics(current_nonprofit.id)] | ||||
|   end | ||||
| 
 | ||||
| 	def payment_history | ||||
|   def payment_history | ||||
|     render json: NonprofitMetrics.payment_history(params) | ||||
| 	end | ||||
|   end | ||||
| 
 | ||||
| 	# put /nonprofits/:id/verify_identity | ||||
| 	def verify_identity | ||||
|   # put /nonprofits/:id/verify_identity | ||||
|   def verify_identity | ||||
|     if params[:legal_entity][:address] | ||||
|       tos = { | ||||
|         ip: current_user.current_sign_in_ip, | ||||
|  | @ -111,8 +113,8 @@ | |||
|         user_agent: request.user_agent | ||||
|       } | ||||
|     end | ||||
|     render_json{ UpdateNonprofit.verify_identity(params[:nonprofit_id], params[:legal_entity], tos) } | ||||
| 	end | ||||
|     render_json { UpdateNonprofit.verify_identity(params[:nonprofit_id], params[:legal_entity], tos) } | ||||
|   end | ||||
| 
 | ||||
|   def search | ||||
|     render json: QueryNonprofits.by_search_string(params[:npo_name]) | ||||
|  | @ -132,13 +134,12 @@ | |||
|     all_countries = ISO3166::Country.translations(locale) | ||||
| 
 | ||||
|     if Settings.intntl.all_countries | ||||
|       countries = all_countries.select{ |code, name| Settings.intntl.all_countries.include? code } | ||||
|       countries = countries.map{ |code, name| [code.upcase, name] }.sort{ |a, b| a[1] <=> b[1] } | ||||
|       countries = all_countries.select { |code, _name| Settings.intntl.all_countries.include? code } | ||||
|       countries = countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } | ||||
|       countries.push([Settings.intntl.other_country.upcase, I18n.t('nonprofits.donate.info.supporter.other_country')]) if Settings.intntl.other_country | ||||
|       countries | ||||
|     else | ||||
|       all_countries.map{ |code, name| [code.upcase, name] }.sort{ |a, b| a[1] <=> b[1] } | ||||
|       all_countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class OnboardController < ApplicationController | ||||
|   layout 'layouts/apified' | ||||
|   def index | ||||
|  |  | |||
|  | @ -1,63 +1,64 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ProfilesController < ApplicationController | ||||
| 
 | ||||
|   helper_method :authenticate_profile_owner! | ||||
| 
 | ||||
| 	before_action :authenticate_profile_owner!, only: [:update, :fundraisers, :donations_history] | ||||
|   before_action :authenticate_profile_owner!, only: %i[update fundraisers donations_history] | ||||
| 
 | ||||
| 	# get /profiles/:id | ||||
| 	# public profile | ||||
| 	def show | ||||
| 		@profile = Profile.find(params[:id]) | ||||
| 		@profile_nonprofits = Psql.execute(Qexpr.new.select("DISTINCT nonprofits.*").from(:nonprofits).join(:supporters, "supporters.nonprofit_id=nonprofits.id AND supporters.profile_id=#{@profile.id}")) | ||||
|   # get /profiles/:id | ||||
|   # public profile | ||||
|   def show | ||||
|     @profile = Profile.find(params[:id]) | ||||
|     @profile_nonprofits = Psql.execute(Qexpr.new.select('DISTINCT nonprofits.*').from(:nonprofits).join(:supporters, "supporters.nonprofit_id=nonprofits.id AND supporters.profile_id=#{@profile.id}")) | ||||
|     @campaigns = @profile.campaigns.published.includes(:nonprofit) | ||||
| 		if @profile.anonymous? && current_user_id != @profile.user_id && !:super_admin | ||||
| 			flash[:notice] = 'That user does not have a public profile.' | ||||
| 			redirect_to(request.env["HTTP_REFERER"] || root_url) | ||||
| 			return | ||||
| 		end | ||||
| 	end | ||||
|     if @profile.anonymous? && current_user_id != @profile.user_id && !:super_admin | ||||
|       flash[:notice] = 'That user does not have a public profile.' | ||||
|       redirect_to(request.env['HTTP_REFERER'] || root_url) | ||||
|       return | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	# get /profiles/:id/donations_history | ||||
| 	def donations_history | ||||
|   # get /profiles/:id/donations_history | ||||
|   def donations_history | ||||
|     validate | ||||
| 		@profile =  Profile.find(params[:id]) | ||||
| 		@recurring_donations = @profile.recurring_donations.where(:active => true).includes(:nonprofit) | ||||
| 		@donations = @profile.donations.includes(:nonprofit) | ||||
| 	end | ||||
|     @profile = Profile.find(params[:id]) | ||||
|     @recurring_donations = @profile.recurring_donations.where(active: true).includes(:nonprofit) | ||||
|     @donations = @profile.donations.includes(:nonprofit) | ||||
|   end | ||||
| 
 | ||||
|   # get /profiles/:id/fundraisers | ||||
|   def fundraisers | ||||
|     validate | ||||
|     current_user = Profile.find(params[:id]).user | ||||
|     @profile = current_user.profile | ||||
|     @edited_campaigns = Campaign.where("profile_id=#{@profile.id}").order("end_datetime DESC") | ||||
|     @edited_campaigns = Campaign.where("profile_id=#{@profile.id}").order('end_datetime DESC') | ||||
|   end | ||||
| 
 | ||||
|   # get /profiles/:id/events | ||||
|   def events | ||||
|     render json:  QueryEventMetrics.for_listings('profile', params[:id], params) | ||||
|     render json: QueryEventMetrics.for_listings('profile', params[:id], params) | ||||
|   end | ||||
| 
 | ||||
| 	# put /profiles/:id | ||||
| 	def update | ||||
|     if current_role?(:super_admin) # can update other profiles | ||||
|       @profile = Profile.find(params[:id]) | ||||
|     else | ||||
|       @profile = current_user.profile | ||||
|     end | ||||
| 		@profile.update_attributes(params[:profile]) | ||||
| 		json_saved @profile, 'Profile updated' | ||||
| 	end | ||||
|   # put /profiles/:id | ||||
|   def update | ||||
|     @profile = if current_role?(:super_admin) # can update other profiles | ||||
|                  Profile.find(params[:id]) | ||||
|                else | ||||
|                  current_user.profile | ||||
|                end | ||||
|     @profile.update_attributes(params[:profile]) | ||||
|     json_saved @profile, 'Profile updated' | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def authenticate_profile_owner!() | ||||
|     if (!current_role?(:super_associate) && | ||||
|         !current_role?(:super_admin) && | ||||
|         (!current_user || | ||||
|             !current_user.profile || | ||||
|             current_user.profile.id != params[:id].to_i)) | ||||
|   def authenticate_profile_owner! | ||||
|     if !current_role?(:super_associate) && | ||||
|        !current_role?(:super_admin) && | ||||
|        (!current_user || | ||||
|            !current_user.profile || | ||||
|            current_user.profile.id != params[:id].to_i) | ||||
|       block_with_sign_in | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -1,19 +1,20 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class RecurringDonationsController < ApplicationController | ||||
| 
 | ||||
|   def edit | ||||
|     @data = QueryRecurringDonations.fetch_for_edit params[:id] | ||||
|     if @data && params[:t] == @data['recurring_donation']['edit_token'] | ||||
|       @data['change_amount_suggestions'] = CalculateSuggestedAmounts.calculate(@data['recurring_donation']['amount']) | ||||
|       @data['miscellaneous_np_info'] = FetchMiscellaneousNpInfo.fetch(@data['nonprofit']['id']) | ||||
|       if @data['miscellaneous_np_info']['donate_again_url'].blank? | ||||
|         @data['miscellaneous_np_info']['donate_again_url'] = url_for(:controller => :nonprofits, :action=> :show, :id => @data['nonprofit']['id'], :only_path =>  false) | ||||
|         @data['miscellaneous_np_info']['donate_again_url'] = url_for(controller: :nonprofits, action: :show, id: @data['nonprofit']['id'], only_path: false) | ||||
|       end | ||||
|       respond_to do |format| | ||||
|         format.html | ||||
|       end | ||||
|     else | ||||
|       flash[:notice] = "Unable to find donation. Please follow the exact link provided in your email" | ||||
|       flash[:notice] = 'Unable to find donation. Please follow the exact link provided in your email' | ||||
|       redirect_to root_url | ||||
|     end | ||||
|   end | ||||
|  | @ -21,7 +22,7 @@ class RecurringDonationsController < ApplicationController | |||
|   def destroy | ||||
|     @data = QueryRecurringDonations.fetch_for_edit params[:id] | ||||
|     if params[:edit_token] != @data['recurring_donation']['edit_token'] | ||||
|       render json: {error: 'Invalid token'}, status: :unprocessable_entity | ||||
|       render json: { error: 'Invalid token' }, status: :unprocessable_entity | ||||
|     else | ||||
|       updated = UpdateRecurringDonations.cancel(params[:id], current_user ? current_user.email : @data['supporter']['email']) | ||||
|       render json: updated | ||||
|  | @ -37,7 +38,7 @@ class RecurringDonationsController < ApplicationController | |||
|       data['recurring_donation'] = UpdateRecurringDonations.update_paydate(data['recurring_donation'], params[:paydate]) if params[:paydate] | ||||
|       render json: data, status: data.is_a?(ValidationError) ? :unprocessable_entity : :ok | ||||
|     else | ||||
|       render json: {error: 'Invalid token'}, status: :unprocessable_entity | ||||
|       render json: { error: 'Invalid token' }, status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | @ -45,15 +46,14 @@ class RecurringDonationsController < ApplicationController | |||
|     rd = RecurringDonation.where('id = ?', params[:id]).first | ||||
|     if rd && params[:edit_token] == rd['edit_token'] | ||||
|       begin | ||||
|         amount_response =  UpdateRecurringDonations.update_amount(rd, params[:token], params[:amount]) | ||||
|         flash[:notice] = "Your recurring donation amount has been successfully changed to $#{(amount_response.amount/100).to_i}" | ||||
|         amount_response = UpdateRecurringDonations.update_amount(rd, params[:token], params[:amount]) | ||||
|         flash[:notice] = "Your recurring donation amount has been successfully changed to $#{(amount_response.amount / 100).to_i}" | ||||
|         render_json { amount_response } | ||||
|       rescue => e | ||||
|       rescue StandardError => e | ||||
|         render_json { raise e } | ||||
|       end | ||||
|     else | ||||
|       render json: {error: 'Invalid token'}, status: :unprocessable_entity | ||||
|       render json: { error: 'Invalid token' }, status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,23 +1,25 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class RolesController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	before_action :authenticate_nonprofit_admin! | ||||
|   before_action :authenticate_nonprofit_admin! | ||||
| 
 | ||||
| 	def create | ||||
| 		role = Role.create_for_nonprofit(params[:role][:name].to_sym, params[:role][:email], FetchNonprofit.with_params(params)) | ||||
| 		json_saved role, "User successfully added!" | ||||
| 	end | ||||
|   def create | ||||
|     role = Role.create_for_nonprofit(params[:role][:name].to_sym, params[:role][:email], FetchNonprofit.with_params(params)) | ||||
|     json_saved role, 'User successfully added!' | ||||
|   end | ||||
| 
 | ||||
| 	def destroy | ||||
| 		role = Role.find(params[:id]) | ||||
| 		roles = role.user.roles.where(host_id: params[:nonprofit_id], name: role.name) | ||||
| 		unless roles.empty? | ||||
| 			roles.destroy_all | ||||
| 			flash[:notice] = 'User successfully removed' | ||||
| 			render json: {} | ||||
| 		else | ||||
| 			render json: {:error => "We couldn't find that admin"}, :status => :unprocessable_entity | ||||
| 		end | ||||
| 	end | ||||
|   def destroy | ||||
|     role = Role.find(params[:id]) | ||||
|     roles = role.user.roles.where(host_id: params[:nonprofit_id], name: role.name) | ||||
|     if roles.empty? | ||||
|       render json: { error: "We couldn't find that admin" }, status: :unprocessable_entity | ||||
|     else | ||||
|       roles.destroy_all | ||||
|       flash[:notice] = 'User successfully removed' | ||||
|       render json: {} | ||||
|      end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,31 +1,31 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class SettingsController < ApplicationController | ||||
| 	include Controllers::NonprofitHelper | ||||
|   include Controllers::NonprofitHelper | ||||
| 
 | ||||
| 	helper_method :current_nonprofit_user? | ||||
| 	before_action :authenticate_user! | ||||
|   helper_method :current_nonprofit_user? | ||||
|   before_action :authenticate_user! | ||||
| 
 | ||||
| 	def index | ||||
| 		if current_role?(:super_admin) && params[:nonprofit_id] | ||||
| 			@nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
| 		elsif current_role?([:nonprofit_admin, :nonprofit_associate]) | ||||
| 			@nonprofit = administered_nonprofit | ||||
| 		end | ||||
| 
 | ||||
|     if current_role?(:super_admin) && params[:user_id] | ||||
|       @user = User.find_by_id(params[:user_id]) | ||||
|     elsif current_role?(:super_admin) && params[:user_email] | ||||
|       @user = User.find_by_email(params[:user_email]) | ||||
|     else | ||||
|       @user = current_user | ||||
|   def index | ||||
|     if current_role?(:super_admin) && params[:nonprofit_id] | ||||
|       @nonprofit = Nonprofit.find(params[:nonprofit_id]) | ||||
|     elsif current_role?(%i[nonprofit_admin nonprofit_associate]) | ||||
|       @nonprofit = administered_nonprofit | ||||
|     end | ||||
| 
 | ||||
| 		@profile = @user.profile | ||||
|     @user = if current_role?(:super_admin) && params[:user_id] | ||||
|               User.find_by_id(params[:user_id]) | ||||
|             elsif current_role?(:super_admin) && params[:user_email] | ||||
|               User.find_by_email(params[:user_email]) | ||||
|             else | ||||
|               current_user | ||||
|             end | ||||
| 
 | ||||
| 		if @nonprofit | ||||
| 			@miscellaneous_np_info = FetchMiscellaneousNpInfo.fetch(@nonprofit.id) | ||||
| 		end | ||||
| 
 | ||||
| 	end | ||||
|     @profile = @user.profile | ||||
| 
 | ||||
|     if @nonprofit | ||||
|       @miscellaneous_np_info = FetchMiscellaneousNpInfo.fetch(@nonprofit.id) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class StaticController < ApplicationController | ||||
|   layout 'layouts/static' | ||||
|  | @ -8,18 +10,17 @@ class StaticController < ApplicationController | |||
| 
 | ||||
|   def ccs | ||||
|     ccs_method = !Settings.ccs ? 'local_tar_gz' : Settings.ccs.ccs_method | ||||
|     if (ccs_method == 'local_tar_gz') | ||||
|     if ccs_method == 'local_tar_gz' | ||||
|       temp_file = "#{Rails.root}/tmp/#{Time.current.to_i}.tar.gz" | ||||
|       result = Kernel.system("git archive --format=tar.gz -o #{temp_file} HEAD") | ||||
|       if result | ||||
|         send_file(temp_file, :type => "application/gzip") | ||||
|         send_file(temp_file, type: 'application/gzip') | ||||
|       else | ||||
|         render body: nil, status: 500 | ||||
|       end | ||||
|     elsif (ccs_method == 'github') | ||||
|     elsif ccs_method == 'github' | ||||
|       git_hash = File.read("#{Rails.root}/CCS_HASH") | ||||
|       redirect_to "https://github.com/#{Settings.ccs.options.account}/#{Settings.ccs.options.repo}/tree/#{git_hash}" | ||||
|     end | ||||
| 
 | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class SuperAdminsController < ApplicationController | ||||
|   layout "layouts/page" | ||||
|   layout 'layouts/page' | ||||
| 
 | ||||
|   before_action :authenticate_super_associate! | ||||
| 
 | ||||
|   def index  | ||||
|   end | ||||
|   def index; end | ||||
| 
 | ||||
|   def search_nonprofits | ||||
|     render json: QueryNonprofits.for_admin(params) | ||||
|  | @ -15,49 +16,47 @@ class SuperAdminsController < ApplicationController | |||
|     render json: QueryProfiles.for_admin(params) | ||||
|   end | ||||
| 
 | ||||
|   def search_fullcontact  | ||||
|   def search_fullcontact | ||||
|     begin | ||||
|       result = FullContact.person(email: params[:search]) | ||||
|     rescue Exception => e | ||||
|       result = ''  | ||||
|       result = '' | ||||
|     end | ||||
|     render json: [result] | ||||
|   end | ||||
| 
 | ||||
|   def resend_user_confirmation | ||||
|     ParamValidation.new(params || {}, { | ||||
|        profile_id: {:required => true, is_integer: true} | ||||
|     }) | ||||
|     ParamValidation.new(params || {}, | ||||
|                         profile_id: { required: true, is_integer: true }) | ||||
| 
 | ||||
|     profile = Profile.includes(:user).where('id = ?', params[:profile_id]).first | ||||
|     unless (profile.user) | ||||
|       raise ArgumentError.new("#{params[:profile_id]} is a profile without a valid user") | ||||
|     unless profile.user | ||||
|       raise ArgumentError, "#{params[:profile_id]} is a profile without a valid user" | ||||
|     end | ||||
| 
 | ||||
|     profile.user.send_confirmation_instructions | ||||
| 
 | ||||
|     render json: {status: :ok} | ||||
|     render json: { status: :ok } | ||||
|   end | ||||
| 
 | ||||
|   def recurring_donations_without_cards | ||||
|     odd_donations = QueryRecurringDonations::recurring_donations_without_cards | ||||
|     odd_donations = QueryRecurringDonations.recurring_donations_without_cards | ||||
|     respond_to do |format| | ||||
|       format.html | ||||
|       format.csv do | ||||
|         csv_out = CSV.generate { |csv| | ||||
|         csv_out = CSV.generate do |csv| | ||||
|           csv << ['supporter id', 'recurring donation id', 'rd created date', 'rd modified', 'donation id', 'donation card id', | ||||
|                   'edit_token', 'nonprofit id', | ||||
|                   'last charge succeeded id', 'last charge succeeded created at', 'last charge attempted id', 'last charge attempted created at', 'amount'] | ||||
| 
 | ||||
|           odd_donations.each { |rd| | ||||
|           odd_donations.each do |rd| | ||||
|             csv << [rd.supporter.id, rd.id, rd.created_at, rd.updated_at, rd.donation.id, rd.donation.card_id, rd.edit_token, rd.nonprofit.id, | ||||
|                     rd.most_recent_paid_charge.id, rd.most_recent_paid_charge.created_at, rd.most_recent_charge.id, rd.most_recent_charge.created_at, | ||||
|                     rd.amount] | ||||
|           } | ||||
|         } | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
| 
 | ||||
|         send_data(csv_out, filename: "recurring_donations_without_cards-#{Time.now.to_date()}.csv") | ||||
|         send_data(csv_out, filename: "recurring_donations_without_cards-#{Time.now.to_date}.csv") | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | @ -65,17 +64,13 @@ class SuperAdminsController < ApplicationController | |||
|   def export_supporters_with_rds | ||||
|     np = params[:np] | ||||
|     ids = params[:ids] | ||||
|     results = QuerySupporters.for_export(np, {ids: ids}) | ||||
|     results[0].push("Management URLS") | ||||
|     results.drop(1).each {|row| | ||||
|       rds = Supporter.includes(:recurring_donations).find(row.last).recurring_donations.select{|rd| rd.active}.map{|rd| "* #{root_url}recurring_donations/#{rd.id}/edit?t=#{rd.edit_token}"}.join("\n") | ||||
|     results = QuerySupporters.for_export(np, ids: ids) | ||||
|     results[0].push('Management URLS') | ||||
|     results.drop(1).each do |row| | ||||
|       rds = Supporter.includes(:recurring_donations).find(row.last).recurring_donations.select(&:active).map { |rd| "* #{root_url}recurring_donations/#{rd.id}/edit?t=#{rd.edit_token}" }.join("\n") | ||||
|       row.push(rds) | ||||
|     } | ||||
|     end | ||||
| 
 | ||||
| 
 | ||||
|     send_data(Format::Csv.from_vectors(results), filename: "supporters_with_multiple_donations.csv") | ||||
|     send_data(Format::Csv.from_vectors(results), filename: 'supporters_with_multiple_donations.csv') | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,27 +1,29 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class TicketLevelsController < ApplicationController | ||||
| 	include Controllers::EventHelper | ||||
|   include Controllers::EventHelper | ||||
| 
 | ||||
| 	before_action :authenticate_event_editor!, :except => [:index, :show] | ||||
|   before_action :authenticate_event_editor!, except: %i[index show] | ||||
| 
 | ||||
| 	def index | ||||
|   def index | ||||
|     ev_id = current_event.id | ||||
|     render json: {data: QueryTicketLevels.with_event_id(ev_id, current_role?(:event_editor, ev_id) || current_role?(:super_admin) || current_role?(:nonprofit_admin, current_event.nonprofit_id))} | ||||
| 	end | ||||
|     render json: { data: QueryTicketLevels.with_event_id(ev_id, current_role?(:event_editor, ev_id) || current_role?(:super_admin) || current_role?(:nonprofit_admin, current_event.nonprofit_id)) } | ||||
|   end | ||||
| 
 | ||||
| 	def show | ||||
| 		render json: current_ticket_level | ||||
| 	end | ||||
|   def show | ||||
|     render json: current_ticket_level | ||||
|   end | ||||
| 
 | ||||
| 	def create | ||||
| 		ticket_level = current_event.ticket_levels.create params[:ticket_level] | ||||
| 		json_saved ticket_level, 'Ticket level created!' | ||||
| 	end | ||||
|   def create | ||||
|     ticket_level = current_event.ticket_levels.create params[:ticket_level] | ||||
|     json_saved ticket_level, 'Ticket level created!' | ||||
|   end | ||||
| 
 | ||||
| 	def update | ||||
| 		current_ticket_level.update_attributes params[:ticket_level] | ||||
| 		json_saved current_ticket_level, 'Ticket level updated' | ||||
| 	end | ||||
|   def update | ||||
|     current_ticket_level.update_attributes params[:ticket_level] | ||||
|     json_saved current_ticket_level, 'Ticket level updated' | ||||
|   end | ||||
| 
 | ||||
|   # put /nonprofits/:nonprofit_id/events/:event_id/ticket_levels/update_order | ||||
|   # Pass in {data: [{id: 1, order: 1}]} | ||||
|  | @ -31,14 +33,13 @@ class TicketLevelsController < ApplicationController | |||
|   end | ||||
| 
 | ||||
|   def destroy | ||||
| 		current_ticket_level.destroy | ||||
| 		render json: {} | ||||
| 	end | ||||
|     current_ticket_level.destroy | ||||
|     render json: {} | ||||
|    end | ||||
| 
 | ||||
| private | ||||
| 
 | ||||
| 	def current_ticket_level | ||||
| 		@ticket_level ||= current_event.ticket_levels.find params[:id] | ||||
| 	end | ||||
|   private | ||||
| 
 | ||||
|   def current_ticket_level | ||||
|     @ticket_level ||= current_event.ticket_levels.find params[:id] | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,13 +1,15 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class TicketsController < ApplicationController | ||||
| 	include Controllers::EventHelper | ||||
|   include Controllers::EventHelper | ||||
| 
 | ||||
| 	helper_method :current_event_admin?, :current_event_editor? | ||||
| 	before_action :authenticate_event_editor!, :except => [:create, :add_note] | ||||
|   helper_method :current_event_admin?, :current_event_editor? | ||||
|   before_action :authenticate_event_editor!, except: %i[create add_note] | ||||
|   before_action :authenticate_nonprofit_user!, only: [:delete_card_for_ticket] | ||||
| 
 | ||||
| 	# post /nonprofits/:nonprofit_id/events/:event_id/tickets | ||||
| 	def create | ||||
|   # post /nonprofits/:nonprofit_id/events/:event_id/tickets | ||||
|   def create | ||||
|     authenticate_event_editor! if params[:kind] == 'offsite' | ||||
|     render_json do | ||||
|       params[:current_user] = current_user | ||||
|  | @ -18,29 +20,29 @@ class TicketsController < ApplicationController | |||
|   def update | ||||
|     params[:ticket][:ticket_id] = params[:id] | ||||
|     params[:ticket][:event_id] = params[:event_id] | ||||
|     render_json{ UpdateTickets.update(params[:ticket], current_user) } | ||||
|     render_json { UpdateTickets.update(params[:ticket], current_user) } | ||||
|   end | ||||
| 
 | ||||
|   # Attendees dashboard | ||||
| 	# get /nonprofits/:nonprofit_id/events/:event_id/tickets | ||||
| 	def index | ||||
| 		@panels_layout = true | ||||
| 		@nonprofit = current_nonprofit | ||||
| 		@event = current_event | ||||
| 		respond_to do |format| | ||||
| 			format.html | ||||
|   # get /nonprofits/:nonprofit_id/events/:event_id/tickets | ||||
|   def index | ||||
|     @panels_layout = true | ||||
|     @nonprofit = current_nonprofit | ||||
|     @event = current_event | ||||
|     respond_to do |format| | ||||
|       format.html | ||||
|       format.csv do | ||||
| 				file_date = Date.today.strftime("%m-%d-%Y") | ||||
| 				filename = "tickets-#{file_date}" | ||||
|         file_date = Date.today.strftime('%m-%d-%Y') | ||||
|         filename = "tickets-#{file_date}" | ||||
|         @tickets = QueryTickets.for_export(@event.id, params) | ||||
| 				send_data(Format::Csv.from_vectors(@tickets), filename: "#{filename}.csv") | ||||
|         send_data(Format::Csv.from_vectors(@tickets), filename: "#{filename}.csv") | ||||
|       end | ||||
| 
 | ||||
| 			format.json do | ||||
|       format.json do | ||||
|         render json: QueryTickets.attendees_list(@event.id, params) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   # PUT nonprofits/:nonprofit_id/events/:event_id/tickets/:id/add_note | ||||
|   def add_note | ||||
|  |  | |||
|  | @ -1,41 +1,41 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Users::ConfirmationsController < Devise::ConfirmationsController | ||||
|   # get /confirm | ||||
|   def show | ||||
|     @user = User.confirm_by_token(params[:confirmation_token]) | ||||
| 
 | ||||
| 	# get /confirm | ||||
| 	def show | ||||
| 		@user = User.confirm_by_token(params[:confirmation_token]) | ||||
| 
 | ||||
| 		if !@user.auto_generated || !@user.valid? | ||||
| 			flash[:notice] = "We successfully confirmed your account" | ||||
| 			redirect_to session[:donor_signup_url] || root_url | ||||
| 		else | ||||
|     if !@user.auto_generated || !@user.valid? | ||||
|       flash[:notice] = 'We successfully confirmed your account' | ||||
|       redirect_to session[:donor_signup_url] || root_url | ||||
|     else | ||||
|       respond_to do |format| | ||||
|         format.html | ||||
|       end | ||||
| 		end | ||||
| 	end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def exists | ||||
|     render json: User.find_by_email(params[:email]) | ||||
|   end | ||||
| 
 | ||||
| 	# post /confirm | ||||
| 	# set account password | ||||
| 	def confirm | ||||
| 		@user = User.find(params[:id]) | ||||
|   # post /confirm | ||||
|   # set account password | ||||
|   def confirm | ||||
|     @user = User.find(params[:id]) | ||||
| 
 | ||||
| 		if @user.valid? && @user.update_attributes(params[:user].except(:confirmation_token)) | ||||
| 			flash[:notice] = "Your account is all set!" | ||||
| 			sign_in @user | ||||
| 			redirect_to session[:donor_signup_url] || root_url | ||||
| 		else | ||||
| 			session[:donor_signup_url] || root_url | ||||
| 			#render :action => "show", :layout => 'layouts/embed' | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
|   def is_confirmed | ||||
|     render json: {is_confirmed: User.find(params[:user_id]).confirmed?} | ||||
|     if @user.valid? && @user.update_attributes(params[:user].except(:confirmation_token)) | ||||
|       flash[:notice] = 'Your account is all set!' | ||||
|       sign_in @user | ||||
|       redirect_to session[:donor_signup_url] || root_url | ||||
|     else | ||||
|       session[:donor_signup_url] || root_url | ||||
|       # render :action => "show", :layout => 'layouts/embed' | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def is_confirmed | ||||
|     render json: { is_confirmed: User.find(params[:user_id]).confirmed? } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Users::RegistrationsController < Devise::RegistrationsController | ||||
|   respond_to :html, :json | ||||
|  | @ -12,9 +14,9 @@ class Users::RegistrationsController < Devise::RegistrationsController | |||
|     user = User.register_donor!(params[:user]) | ||||
|     if user.save | ||||
|       sign_in user | ||||
|       render :json => user | ||||
|       render json: user | ||||
|     else | ||||
|       render :json => user.errors.full_messages, :status => :unprocessable_entity | ||||
|       render json: user.errors.full_messages, status: :unprocessable_entity | ||||
|       clean_up_passwords(user) | ||||
|     end | ||||
|   end | ||||
|  | @ -33,7 +35,7 @@ class Users::RegistrationsController < Devise::RegistrationsController | |||
|       errs = current_user.errors.full_messages | ||||
|     else | ||||
|       success = false | ||||
|       errs = {:password => :incorrect} | ||||
|       errs = { password: :incorrect } | ||||
|     end | ||||
| 
 | ||||
|     if success | ||||
|  | @ -43,10 +45,10 @@ class Users::RegistrationsController < Devise::RegistrationsController | |||
|         flash[:notice] = 'Account updated!' | ||||
|       end | ||||
| 
 | ||||
|       sign_in(current_user, :bypass => true) | ||||
|       render :json => current_user | ||||
|       sign_in(current_user, bypass: true) | ||||
|       render json: current_user | ||||
|     else | ||||
|       render :json => {:errors => errs}, :status => :unprocessable_entity | ||||
|       render json: { errors: errs }, status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,37 +1,36 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Users::SessionsController < Devise::SessionsController | ||||
| 	layout 'layouts/apified', only: :new | ||||
| 	respond_to :json, only: :new | ||||
|   layout 'layouts/apified', only: :new | ||||
|   respond_to :json, only: :new | ||||
| 
 | ||||
|   def new | ||||
|     @theme = 'minimal' | ||||
|     super | ||||
|   end | ||||
| 
 | ||||
| 	def create | ||||
|   def create | ||||
|     @theme = 'minimal' | ||||
| 
 | ||||
| 		respond_to do |format| | ||||
| 			format.json {   | ||||
| 				warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")   | ||||
| 				render :status => 200, :json => { :status => "Success" }   | ||||
| 			} | ||||
| 		end   | ||||
| 	end   | ||||
| 
 | ||||
| 	 | ||||
| 	# post /users/confirm_auth | ||||
| 	# A simple action to confirm an entered password for a user who is already signed in | ||||
| 	def confirm_auth | ||||
| 		if current_user.valid_password?(params[:password]) | ||||
| 			tok = SecureRandom.uuid | ||||
| 			session[:pw_token]  = tok | ||||
| 			session[:pw_timestamp] = Time.current.to_s | ||||
| 			render json: {token: tok}, status: :ok | ||||
| 		else | ||||
| 			render json: ["Incorrect password. Please enter your #{Settings.general.name} %> password."], status: :unprocessable_entity | ||||
| 		end | ||||
|     respond_to do |format| | ||||
|       format.json do | ||||
|         warden.authenticate!(scope: resource_name, recall: "#{controller_path}#new") | ||||
|         render status: 200, json: { status: 'Success' } | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 	 | ||||
| end | ||||
| 
 | ||||
|   # post /users/confirm_auth | ||||
|   # A simple action to confirm an entered password for a user who is already signed in | ||||
|   def confirm_auth | ||||
|     if current_user.valid_password?(params[:password]) | ||||
|       tok = SecureRandom.uuid | ||||
|       session[:pw_token] = tok | ||||
|       session[:pw_timestamp] = Time.current.to_s | ||||
|       render json: { token: tok }, status: :ok | ||||
|     else | ||||
|       render json: ["Incorrect password. Please enter your #{Settings.general.name} %> password."], status: :unprocessable_entity | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,70 +1,71 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module ApplicationHelper | ||||
|   def resource_name | ||||
|     :user | ||||
|   end | ||||
| 
 | ||||
| 	def resource_name | ||||
| 		:user | ||||
| 	end | ||||
|   def resource | ||||
|     @resource ||= User.new | ||||
|   end | ||||
| 
 | ||||
| 	def resource | ||||
| 		@resource ||= User.new | ||||
| 	end | ||||
|   def devise_mapping | ||||
|     @devise_mapping ||= Devise.mappings[:user] | ||||
|   end | ||||
| 
 | ||||
| 	def devise_mapping | ||||
| 		@devise_mapping ||= Devise.mappings[:user] | ||||
| 	end | ||||
|   def print_currency(cents, unit = 'EUR', sign = true) | ||||
|     dollars = cents.to_f / 100.0 | ||||
|     dollars = number_to_currency(dollars, unit: unit.to_s, precision: dollars.round == dollars ? 0 : 2) | ||||
|     dollars = dollars[1..-1] unless sign | ||||
|     dollars | ||||
|   end | ||||
| 
 | ||||
| 	def print_currency(cents, unit="EUR", sign=true) | ||||
|              | ||||
| 		dollars = cents.to_f / 100.0 | ||||
| 		dollars = number_to_currency(dollars, :unit => "#{unit}", :precision => (dollars.round == dollars) ? 0 : 2) | ||||
| 		dollars = dollars[1..-1] if !sign | ||||
| 		dollars | ||||
| 	end | ||||
|   def print_percent(rate) | ||||
|     (rate.to_f * 100).round(2) | ||||
|   end | ||||
| 
 | ||||
| 	def print_percent(rate) | ||||
| 		(rate.to_f * 100).round(2) | ||||
| 	end | ||||
|   ## Dates | ||||
| 
 | ||||
| 	## Dates | ||||
|   def simple_date(date_object, timezone = nil) | ||||
|     return '' if date_object.nil? | ||||
| 
 | ||||
| 	def simple_date date_object, timezone=nil | ||||
| 		return '' if date_object.nil? | ||||
| 		date_object = date_object.in_time_zone(timezone) if timezone | ||||
| 		date_object.strftime("%m/%d/%Y") | ||||
| 	end | ||||
|     date_object = date_object.in_time_zone(timezone) if timezone | ||||
|     date_object.strftime('%m/%d/%Y') | ||||
|   end | ||||
| 
 | ||||
| 	def simple_time time_object, timezone=nil | ||||
| 		return '' if time_object.nil? | ||||
| 		time_object = time_object.in_time_zone(timezone) if timezone | ||||
| 		time_object.strftime("%l:%M%P") | ||||
| 	end | ||||
|   def simple_time(time_object, timezone = nil) | ||||
|     return '' if time_object.nil? | ||||
| 
 | ||||
| 	def readable_date date_object | ||||
| 		date_object.strftime("%B %d, %Y") | ||||
| 	end | ||||
|     time_object = time_object.in_time_zone(timezone) if timezone | ||||
|     time_object.strftime('%l:%M%P') | ||||
|   end | ||||
| 
 | ||||
| 	def date_and_time date_object, timezone=nil | ||||
| 		date_object = date_object.in_time_zone(timezone) if timezone | ||||
| 		date_object.strftime("%m/%d/%Y %I:%M%P (%Z)") | ||||
| 	end | ||||
|   def readable_date(date_object) | ||||
|     date_object.strftime('%B %d, %Y') | ||||
|   end | ||||
| 
 | ||||
| 	def us_states | ||||
| 		[ ['Alabama', 'AL'], ['Alaska', 'AK'], ['Arizona', 'AZ'], ['Arkansas', 'AR'], ['California', 'CA'], ['Colorado', 'CO'], ['Connecticut', 'CT'], ['Delaware', 'DE'], ['District of Columbia', 'DC'], ['Florida', 'FL'], ['Georgia', 'GA'], ['Hawaii', 'HI'], ['Idaho', 'ID'], ['Illinois', 'IL'], ['Indiana', 'IN'], ['Iowa', 'IA'], ['Kansas', 'KS'], ['Kentucky', 'KY'], ['Louisiana', 'LA'], ['Maine', 'ME'], ['Maryland', 'MD'], ['Massachusetts', 'MA'], ['Michigan', 'MI'], ['Minnesota', 'MN'], ['Mississippi', 'MS'], ['Missouri', 'MO'], ['Montana', 'MT'], ['Nebraska', 'NE'], ['Nevada', 'NV'], ['New Hampshire', 'NH'], ['New Jersey', 'NJ'], ['New Mexico', 'NM'], ['New York', 'NY'], ['North Carolina', 'NC'], ['North Dakota', 'ND'], ['Ohio', 'OH'], ['Oklahoma', 'OK'], ['Oregon', 'OR'], ['Pennsylvania', 'PA'], ['Puerto Rico', 'PR'], ['Rhode Island', 'RI'], ['South Carolina', 'SC'], ['South Dakota', 'SD'], ['Tennessee', 'TN'], ['Texas', 'TX'], ['Utah', 'UT'], ['Vermont', 'VT'], ['Virginia', 'VA'], ['Washington', 'WA'], ['West Virginia', 'WV'], ['Wisconsin', 'WI'], ['Wyoming', 'WY'] ] | ||||
| 	end | ||||
|   def date_and_time(date_object, timezone = nil) | ||||
|     date_object = date_object.in_time_zone(timezone) if timezone | ||||
|     date_object.strftime('%m/%d/%Y %I:%M%P (%Z)') | ||||
|   end | ||||
| 
 | ||||
| 	# Append a parameter to a URL string | ||||
| 	def url_with_param(param, val, url) | ||||
| 		url + (url.include?('?') ? '&' : '?') + param + '=' + val | ||||
| 	end | ||||
|   def us_states | ||||
|     [%w[Alabama AL], %w[Alaska AK], %w[Arizona AZ], %w[Arkansas AR], %w[California CA], %w[Colorado CO], %w[Connecticut CT], %w[Delaware DE], ['District of Columbia', 'DC'], %w[Florida FL], %w[Georgia GA], %w[Hawaii HI], %w[Idaho ID], %w[Illinois IL], %w[Indiana IN], %w[Iowa IA], %w[Kansas KS], %w[Kentucky KY], %w[Louisiana LA], %w[Maine ME], %w[Maryland MD], %w[Massachusetts MA], %w[Michigan MI], %w[Minnesota MN], %w[Mississippi MS], %w[Missouri MO], %w[Montana MT], %w[Nebraska NE], %w[Nevada NV], ['New Hampshire', 'NH'], ['New Jersey', 'NJ'], ['New Mexico', 'NM'], ['New York', 'NY'], ['North Carolina', 'NC'], ['North Dakota', 'ND'], %w[Ohio OH], %w[Oklahoma OK], %w[Oregon OR], %w[Pennsylvania PA], ['Puerto Rico', 'PR'], ['Rhode Island', 'RI'], ['South Carolina', 'SC'], ['South Dakota', 'SD'], %w[Tennessee TN], %w[Texas TX], %w[Utah UT], %w[Vermont VT], %w[Virginia VA], %w[Washington WA], ['West Virginia', 'WV'], %w[Wisconsin WI], %w[Wyoming WY]] | ||||
|   end | ||||
| 
 | ||||
| 	# Prepend 'http://' if it is not present in a given url | ||||
| 	# Used for linking to nonprofit-provided website | ||||
| 	def add_http url | ||||
| 		if url[/^http:\/\//] || url[/^https:\/\//] | ||||
| 			url | ||||
| 		else | ||||
| 			'http://' + url | ||||
| 		end | ||||
| 	end | ||||
|   # Append a parameter to a URL string | ||||
|   def url_with_param(param, val, url) | ||||
|     url + (url.include?('?') ? '&' : '?') + param + '=' + val | ||||
|   end | ||||
| 
 | ||||
|   # Prepend 'http://' if it is not present in a given url | ||||
|   # Used for linking to nonprofit-provided website | ||||
|   def add_http(url) | ||||
|     if url[%r{^http://}] || url[%r{^https://}] | ||||
|       url | ||||
|     else | ||||
|       'http://' + url | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,23 +1,24 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module CardHelper | ||||
|   def brand_file(brand) | ||||
|     if brand == 'Visa' || brand == 'visa' || brand == 'VISA' | ||||
|       'visa' | ||||
|     elsif brand == 'American Express' || brand == 'amex' | ||||
|       'amex' | ||||
|     elsif brand == 'Discover' || brand == 'Discover Card' || brand == 'discover' | ||||
|       'discover' | ||||
|     elsif brand == 'MasterCard' || brand == 'Mastercard' || brand == 'mastercard' | ||||
|       'mastercard' | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def brand_file(brand) | ||||
| 		if brand == 'Visa' || brand == 'visa' || brand == 'VISA' | ||||
| 			'visa' | ||||
| 		elsif brand == 'American Express' || brand == 'amex' | ||||
| 			'amex' | ||||
| 		elsif brand == 'Discover' || brand == 'Discover Card' || brand == 'discover' | ||||
| 			'discover' | ||||
| 		elsif brand == 'MasterCard' || brand == 'Mastercard' || brand == 'mastercard' | ||||
| 			'mastercard' | ||||
| 		end | ||||
| 	end | ||||
|   def current_card | ||||
|     current_user&.profile&.card | ||||
|   end | ||||
| 
 | ||||
| 	def current_card | ||||
| 		current_user && current_user.profile.card | ||||
| 	end | ||||
| 
 | ||||
| 	def expiration_years | ||||
| 		(0..15).map{|n| (Date.today + n.years).year} | ||||
| 	end | ||||
|   def expiration_years | ||||
|     (0..15).map { |n| (Date.today + n.years).year } | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,8 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module DeviseHelper | ||||
|   def devise_error_messages! | ||||
|     if resource && !resource.errors.empty? | ||||
|       resource.errors.first.first.to_s + ' ' +  | ||||
|       resource.errors.first.first.to_s + ' ' + | ||||
|         resource.errors.first.second | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -1,16 +1,16 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module NonprofitsHelper | ||||
| 
 | ||||
| 	def managed_npo_card_json | ||||
| 		if current_user | ||||
| 			if params[:nonprofit_id] && current_role?(:super_admin) | ||||
| 				raw(Nonprofit.find(params[:nonprofit_id]).active_card.to_json) | ||||
| 			elsif administered_nonprofit && administered_nonprofit.active_card | ||||
| 				raw(administered_nonprofit.active_card.to_json) | ||||
| 			end | ||||
| 		else | ||||
| 			'undefined' | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
|   def managed_npo_card_json | ||||
|     if current_user | ||||
|       if params[:nonprofit_id] && current_role?(:super_admin) | ||||
|         raw(Nonprofit.find(params[:nonprofit_id]).active_card.to_json) | ||||
|       elsif administered_nonprofit&.active_card | ||||
|         raw(administered_nonprofit.active_card.to_json) | ||||
|       end | ||||
|     else | ||||
|       'undefined' | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,2 +1,4 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| module OnboardHelper | ||||
| end | ||||
|  |  | |||
|  | @ -1,8 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module PricingHelper | ||||
| private | ||||
| 	def nonprofit_email | ||||
| 		return nil if @nonprofit.nil? | ||||
| 		@nonprofit.email || GetData.chain(@nonprofit.users.first, :email) | ||||
| 	end | ||||
|   private | ||||
| 
 | ||||
|   def nonprofit_email | ||||
|     return nil if @nonprofit.nil? | ||||
| 
 | ||||
|     @nonprofit.email || GetData.chain(@nonprofit.users.first, :email) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| module ProfilesHelper | ||||
| 
 | ||||
|   def get_shortened_name name | ||||
|   def get_shortened_name(name) | ||||
|     if name | ||||
|       name.length > 18 ? name[0..18] + '...' : name | ||||
|     else | ||||
|       'Your Account' | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| 
 | ||||
| class ApplicationJob < ActiveJob::Base | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class AdminMailer < BaseMailer | ||||
| 
 | ||||
|   # Subject can be set in your I18n file at config/locales/en.yml | ||||
|   # with the following lookup: | ||||
|   # | ||||
|  |  | |||
|  | @ -1,8 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class BaseMailer < ActionMailer::Base | ||||
|   include Roadie::Rails::Automatic | ||||
|   include Devise::Controllers::UrlHelpers | ||||
|   add_template_helper(ApplicationHelper) | ||||
|   default :from => Settings.mailer.default_from | ||||
|   default from: Settings.mailer.default_from | ||||
|   layout 'email' | ||||
| end | ||||
|  |  | |||
|  | @ -1,13 +1,13 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class BillingSubscriptionMailer < BaseMailer | ||||
| 
 | ||||
|   def failed_notice(np_id) | ||||
|     @nonprofit = Nonprofit.find(np_id) | ||||
|     @billing_subscription = @nonprofit.billing_subscription | ||||
|     @card = @nonprofit.active_card | ||||
|     @billing_plan = @billing_subscription.billing_plan | ||||
| 		@emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) | ||||
| 		mail(to: @emails, subject: "Action Needed, Please Update Your #{Settings.general.name} Account") | ||||
|     @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) | ||||
|     mail(to: @emails, subject: "Action Needed, Please Update Your #{Settings.general.name} Account") | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,15 +1,16 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class CampaignMailer < BaseMailer | ||||
|   def creation_followup(campaign) | ||||
|     @creator_profile = campaign.profile | ||||
|     @campaign = campaign | ||||
|     mail(to: @creator_profile.user.email, subject: "Get your new campaign rolling! (via #{Settings.general.name})") | ||||
|   end | ||||
| 
 | ||||
| 	def creation_followup(campaign) | ||||
| 		@creator_profile = campaign.profile | ||||
| 		@campaign = campaign | ||||
| 		mail(:to => @creator_profile.user.email, :subject => "Get your new campaign rolling! (via #{Settings.general.name})") | ||||
| 	end | ||||
| 
 | ||||
| 	def federated_creation_followup(campaign) | ||||
| 		@creator_profile = campaign.profile | ||||
| 		@campaign = campaign | ||||
| 		mail(:to => @creator_profile.user.email, :subject => "Get your new campaign rolling! (via #{Settings.general.name})") | ||||
| 	end | ||||
|   def federated_creation_followup(campaign) | ||||
|     @creator_profile = campaign.profile | ||||
|     @campaign = campaign | ||||
|     mail(to: @creator_profile.user.email, subject: "Get your new campaign rolling! (via #{Settings.general.name})") | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,36 +1,38 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class DonationMailer < BaseMailer | ||||
| 
 | ||||
| 	# Used for both one-time and recurring donations | ||||
|   # Used for both one-time and recurring donations | ||||
|   # can pass in array of admin user_ids to send to only some -- if falsey/empty, will send to all | ||||
| 	def donor_payment_notification(donation_id, locale=I18n.locale) | ||||
| 		@donation = Donation.find(donation_id) | ||||
| 		@nonprofit = @donation.nonprofit | ||||
|     if  @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? | ||||
|   def donor_payment_notification(donation_id, locale = I18n.locale) | ||||
|     @donation = Donation.find(donation_id) | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? | ||||
|       @thank_you_note = @donation.campaign.receipt_message | ||||
|     else | ||||
|       @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, {'NAME' => @donation.supporter.name}) | ||||
|       @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, 'NAME' => @donation.supporter.name) | ||||
|     end | ||||
|     @charge = @donation.charges.last | ||||
| 		reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
|     I18n.with_locale(locale) do | ||||
|   		mail( | ||||
|                   to: @donation.supporter.email,  | ||||
|                   from: from,  | ||||
|                   reply_to: reply_to,  | ||||
|                   subject: I18n.t('mailer.donations.donor_direct_debit_notification.subject', nonprofit_name: @nonprofit.name)) | ||||
|       mail( | ||||
|         to: @donation.supporter.email, | ||||
|         from: from, | ||||
|         reply_to: reply_to, | ||||
|         subject: I18n.t('mailer.donations.donor_direct_debit_notification.subject', nonprofit_name: @nonprofit.name) | ||||
|       ) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def donor_direct_debit_notification(donation_id, locale=I18n.locale) | ||||
|   def donor_direct_debit_notification(donation_id, locale = I18n.locale) | ||||
|     @donation = Donation.find(donation_id) | ||||
|     @nonprofit = @donation.nonprofit | ||||
| 
 | ||||
|     if  @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? | ||||
|     if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? | ||||
|       @thank_you_note = @donation.campaign.receipt_message | ||||
|     else | ||||
|       @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, {'NAME' => @donation.supporter.name}) | ||||
|       @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, 'NAME' => @donation.supporter.name) | ||||
|     end | ||||
| 
 | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|  | @ -45,87 +47,86 @@ class DonationMailer < BaseMailer | |||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	# Used for both one-time and recurring donations | ||||
| 	def nonprofit_payment_notification(donation_id, user_id=nil) | ||||
| 		@donation = Donation.find(donation_id) | ||||
| 		@charge = @donation.charges.last | ||||
| 		@nonprofit = @donation.nonprofit | ||||
|   # Used for both one-time and recurring donations | ||||
|   def nonprofit_payment_notification(donation_id, user_id = nil) | ||||
|     @donation = Donation.find(donation_id) | ||||
|     @charge = @donation.charges.last | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, @donation.campaign ? 'notify_campaigns' : 'notify_payments') | ||||
|     if user_id | ||||
|       em = User.find(user_id).email | ||||
|       # return unless @emails.include?(em) | ||||
|       @emails = [em] | ||||
|     end | ||||
| 		mail(to: @emails, subject: "Donation receipt for #{@donation.supporter.name}") | ||||
| 	end | ||||
|     mail(to: @emails, subject: "Donation receipt for #{@donation.supporter.name}") | ||||
|   end | ||||
| 
 | ||||
|   def nonprofit_failed_recurring_donation(donation_id) | ||||
| 		@donation = Donation.find(donation_id) | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		@charge = @donation.charges.last | ||||
|     @donation = Donation.find(donation_id) | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     @charge = @donation.charges.last | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, @donation.campaign ? 'notify_campaigns' : 'notify_payments') | ||||
| 		mail(to: @emails, subject: "Recurring donation payment failure for #{@donation.supporter.name || @donation.supporter.email}") | ||||
|     mail(to: @emails, subject: "Recurring donation payment failure for #{@donation.supporter.name || @donation.supporter.email}") | ||||
|   end | ||||
| 
 | ||||
|   def donor_failed_recurring_donation(donation_id) | ||||
| 		@donation = Donation.find(donation_id) | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		@charge = @donation.charges.last | ||||
| 		reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     @donation = Donation.find(donation_id) | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     @charge = @donation.charges.last | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
| 		mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Donation payment failure for #{@nonprofit.name}") | ||||
|     mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Donation payment failure for #{@nonprofit.name}") | ||||
|   end | ||||
| 
 | ||||
|   def nonprofit_recurring_donation_cancellation(donation_id) | ||||
| 		@donation = Donation.find(donation_id) | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		@charge = @donation.charges.last | ||||
|     @donation = Donation.find(donation_id) | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     @charge = @donation.charges.last | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, @donation.campaign ? 'notify_campaigns' : 'notify_payments') | ||||
| 		mail(to: @emails, subject: "Recurring donation cancelled for #{@donation.supporter.name || @donation.supporter.email}") | ||||
| 	end | ||||
|     mail(to: @emails, subject: "Recurring donation cancelled for #{@donation.supporter.name || @donation.supporter.email}") | ||||
|    end | ||||
| 
 | ||||
| 	def nonprofit_recurring_donation_change_amount(donation_id, previous_amount=nil) | ||||
| 		@donation = RecurringDonation.find(donation_id).donation | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
| 		@previous_amount = previous_amount | ||||
| 		mail(to: @emails, subject:"Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") | ||||
| 	end | ||||
|   def nonprofit_recurring_donation_change_amount(donation_id, previous_amount = nil) | ||||
|     @donation = RecurringDonation.find(donation_id).donation | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
|     @previous_amount = previous_amount | ||||
|     mail(to: @emails, subject: "Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") | ||||
|   end | ||||
| 
 | ||||
| 	def donor_recurring_donation_change_amount(donation_id, previous_amount=nil) | ||||
| 		@donation = RecurringDonation.find(donation_id).donation | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
| 		if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? | ||||
| 			@thank_you_note =	@nonprofit.miscellaneous_np_info.change_amount_message | ||||
| 		else | ||||
| 			@thank_you_note = nil | ||||
| 		end | ||||
| 		from = Format::Name.email_from_np(@nonprofit.name) | ||||
| 		@previous_amount = previous_amount | ||||
| 		mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") | ||||
| 	end | ||||
|   def donor_recurring_donation_change_amount(donation_id, previous_amount = nil) | ||||
|     @donation = RecurringDonation.find(donation_id).donation | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? | ||||
|       @thank_you_note = @nonprofit.miscellaneous_np_info.change_amount_message | ||||
|     else | ||||
|       @thank_you_note = nil | ||||
|     end | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
|     @previous_amount = previous_amount | ||||
|     mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") | ||||
|   end | ||||
| 
 | ||||
| 	def nonprofit_recurring_donation_change_amount(donation_id, previous_amount=nil) | ||||
| 		@donation = RecurringDonation.find(donation_id).donation | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
| 		@previous_amount = previous_amount | ||||
| 		mail(to: @emails, subject:"Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") | ||||
| 	end | ||||
| 
 | ||||
| 	def donor_recurring_donation_change_amount(donation_id, previous_amount=nil) | ||||
| 		@donation = RecurringDonation.find(donation_id).donation | ||||
| 		@nonprofit = @donation.nonprofit | ||||
| 		reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
| 		if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? | ||||
| 			@thank_you_note =	@nonprofit.miscellaneous_np_info.change_amount_message | ||||
| 		else | ||||
| 			@thank_you_note = nil | ||||
| 		end | ||||
| 		from = Format::Name.email_from_np(@nonprofit.name) | ||||
| 		@previous_amount = previous_amount | ||||
| 		mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") | ||||
| 	end | ||||
|   def nonprofit_recurring_donation_change_amount(donation_id, previous_amount = nil) | ||||
|     @donation = RecurringDonation.find(donation_id).donation | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
|     @previous_amount = previous_amount | ||||
|     mail(to: @emails, subject: "Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") | ||||
|   end | ||||
| 
 | ||||
|   def donor_recurring_donation_change_amount(donation_id, previous_amount = nil) | ||||
|     @donation = RecurringDonation.find(donation_id).donation | ||||
|     @nonprofit = @donation.nonprofit | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? | ||||
|       @thank_you_note = @nonprofit.miscellaneous_np_info.change_amount_message | ||||
|     else | ||||
|       @thank_you_note = nil | ||||
|     end | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
|     @previous_amount = previous_amount | ||||
|     mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class EventMailer < BaseMailer | ||||
|   helper :application | ||||
| 
 | ||||
| 	helper :application | ||||
| 
 | ||||
| 	include Devise::Controllers::UrlHelpers | ||||
| 
 | ||||
| 	def creation_followup(event) | ||||
| 		@creator_profile = event.profile | ||||
| 		@event = event | ||||
| 		mail(:to => @creator_profile.user.email, :subject => "Get your new event rolling on #{Settings.general.name}!") | ||||
| 	end | ||||
|   include Devise::Controllers::UrlHelpers | ||||
| 
 | ||||
|   def creation_followup(event) | ||||
|     @creator_profile = event.profile | ||||
|     @event = event | ||||
|     mail(to: @creator_profile.user.email, subject: "Get your new event rolling on #{Settings.general.name}!") | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ExportMailer < BaseMailer | ||||
| 
 | ||||
|   # Subject can be set in your I18n file at config/locales/en.yml | ||||
|   # with the following lookup: | ||||
|   # | ||||
|  | @ -18,7 +19,6 @@ class ExportMailer < BaseMailer | |||
|     mail(to: @export.user.email, subject: 'Your payment export has failed') | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
|   def export_recurring_donations_completed_notification(export) | ||||
|     @export = export | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,11 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class GenericMailer < BaseMailer | ||||
| 
 | ||||
|   def generic_mail(from_email, from_name, message, subject, to_email, to_name) | ||||
|   def generic_mail(from_email, from_name, message, subject, to_email, _to_name) | ||||
|     @from_email = from_email | ||||
|     @from_name = from_name | ||||
|     @message = message | ||||
|     mail(:to => to_email, :from => "#{from_name} <#{Settings.mailer.email}>", :reply_to => from_email, :subject => "#{subject}") | ||||
|     mail(to: to_email, from: "#{from_name} <#{Settings.mailer.email}>", reply_to: from_email, subject: subject.to_s) | ||||
|   end | ||||
| 
 | ||||
|   # For sending a system notice to super admins | ||||
|  | @ -16,5 +17,4 @@ class GenericMailer < BaseMailer | |||
|     emails = QueryUsers.super_admin_emails | ||||
|     mail(to: emails, from: "#{@from_name} <#{@from_email}>", reply_to: @from_email, subject: options[:subject], template_name: 'generic_mail') | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,10 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class ImportMailer < BaseMailer | ||||
| 
 | ||||
| 	def import_completed_notification(import_id) | ||||
| 		@import = Import.find(import_id) | ||||
| 		@nonprofit = @import.nonprofit | ||||
| 		mail(to: @import.user.email, subject: "Your import is complete!") | ||||
| 	end | ||||
| 
 | ||||
|   def import_completed_notification(import_id) | ||||
|     @import = Import.find(import_id) | ||||
|     @nonprofit = @import.nonprofit | ||||
|     mail(to: @import.user.email, subject: 'Your import is complete!') | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,28 +1,28 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class NonprofitAdminMailer < BaseMailer | ||||
|   def new_invite(role, raw_token) | ||||
|     @user = role.user | ||||
|     @title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) | ||||
|     @nonprofit = role.host | ||||
|     @token = raw_token | ||||
|     mail(to: @user.email, subject: "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}. Let's set your password.") | ||||
|   end | ||||
| 
 | ||||
| 	def new_invite(role, raw_token) | ||||
| 		@user = role.user | ||||
| 		@title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) | ||||
| 		@nonprofit = role.host | ||||
| 		@token = raw_token | ||||
| 		mail(:to => @user.email, :subject => "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}. Let's set your password.") | ||||
| 	end | ||||
|   def existing_invite(role) | ||||
|     @user = role.user | ||||
|     @title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) | ||||
|     @nonprofit = role.host | ||||
|     mail(to: @user.email, subject: "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}.") | ||||
|   end | ||||
| 
 | ||||
| 	def existing_invite(role) | ||||
| 		@user = role.user | ||||
| 		@title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) | ||||
| 		@nonprofit = role.host | ||||
| 		mail(:to => @user.email, :subject => "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}.") | ||||
| 	end | ||||
| 
 | ||||
| 	def supporter_fundraiser(event_or_campaign) | ||||
| 		@fundraiser = event_or_campaign | ||||
| 		@kind = event_or_campaign.class.name.downcase || 'event' | ||||
| 		@nonprofit = event_or_campaign.nonprofit | ||||
| 		@profile = event_or_campaign.profile | ||||
| 		recipients = @nonprofit.nonprofit_personnel_emails | ||||
| 		mail(to: recipients, subject: "A Supporter has created #{Format::Indefinitize.with_article(@kind.capitalize)} for your Nonprofit!") | ||||
| 	end | ||||
|   def supporter_fundraiser(event_or_campaign) | ||||
|     @fundraiser = event_or_campaign | ||||
|     @kind = event_or_campaign.class.name.downcase || 'event' | ||||
|     @nonprofit = event_or_campaign.nonprofit | ||||
|     @profile = event_or_campaign.profile | ||||
|     recipients = @nonprofit.nonprofit_personnel_emails | ||||
|     mail(to: recipients, subject: "A Supporter has created #{Format::Indefinitize.with_article(@kind.capitalize)} for your Nonprofit!") | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class NonprofitMailer < BaseMailer | ||||
| 
 | ||||
|   def failed_verification_notice(np) | ||||
|     @nonprofit = np | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
|  | @ -13,92 +14,93 @@ class NonprofitMailer < BaseMailer | |||
|     mail(to: @emails, subject: "Verification successful on #{Settings.general.name}!") | ||||
|   end | ||||
| 
 | ||||
| 	def refund_notification(refund_id) | ||||
| 		@refund = Refund.find(refund_id) | ||||
| 		@charge = @refund.charge | ||||
| 		@nonprofit = @refund.payment.nonprofit | ||||
|   def refund_notification(refund_id) | ||||
|     @refund = Refund.find(refund_id) | ||||
|     @charge = @refund.charge | ||||
|     @nonprofit = @refund.payment.nonprofit | ||||
|     @supporter = @refund.payment.supporter | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payments') | ||||
| 		mail(to: @emails, subject: "A new refund has been made for $#{Format::Currency.cents_to_dollars(@refund.amount)}") | ||||
| 	end | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payments') | ||||
|     mail(to: @emails, subject: "A new refund has been made for $#{Format::Currency.cents_to_dollars(@refund.amount)}") | ||||
|   end | ||||
| 
 | ||||
| 	def new_bank_account_notification(ba) | ||||
| 		@nonprofit = ba.nonprofit | ||||
| 		@bank_account = ba | ||||
| 		@emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) | ||||
| 		mail(to: @emails, subject: "We need to confirm the new bank account") | ||||
| 	end | ||||
|   def new_bank_account_notification(ba) | ||||
|     @nonprofit = ba.nonprofit | ||||
|     @bank_account = ba | ||||
|     @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) | ||||
|     mail(to: @emails, subject: 'We need to confirm the new bank account') | ||||
|   end | ||||
| 
 | ||||
| 	def pending_payout_notification(payout_id) | ||||
| 		@payout = Payout.find(payout_id) | ||||
| 		@nonprofit = @payout.nonprofit | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
| 		mail(to: @emails, subject: "Payout of available balance now pending") | ||||
| 	end | ||||
|   def pending_payout_notification(payout_id) | ||||
|     @payout = Payout.find(payout_id) | ||||
|     @nonprofit = @payout.nonprofit | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
|     mail(to: @emails, subject: 'Payout of available balance now pending') | ||||
|   end | ||||
| 
 | ||||
| 	def successful_payout_notification(payout) | ||||
| 		@nonprofit = payout.nonprofit | ||||
| 		@payout = payout | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
| 		mail(to: @emails, subject: "Payout of available balance succeeded") | ||||
| 	end | ||||
|   def successful_payout_notification(payout) | ||||
|     @nonprofit = payout.nonprofit | ||||
|     @payout = payout | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
|     mail(to: @emails, subject: 'Payout of available balance succeeded') | ||||
|   end | ||||
| 
 | ||||
| 	def failed_payout_notification(payout) | ||||
| 		@nonprofit = payout.nonprofit | ||||
| 		@payout = payout | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
| 		mail(to: @emails, subject: "Payout could not be completed") | ||||
| 	end | ||||
|   def failed_payout_notification(payout) | ||||
|     @nonprofit = payout.nonprofit | ||||
|     @payout = payout | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') | ||||
|     mail(to: @emails, subject: 'Payout could not be completed') | ||||
|   end | ||||
| 
 | ||||
| 	def failed_recurring_donation(recurring_donation) | ||||
| 		@recurring_donation = recurring_donation | ||||
| 		@nonprofit = recurring_donation.nonprofit | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
| 		mail(to: @emails, subject: "A recurring donation from one of your supporters had a payment failure.") | ||||
| 	end | ||||
|   def failed_recurring_donation(recurring_donation) | ||||
|     @recurring_donation = recurring_donation | ||||
|     @nonprofit = recurring_donation.nonprofit | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
|     mail(to: @emails, subject: 'A recurring donation from one of your supporters had a payment failure.') | ||||
|   end | ||||
| 
 | ||||
| 	def cancelled_recurring_donation(recurring_donation) | ||||
| 		@recurring_donation = recurring_donation | ||||
| 		@nonprofit = recurring_donation.nonprofit | ||||
| 		@emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
| 		mail(to: @emails, subject: "A recurring donation from one of your supporters was cancelled.") | ||||
| 	end | ||||
|   def cancelled_recurring_donation(recurring_donation) | ||||
|     @recurring_donation = recurring_donation | ||||
|     @nonprofit = recurring_donation.nonprofit | ||||
|     @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') | ||||
|     mail(to: @emails, subject: 'A recurring donation from one of your supporters was cancelled.') | ||||
|   end | ||||
| 
 | ||||
| 	def verified_notification(nonprofit) | ||||
| 		@nonprofit = nonprofit | ||||
| 		@emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) | ||||
| 		mail(to: @emails, subject: "Your nonprofit has been verified!") | ||||
| 	end | ||||
|   def verified_notification(nonprofit) | ||||
|     @nonprofit = nonprofit | ||||
|     @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) | ||||
|     mail(to: @emails, subject: 'Your nonprofit has been verified!') | ||||
|   end | ||||
| 
 | ||||
| 	def button_code(nonprofit, to_email, to_name, from_email, message, code) | ||||
| 		@nonprofit = nonprofit | ||||
| 		@to_email = to_email | ||||
| 		@to_name = to_name | ||||
| 		@from = from_email | ||||
| 		@message = message | ||||
| 		@code = code | ||||
|   def button_code(nonprofit, to_email, to_name, from_email, message, code) | ||||
|     @nonprofit = nonprofit | ||||
|     @to_email = to_email | ||||
|     @to_name = to_name | ||||
|     @from = from_email | ||||
|     @message = message | ||||
|     @code = code | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
| 		mail(to: to_email, from: from, reply_to: from_email, subject: "Please include this donate button code on the website") | ||||
| 	end | ||||
|     mail(to: to_email, from: from, reply_to: from_email, subject: 'Please include this donate button code on the website') | ||||
|   end | ||||
| 
 | ||||
|   def invoice_payment_notification(nonprofit_id, payment) | ||||
|     @nonprofit = Nonprofit.find(nonprofit_id) | ||||
|     @payment = payment | ||||
|     @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id, [:nonprofit_admin]) | ||||
|     @month_name = Date::MONTHNAMES[payment.date.month] | ||||
|     mail(to: @emails,  subject: "#{Settings.general.name} Subscription Receipt for #{@month_name}") | ||||
|     mail(to: @emails, subject: "#{Settings.general.name} Subscription Receipt for #{@month_name}") | ||||
|   end | ||||
| 
 | ||||
| 	# pass in all of: | ||||
| 	# {is_unsubscribed_from_emails, supporter_email, message, email_unsubscribe_uuid, nonprofit_id, from_email, subject} | ||||
| 	def supporter_message(args) | ||||
| 		return if args[:is_unsubscribed_from_emails] || args[:supporter_email].blank? | ||||
| 		@message = args[:message] | ||||
| 		@uuid = args[:email_unsubscribe_uuid] | ||||
| 		@nonprofit = Nonprofit.find args[:nonprofit_id] | ||||
|   # pass in all of: | ||||
|   # {is_unsubscribed_from_emails, supporter_email, message, email_unsubscribe_uuid, nonprofit_id, from_email, subject} | ||||
|   def supporter_message(args) | ||||
|     return if args[:is_unsubscribed_from_emails] || args[:supporter_email].blank? | ||||
| 
 | ||||
|     @message = args[:message] | ||||
|     @uuid = args[:email_unsubscribe_uuid] | ||||
|     @nonprofit = Nonprofit.find args[:nonprofit_id] | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
| 		mail(to: args[:supporter_email], reply_to: args[:from_email], from: from, subject: args[:subject]) | ||||
| 	end | ||||
|     mail(to: args[:supporter_email], reply_to: args[:from_email], from: from, subject: args[:subject]) | ||||
|   end | ||||
| 
 | ||||
|   def setup_verification(np_id) | ||||
|     @nonprofit = Nonprofit.find(np_id) | ||||
|  | @ -113,6 +115,4 @@ class NonprofitMailer < BaseMailer | |||
|     @emails = QueryUsers.all_nonprofit_user_emails(np_id, [:nonprofit_admin]) | ||||
|     mail(to: @emails, reply_to: 'support@commitchange.com', from: "#{Settings.general.name} Support", subject: "A hearty welcome from the #{Settings.general.name} team") | ||||
|   end | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class PaymentMailer < BaseMailer | ||||
| 
 | ||||
|   # Send a donation receipt to a single admin | ||||
|   # or a ticket receipt | ||||
|   def resend_admin_receipt(payment_id, user_id) | ||||
|  | @ -22,5 +23,4 @@ class PaymentMailer < BaseMailer | |||
|       return TicketMailer.followup(payment.tickets.pluck(:id), payment.charge.id).deliver | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,14 +1,15 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class RecurringDonationMailer < BaseMailer | ||||
|   def send_cancellation_notices(recurring_donation) | ||||
|     UserMailer.recurring_donation_cancelled(recurring_donation).deliver | ||||
|     NonprofitMailer.cancelled_recurring_donation(recurring_donation).deliver | ||||
|     recurring_donation | ||||
|   end | ||||
| 
 | ||||
| 	def send_cancellation_notices(recurring_donation) | ||||
| 		UserMailer.recurring_donation_cancelled(recurring_donation).deliver | ||||
| 		NonprofitMailer.cancelled_recurring_donation(recurring_donation).deliver | ||||
| 		return recurring_donation | ||||
| 	end | ||||
| 
 | ||||
| 	def send_failure_notifications(recurring_donation) | ||||
| 		UserMailer.recurring_donation_failure(recurring_donation).deliver | ||||
| 		NonprofitMailer.failed_recurring_donation(recurring_donation).deliver | ||||
| 	end | ||||
|   def send_failure_notifications(recurring_donation) | ||||
|     UserMailer.recurring_donation_failure(recurring_donation).deliver | ||||
|     NonprofitMailer.failed_recurring_donation(recurring_donation).deliver | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Testing < ActionMailer::Base | ||||
|   default from: "from@example.com" | ||||
|   default from: 'from@example.com' | ||||
| end | ||||
|  |  | |||
|  | @ -1,22 +1,23 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class TicketMailer < BaseMailer | ||||
| 
 | ||||
|   helper :application | ||||
| 
 | ||||
|   # Pass in ticket_ids, event_id, and supporter | ||||
|   def followup(ticket_ids, charge_id=nil) | ||||
|   def followup(ticket_ids, charge_id = nil) | ||||
|     @charge = charge_id ? Charge.find(charge_id) : nil | ||||
|     @tickets = Ticket.where("id IN(?)", ticket_ids) | ||||
|     @tickets = Ticket.where('id IN(?)', ticket_ids) | ||||
|     @event = @tickets.last.event | ||||
|     @supporter = @tickets.last.supporter | ||||
|     @nonprofit = @supporter.nonprofit | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     mail(from: from, to: @supporter.email, reply_to: reply_to, subject: "Your tickets#{@charge ?  ' and receipt ' : ' '}for: #{@event.name}") | ||||
|     mail(from: from, to: @supporter.email, reply_to: reply_to, subject: "Your tickets#{@charge ? ' and receipt ' : ' '}for: #{@event.name}") | ||||
|   end | ||||
| 
 | ||||
|   def receipt_admin(ticket_ids, user_id=nil) | ||||
|     @tickets = Ticket.where("id IN (?)", ticket_ids) | ||||
|   def receipt_admin(ticket_ids, user_id = nil) | ||||
|     @tickets = Ticket.where('id IN (?)', ticket_ids) | ||||
|     @charge = @tickets.last.charge | ||||
|     @supporter = @tickets.last.supporter | ||||
|     @event = @tickets.last.event | ||||
|  | @ -25,9 +26,9 @@ class TicketMailer < BaseMailer | |||
|     if user_id | ||||
|       em = User.find(user_id).email | ||||
|       return unless recipients.include?(em) | ||||
| 
 | ||||
|       recipients = [em] | ||||
|     end | ||||
|     mail(to: recipients, subject: "Ticket redeemed for #{@event.name} - #{@supporter.name}") | ||||
|   end | ||||
| 
 | ||||
| end | ||||
|  |  | |||
|  | @ -1,26 +1,26 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class UserMailer < BaseMailer | ||||
| 
 | ||||
| 	def refund_receipt(refund_id) | ||||
| 		@refund = Refund.find(refund_id) | ||||
|   def refund_receipt(refund_id) | ||||
|     @refund = Refund.find(refund_id) | ||||
|     @nonprofit = @refund.payment.nonprofit | ||||
| 		@charge = @refund.charge | ||||
|     @charge = @refund.charge | ||||
|     @supporter = @refund.payment.supporter | ||||
| 		reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email | ||||
|     from = Format::Name.email_from_np(@nonprofit.name) | ||||
| 		mail(to: @supporter.email, from: from, reply_to: reply_to, subject: "Your refund receipt for #{@nonprofit.name}") | ||||
| 	end | ||||
|     mail(to: @supporter.email, from: from, reply_to: reply_to, subject: "Your refund receipt for #{@nonprofit.name}") | ||||
|   end | ||||
| 
 | ||||
| 	def recurring_donation_failure(recurring_donation) | ||||
| 		@recurring_donation = recurring_donation | ||||
| 		mail(:to => @recurring_donation.email, | ||||
| 				 :subject => ("We couldn't process your recurring donation towards #{@recurring_donation.nonprofit.name}.")) | ||||
| 	end | ||||
| 
 | ||||
| 	def recurring_donation_cancelled(recurring_donation) | ||||
| 		@recurring_donation = recurring_donation | ||||
| 		mail(:to => @recurring_donation.email, | ||||
| 				 :subject => ("Your recurring donation towards #{@recurring_donation.nonprofit.name} was successfully cancelled.")) | ||||
| 	end | ||||
|   def recurring_donation_failure(recurring_donation) | ||||
|     @recurring_donation = recurring_donation | ||||
|     mail(to: @recurring_donation.email, | ||||
|          subject: "We couldn't process your recurring donation towards #{@recurring_donation.nonprofit.name}.") | ||||
|   end | ||||
| 
 | ||||
|   def recurring_donation_cancelled(recurring_donation) | ||||
|     @recurring_donation = recurring_donation | ||||
|     mail(to: @recurring_donation.email, | ||||
|          subject: "Your recurring donation towards #{@recurring_donation.nonprofit.name} was successfully cancelled.") | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Activity < ApplicationRecord | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| 
 | ||||
| class ApplicationRecord < ActiveRecord::Base | ||||
|     self.abstract_class = true | ||||
| end | ||||
|   self.abstract_class = true | ||||
| end | ||||
|  |  | |||
|  | @ -1,42 +1,41 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class BankAccount < ApplicationRecord | ||||
|   # TODO | ||||
|   # attr_accessible \ | ||||
|   # :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") | ||||
|   # :confirmation_token, # str (randomly generated private token for email confirmation) | ||||
|   # :account_number, # str (last digits only) | ||||
|   # :bank_name, # str | ||||
|   # :pending_verification, # bool (whether this bank account is still awaiting email confirmation) | ||||
|   # :status, # str | ||||
|   # :email, # str (contact email associated with the user who created this bank account) | ||||
|   # :deleted, # bool (soft delete flag) | ||||
|   # :stripe_bank_account_token, # str | ||||
|   # :stripe_bank_account_id, # str | ||||
|   # :nonprofit_id, :nonprofit | ||||
| 
 | ||||
| 	#TODO | ||||
| 	# attr_accessible \ | ||||
| 	# :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") | ||||
| 	# :confirmation_token, # str (randomly generated private token for email confirmation) | ||||
| 	# :account_number, # str (last digits only) | ||||
| 	# :bank_name, # str | ||||
| 	# :pending_verification, # bool (whether this bank account is still awaiting email confirmation) | ||||
| 	# :status, # str | ||||
| 	# :email, # str (contact email associated with the user who created this bank account) | ||||
| 	# :deleted, # bool (soft delete flag) | ||||
| 	# :stripe_bank_account_token, # str | ||||
| 	# :stripe_bank_account_id, # str | ||||
| 	# :nonprofit_id, :nonprofit | ||||
|   # validates :stripe_bank_account_token, presence: true, uniqueness: true | ||||
|   # validates :stripe_bank_account_id, presence: true, uniqueness: true | ||||
|   # validates :nonprofit, presence: true | ||||
|   # validates :email, presence: true, format: {with: Email::Regex} | ||||
|   # validate  :nonprofit_must_be_vetted, on: :create | ||||
|   # validate  :nonprofit_has_stripe_account | ||||
| 
 | ||||
| 	#validates :stripe_bank_account_token, presence: true, uniqueness: true | ||||
| 	# validates :stripe_bank_account_id, presence: true, uniqueness: true | ||||
| 	#validates :nonprofit, presence: true | ||||
| 	#validates :email, presence: true, format: {with: Email::Regex} | ||||
| 	#validate  :nonprofit_must_be_vetted, on: :create | ||||
| 	#validate  :nonprofit_has_stripe_account | ||||
|   has_many :payouts | ||||
|   belongs_to :nonprofit | ||||
| 
 | ||||
| 	has_many :payouts | ||||
| 	belongs_to :nonprofit | ||||
|   def nonprofit_must_be_vetted | ||||
|     errors.add(:nonprofit, 'must be vetted') unless nonprofit&.vetted | ||||
|   end | ||||
| 
 | ||||
| 	def nonprofit_must_be_vetted | ||||
| 		errors.add(:nonprofit, "must be vetted") unless self.nonprofit && self.nonprofit.vetted | ||||
| 	end | ||||
| 
 | ||||
| 
 | ||||
| 	def nonprofit_has_stripe_account | ||||
| 		errors.add(:nonprofit, 'must have a Stripe account id') if !self.nonprofit || self.nonprofit.stripe_account_id.blank? | ||||
| 	end | ||||
| 
 | ||||
| 	# Manually cause an instance to become invalid | ||||
| 	def invalidate! | ||||
| 		@not_valid = true | ||||
| 	end | ||||
|   def nonprofit_has_stripe_account | ||||
|     errors.add(:nonprofit, 'must have a Stripe account id') if !nonprofit || nonprofit.stripe_account_id.blank? | ||||
|   end | ||||
| 
 | ||||
|   # Manually cause an instance to become invalid | ||||
|   def invalidate! | ||||
|     @not_valid = true | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,19 +1,21 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class BillingPlan < ApplicationRecord | ||||
| 	Names = ['Starter', 'Fundraising', 'Supporter Management'] | ||||
| 	DefaultAmounts = [0, 9900, 29900] # in pennies | ||||
|   Names = ['Starter', 'Fundraising', 'Supporter Management'].freeze | ||||
|   DefaultAmounts = [0, 9900, 29_900].freeze # in pennies | ||||
| 
 | ||||
| 	#TODO | ||||
| 	# attr_accessible \ | ||||
| 	# 	:name, #str: readable name | ||||
| 	# 	:tier, #int: 0-4 (0: Free, 1: Fundraising, 2: Supporter Management) | ||||
| 	# 	:amount, #int (cents) | ||||
| 	# 	:stripe_plan_id, #str (matches plan ID in Stripe) Not needed if it's not a paying subscription | ||||
| 	# 	:interval, #str ('monthly', 'annual') | ||||
| 	# 	:percentage_fee # 0.038 | ||||
|   # TODO | ||||
|   # attr_accessible \ | ||||
|   #   :name, #str: readable name | ||||
|   #   :tier, #int: 0-4 (0: Free, 1: Fundraising, 2: Supporter Management) | ||||
|   #   :amount, #int (cents) | ||||
|   #   :stripe_plan_id, #str (matches plan ID in Stripe) Not needed if it's not a paying subscription | ||||
|   #   :interval, #str ('monthly', 'annual') | ||||
|   #   :percentage_fee # 0.038 | ||||
| 
 | ||||
| 	has_many :billing_subscriptions | ||||
|   has_many :billing_subscriptions | ||||
| 
 | ||||
| 	validates :name, :presence => true | ||||
| 	validates :amount, :presence => true | ||||
|   validates :name, presence: true | ||||
|   validates :amount, presence: true | ||||
| end | ||||
|  |  | |||
|  | @ -1,32 +1,31 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class BillingSubscription < ApplicationRecord | ||||
|   # TODO | ||||
|   # attr_accessible \ | ||||
|   #   :nonprofit_id, :nonprofit, | ||||
|   #   :billing_plan_id, :billing_plan, | ||||
|   #   :stripe_subscription_id, | ||||
|   #   :status # trialing, active, past_due, canceled, or unpaid | ||||
| 
 | ||||
| 	#TODO | ||||
| 	# attr_accessible \ | ||||
| 	# 	:nonprofit_id, :nonprofit, | ||||
| 	# 	:billing_plan_id, :billing_plan, | ||||
| 	# 	:stripe_subscription_id, | ||||
| 	# 	:status # trialing, active, past_due, canceled, or unpaid | ||||
|   attr_accessor :stripe_plan_id, :manual | ||||
|   belongs_to :nonprofit | ||||
|   belongs_to :billing_plan | ||||
| 
 | ||||
| 	attr_accessor :stripe_plan_id, :manual | ||||
| 	belongs_to :nonprofit | ||||
| 	belongs_to :billing_plan | ||||
|   validates :nonprofit, presence: true | ||||
|   validates :billing_plan, presence: true | ||||
| 
 | ||||
| 	validates :nonprofit, presence: true | ||||
| 	validates :billing_plan, presence: true | ||||
| 
 | ||||
| 	def as_json(options={}) | ||||
| 		h = super(options) | ||||
| 		h[:plan_name] = self.billing_plan.name | ||||
| 		h[:plan_amount] = self.billing_plan.amount / 100 | ||||
| 		h | ||||
| 	end | ||||
| 
 | ||||
| 	def self.create_with_stripe(np, params) | ||||
| 		bp = BillingPlan.find_by_stripe_plan_id params[:stripe_plan_id] | ||||
| 		h =  ConstructBillingSubscription.with_stripe np, bp | ||||
| 		return np.create_billing_subscription h | ||||
| 	end | ||||
|   def as_json(options = {}) | ||||
|     h = super(options) | ||||
|     h[:plan_name] = billing_plan.name | ||||
|     h[:plan_amount] = billing_plan.amount / 100 | ||||
|     h | ||||
|   end | ||||
| 
 | ||||
|   def self.create_with_stripe(np, params) | ||||
|     bp = BillingPlan.find_by_stripe_plan_id params[:stripe_plan_id] | ||||
|     h =  ConstructBillingSubscription.with_stripe np, bp | ||||
|     np.create_billing_subscription h | ||||
|   end | ||||
| end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,186 +1,185 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class Campaign < ApplicationRecord | ||||
|   # TODO | ||||
|   # attr_accessible \ | ||||
|   #   :name, | ||||
|   #   :tagline, | ||||
|   #   :slug, # str: url name | ||||
|   #   :total_supporters, | ||||
|   #   :goal_amount, | ||||
|   #   :nonprofit_id, | ||||
|   #   :profile_id, | ||||
|   #   :main_image, | ||||
|   #   :remove_main_image, # for carrierwave | ||||
|   #   :background_image, | ||||
|   #   :remove_background_image, #bool carrierwave | ||||
|   # :banner_image, | ||||
|   # :remove_banner_image, | ||||
|   #   :published, | ||||
|   #   :video_url, #str | ||||
|   #   :vimeo_video_id, | ||||
|   #   :youtube_video_id, | ||||
|   #   :summary, | ||||
|   #   :recurring_fund, # bool: whether this is a recurring campaign | ||||
|   #   :body, | ||||
|   #   :goal_amount_dollars, #accessor: translated into goal_amount (cents) | ||||
|   #   :show_total_raised, # bool | ||||
|   #   :show_total_count, # bool | ||||
|   #   :hide_activity_feed, # bool | ||||
|   # :end_datetime, | ||||
|   #   :deleted, #bool (soft delete) | ||||
|   #   :hide_goal, # bool | ||||
|   #   :hide_thermometer, #bool | ||||
|   #   :hide_title, # bool | ||||
|   # :receipt_message, # text | ||||
|   # :hide_custom_amounts, # boolean | ||||
|   # :parent_campaign_id, | ||||
|   # :reason_for_supporting, | ||||
|   # :default_reason_for_supporting | ||||
| 
 | ||||
| 	#TODO | ||||
| 	# attr_accessible \ | ||||
| 	# 	:name, | ||||
| 	# 	:tagline, | ||||
| 	# 	:slug, # str: url name | ||||
| 	# 	:total_supporters, | ||||
| 	# 	:goal_amount, | ||||
| 	# 	:nonprofit_id, | ||||
| 	# 	:profile_id, | ||||
| 	# 	:main_image, | ||||
| 	# 	:remove_main_image, # for carrierwave | ||||
| 	# 	:background_image, | ||||
| 	# 	:remove_background_image, #bool carrierwave | ||||
|     # :banner_image, | ||||
|     # :remove_banner_image, | ||||
| 	# 	:published, | ||||
| 	# 	:video_url, #str | ||||
| 	# 	:vimeo_video_id, | ||||
| 	# 	:youtube_video_id, | ||||
| 	# 	:summary, | ||||
| 	# 	:recurring_fund, # bool: whether this is a recurring campaign | ||||
| 	# 	:body, | ||||
| 	# 	:goal_amount_dollars, #accessor: translated into goal_amount (cents) | ||||
| 	# 	:show_total_raised, # bool | ||||
| 	# 	:show_total_count, # bool | ||||
| 	# 	:hide_activity_feed, # bool | ||||
|     # :end_datetime, | ||||
| 	# 	:deleted, #bool (soft delete) | ||||
| 	# 	:hide_goal, # bool | ||||
| 	# 	:hide_thermometer, #bool | ||||
| 	# 	:hide_title, # bool | ||||
|     # :receipt_message, # text | ||||
|     # :hide_custom_amounts, # boolean | ||||
|     # :parent_campaign_id, | ||||
|     # :reason_for_supporting, | ||||
|     # :default_reason_for_supporting | ||||
| 
 | ||||
|   validate  :end_datetime_cannot_be_in_past, :on => :create | ||||
| 	validates :profile, :presence => true | ||||
| 	validates :nonprofit, :presence => true | ||||
| 	validates :goal_amount, | ||||
| 		:presence => true, | ||||
| 		:numericality => {:only_integer => true, :greater_than => 99} | ||||
| 	validates :name, | ||||
| 		:presence => true, | ||||
| 		:length => {:maximum => 60} | ||||
|   validates :slug, uniqueness: {scope: :nonprofit_id, message: 'You already have a campaign with that URL.'}, presence: true | ||||
|   validate  :end_datetime_cannot_be_in_past, on: :create | ||||
|   validates :profile, presence: true | ||||
|   validates :nonprofit, presence: true | ||||
|   validates :goal_amount, | ||||
|             presence: true, | ||||
|             numericality: { only_integer: true, greater_than: 99 } | ||||
|   validates :name, | ||||
|             presence: true, | ||||
|             length: { maximum: 60 } | ||||
|   validates :slug, uniqueness: { scope: :nonprofit_id, message: 'You already have a campaign with that URL.' }, presence: true | ||||
| 
 | ||||
|   attr_accessor :goal_amount_dollars | ||||
| 
 | ||||
| 	mount_uploader :main_image, CampaignMainImageUploader | ||||
| 	mount_uploader :background_image, CampaignBackgroundImageUploader | ||||
| 	mount_uploader :banner_image, CampaignBannerImageUploader | ||||
|   mount_uploader :main_image, CampaignMainImageUploader | ||||
|   mount_uploader :background_image, CampaignBackgroundImageUploader | ||||
|   mount_uploader :banner_image, CampaignBannerImageUploader | ||||
| 
 | ||||
| 	has_many :donations | ||||
| 	has_many :charges, through: :donations | ||||
| 	has_many :payments, { through: :donations, source: "payment" } | ||||
| 	has_many :campaign_gift_options | ||||
| 	has_many :campaign_gifts, through: :campaign_gift_options | ||||
| 	has_many :supporters, :through => :donations | ||||
| 	has_many :recurring_donations | ||||
| 	has_many :roles,        as: :host, dependent: :destroy | ||||
| 	has_many :comments,     as: :host, dependent: :destroy | ||||
| 	has_many :activities,   as: :host, dependent: :destroy | ||||
| 	belongs_to :profile | ||||
| 	belongs_to :nonprofit | ||||
|   has_many :donations | ||||
|   has_many :charges, through: :donations | ||||
|   has_many :payments, through: :donations, source: 'payment' | ||||
|   has_many :campaign_gift_options | ||||
|   has_many :campaign_gifts, through: :campaign_gift_options | ||||
|   has_many :supporters, through: :donations | ||||
|   has_many :recurring_donations | ||||
|   has_many :roles,        as: :host, dependent: :destroy | ||||
|   has_many :comments,     as: :host, dependent: :destroy | ||||
|   has_many :activities,   as: :host, dependent: :destroy | ||||
|   belongs_to :profile | ||||
|   belongs_to :nonprofit | ||||
| 
 | ||||
|   belongs_to :parent_campaign, class_name: 'Campaign' | ||||
|   has_many :children_campaigns, class_name: 'Campaign', foreign_key: 'parent_campaign_id' | ||||
| 
 | ||||
| 	scope :published, ->   {where(:published => true)} | ||||
|   scope :active, ->      {where(:published => true).where("end_datetime IS NULL OR end_datetime >= ?", Date.today)} | ||||
|   scope :past, ->        {where(:published => true).where("end_datetime < ?", Date.today)} | ||||
| 	scope :unpublished, -> {where(:published => [nil, false])} | ||||
| 	scope :not_deleted, -> {where(deleted: [nil, false])} | ||||
| 	scope :deleted, -> {where(deleted: true)} | ||||
| 	scope :not_a_child, -> {where(parent_campaign_id: nil)} | ||||
|   scope :published, ->   { where(published: true) } | ||||
|   scope :active, ->      { where(published: true).where('end_datetime IS NULL OR end_datetime >= ?', Date.today) } | ||||
|   scope :past, ->        { where(published: true).where('end_datetime < ?', Date.today) } | ||||
|   scope :unpublished, -> { where(published: [nil, false]) } | ||||
|   scope :not_deleted, -> { where(deleted: [nil, false]) } | ||||
|   scope :deleted, -> { where(deleted: true) } | ||||
|   scope :not_a_child, -> { where(parent_campaign_id: nil) } | ||||
| 
 | ||||
| 	before_validation do | ||||
| 		if self.goal_amount_dollars.present? | ||||
| 			self.goal_amount = (self.goal_amount_dollars.gsub(',','').to_f * 100).to_i | ||||
| 		end | ||||
| 		self | ||||
| 	end | ||||
|   before_validation do | ||||
|     if goal_amount_dollars.present? | ||||
|       self.goal_amount = (goal_amount_dollars.delete(',').to_f * 100).to_i | ||||
|     end | ||||
|     self | ||||
|   end | ||||
| 
 | ||||
| 	before_validation(on: :create) do | ||||
| 		unless self.slug | ||||
| 			self.slug = Format::Url.convert_to_slug(name) | ||||
| 		end | ||||
| 		self.set_defaults | ||||
| 		self | ||||
| 	end | ||||
|   before_validation(on: :create) do | ||||
|     self.slug = Format::Url.convert_to_slug(name) unless slug | ||||
|     set_defaults | ||||
|     self | ||||
|   end | ||||
| 
 | ||||
| 	before_save do | ||||
| 		self.parse_video_id if self.video_url && self.video_url_changed? | ||||
| 		self | ||||
| 	end | ||||
|   before_save do | ||||
|     parse_video_id if video_url && video_url_changed? | ||||
|     self | ||||
|   end | ||||
| 
 | ||||
| 	after_create do | ||||
| 		user = self.profile.user | ||||
| 		Role.create(name: :campaign_editor, user_id: user.id, host: self) | ||||
| 		if child_campaign? | ||||
| 			CampaignMailer.delay.federated_creation_followup(self) | ||||
| 		else | ||||
| 			CampaignMailer.delay.creation_followup(self) | ||||
| 		end | ||||
|   after_create do | ||||
|     user = profile.user | ||||
|     Role.create(name: :campaign_editor, user_id: user.id, host: self) | ||||
|     if child_campaign? | ||||
|       CampaignMailer.delay.federated_creation_followup(self) | ||||
|     else | ||||
|       CampaignMailer.delay.creation_followup(self) | ||||
|     end | ||||
| 
 | ||||
| 		NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, self.nonprofit_id) | ||||
| 		self | ||||
| 	end | ||||
|     NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, nonprofit_id) | ||||
|     self | ||||
|   end | ||||
| 
 | ||||
| 	def set_defaults | ||||
|   def set_defaults | ||||
|     self.total_supporters = 1 | ||||
|     self.published = false if published.nil? | ||||
|   end | ||||
| 
 | ||||
| 		self.total_supporters = 1 | ||||
| 		self.published = false if self.published.nil? | ||||
| 	end | ||||
|   def parse_video_id | ||||
|     if video_url.include? 'vimeo' | ||||
|       self.vimeo_video_id = video_url.split('/').last | ||||
|       self.youtube_video_id = nil | ||||
|     elsif video_url.include? 'youtube' | ||||
|       match = video_url.match(/\?v=(.+)/) | ||||
|       return if match.nil? | ||||
| 
 | ||||
|       self.youtube_video_id = match[1].split('&').first | ||||
|       self.vimeo_video_id = nil | ||||
|     elsif video_url.include? 'youtu.be' | ||||
|       self.youtube_video_id = video_url.split('/').last | ||||
|       self.vimeo_video_id = nil | ||||
|     elsif video_url.blank? | ||||
|       self.vimeo_video_id = nil | ||||
|       self.youtube_video_id = nil | ||||
|     end | ||||
|     self | ||||
|   end | ||||
| 
 | ||||
| 	def parse_video_id | ||||
| 		if self.video_url.include? 'vimeo' | ||||
| 			self.vimeo_video_id = self.video_url.split('/').last | ||||
| 			self.youtube_video_id = nil | ||||
| 		elsif self.video_url.include? 'youtube' | ||||
| 			match = self.video_url.match(/\?v=(.+)/) | ||||
| 			return if match.nil? | ||||
| 			self.youtube_video_id = match[1].split('&').first | ||||
| 			self.vimeo_video_id = nil | ||||
| 		elsif self.video_url.include? 'youtu.be' | ||||
| 			self.youtube_video_id = self.video_url.split('/').last | ||||
| 			self.vimeo_video_id = nil | ||||
| 		elsif self.video_url.blank? | ||||
| 			self.vimeo_video_id = nil | ||||
| 			self.youtube_video_id = nil | ||||
| 		end | ||||
| 		self | ||||
| 	end | ||||
|   def total_raised | ||||
|     payments.sum(:gross_amount) | ||||
|   end | ||||
| 
 | ||||
| 	def total_raised | ||||
|     self.payments.sum(:gross_amount) | ||||
| 	end | ||||
|   def percentage_funded | ||||
|     goal_amount.nil? ? 0 : total_raised * 100 / goal_amount | ||||
|   end | ||||
| 
 | ||||
| 	def percentage_funded | ||||
| 		self.goal_amount.nil? ? 0 : self.total_raised * 100 / self.goal_amount | ||||
| 	end | ||||
|   def average_donation | ||||
|     donations.any? ? total_raised / donations.count : 0 | ||||
|   end | ||||
| 
 | ||||
| 	def average_donation | ||||
| 		self.donations.any? ? self.total_raised / self.donations.count : 0 | ||||
| 	end | ||||
| 
 | ||||
| 	# Validations | ||||
|   # Validations | ||||
| 
 | ||||
|   def end_datetime_cannot_be_in_past | ||||
|     if self.end_datetime.present? && self.end_datetime < Time.now | ||||
|     if end_datetime.present? && end_datetime < Time.now | ||||
|       errors.add(:end_datetime, "can't be in the past") | ||||
| 		end | ||||
| 	end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
| 	def ready_to_publish? | ||||
| 		[(self.body && self.body.length >= 500), (self.campaign_gift_options.count >= 1)].all? | ||||
| 	end | ||||
|   def ready_to_publish? | ||||
|     [(body && body.length >= 500), (campaign_gift_options.count >= 1)].all? | ||||
|   end | ||||
| 
 | ||||
| 	def url | ||||
| 		"#{self.nonprofit.url}/campaigns/#{self.slug}" | ||||
| 	end | ||||
|   def url | ||||
|     "#{nonprofit.url}/campaigns/#{slug}" | ||||
|   end | ||||
| 
 | ||||
| 	def days_left | ||||
|     return 0 if self.end_datetime.nil? | ||||
|     (self.end_datetime.to_date - Date.today).to_i | ||||
| 	end | ||||
|   def days_left | ||||
|     return 0 if end_datetime.nil? | ||||
| 
 | ||||
| 	def finished? | ||||
| 		self.end_datetime && self.end_datetime < Time.now | ||||
| 	end | ||||
|     (end_datetime.to_date - Date.today).to_i | ||||
|   end | ||||
| 
 | ||||
|   def finished? | ||||
|     end_datetime && end_datetime < Time.now | ||||
|   end | ||||
| 
 | ||||
|   def child_params | ||||
|     excluded_for_peer_to_peer = %w( | ||||
|       id created_at updated_at slug profile_id  url | ||||
|     excluded_for_peer_to_peer = %w[ | ||||
|       id created_at updated_at slug profile_id url | ||||
|       total_raised show_recurring_amount external_identifier parent_campaign_id | ||||
|       reason_for_supporting metadata | ||||
|     ) | ||||
|     ] | ||||
|     attributes.except(*excluded_for_peer_to_peer) | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,17 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later | ||||
| class CampaignGift < ApplicationRecord | ||||
|   # TODO | ||||
|   # attr_accessible \ | ||||
|   #   :donation_id, | ||||
|   #   :donation, | ||||
|   #   :campaign_gift_option, | ||||
|   #   :campaign_gift_option_id | ||||
| 
 | ||||
| 	#TODO | ||||
| 	# attr_accessible \ | ||||
| 	# 	:donation_id, | ||||
| 	# 	:donation, | ||||
| 	# 	:campaign_gift_option, | ||||
| 	# 	:campaign_gift_option_id | ||||
| 
 | ||||
| 	belongs_to :donation | ||||
| 	belongs_to :campaign_gift_option | ||||
| 
 | ||||
| 	validates :donation, presence: true | ||||
| 	validates :campaign_gift_option, presence: true | ||||
|   belongs_to :donation | ||||
|   belongs_to :campaign_gift_option | ||||
| 
 | ||||
|   validates :donation, presence: true | ||||
|   validates :campaign_gift_option, presence: true | ||||
| end | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Luis Castro
						Luis Castro