diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index e69de29bb2..1e992b6216 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# ran bin/rubocop -a +5c1a35f51b1eedab065f0403057f9909087d0e7b diff --git a/Gemfile b/Gemfile index 648c81fa84..da48dac6b5 100644 --- a/Gemfile +++ b/Gemfile @@ -1,82 +1,82 @@ # frozen_string_literal: true -source 'https://rubygems.org' - -gem 'rails', '6.1.7.10' -gem 'jbuilder', '~> 2.13' -gem 'bootsnap', '~> 1.18', require: false # Large rails application booting enhancer -gem 'hamster', '~> 3.0' # Thread-safe collection classes for Ruby -gem 'puma', '~> 5.6' -gem 'rake' -gem 'sassc-rails', '~> 2.1', '>= 2.1.2' -gem 'sassc', '~> 2.0', '>= 2.0.1' -gem 'stripe', '~> 1.58' # January 19, 2017 version of the Stripe API https://stripe.com/docs/api -gem 'webpacker', '~> 5.4.4' -gem 'good_job', '~> 3.99' +source "https://rubygems.org" + +gem "rails", "6.1.7.10" +gem "jbuilder", "~> 2.13" +gem "bootsnap", "~> 1.18", require: false # Large rails application booting enhancer +gem "hamster", "~> 3.0" # Thread-safe collection classes for Ruby +gem "puma", "~> 5.6" +gem "rake" +gem "sassc-rails", "~> 2.1", ">= 2.1.2" +gem "sassc", "~> 2.0", ">= 2.0.1" +gem "stripe", "~> 1.58" # January 19, 2017 version of the Stripe API https://stripe.com/docs/api +gem "webpacker", "~> 5.4.4" +gem "good_job", "~> 3.99" # fix for https://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/ gem "date", "~> 3.4.1" -gem 'httparty', '~> 0.22.0' # https://github.com/jnunemaker/httparty -gem 'sprockets', '~> 3.7' +gem "httparty", "~> 0.22.0" # https://github.com/jnunemaker/httparty +gem "sprockets", "~> 3.7" # Helpers -gem 'chronic', '~> 0.10.2' # For nat lang parsing of dates -gem 'countries', '~> 4.2' -gem 'i18n-js', '~> 3.8', git: 'https://github.com/houdiniproject/i18n-js.git', branch: 'houdini-tweaks' -gem 'rails-i18n', '~> 6.0.0', '~> 6' -gem 'premailer-rails', '~> 1.12' # for styling of email -gem 'money', '~> 6.19' +gem "chronic", "~> 0.10.2" # For nat lang parsing of dates +gem "countries", "~> 4.2" +gem "i18n-js", "~> 3.8", git: "https://github.com/houdiniproject/i18n-js.git", branch: "houdini-tweaks" +gem "rails-i18n", "~> 6.0.0", "~> 6" +gem "premailer-rails", "~> 1.12" # for styling of email +gem "money", "~> 6.19" # Database and Events -gem 'pg', '~> 1.5' +gem "pg", "~> 1.5" -gem 'param_validation', path: 'gems/ruby-param-validation' -gem 'qx', path: 'gems/ruby-qx' +gem "param_validation", path: "gems/ruby-param-validation" +gem "qx", path: "gems/ruby-qx" # Optimization -gem 'fast_blank' +gem "fast_blank" # Images -gem 'image_processing', '~> 1.13.0' +gem "image_processing", "~> 1.13.0" # URL validation -gem 'validate_url' +gem "validate_url" # User authentication # https://github.com/plataformatec/devise -gem 'devise-async', '~> 1.0' -gem 'devise', '~> 4.9' +gem "devise-async", "~> 1.0" +gem "devise", "~> 4.9" group :development, :ci do - gem 'traceroute', '~> 0.8.0' + gem "traceroute", "~> 0.8.0" end group :development, :ci, :test do - gem 'debug' - gem 'dotenv-rails', '~> 2.8', require: 'dotenv/rails-now' - gem 'rspec-rails', '~> 4.1.2' - gem 'rspec', '~> 3.13.0' - gem 'rspec-json_expectations', '~> 2' - gem 'factory_bot_rails', '~> 6.4' - gem 'factory_bot', '~> 6.5' - gem 'listen' - gem 'table_print', '~> 1.5', '>= 1.5.6' # giuNice table printing of data for the console - gem 'colorize', '~> 0.8.1' # Print colorized text in debugger/console - gem 'shoulda-matchers', '~> 5.3.0' - gem 'turbo_test' - gem 'erb_lint', require: false - eval_gemfile './gemfiles/rubocop.gemfile' + gem "debug" + gem "dotenv-rails", "~> 2.8", require: "dotenv/rails-now" + gem "rspec-rails", "~> 4.1.2" + gem "rspec", "~> 3.13.0" + gem "rspec-json_expectations", "~> 2" + gem "factory_bot_rails", "~> 6.4" + gem "factory_bot", "~> 6.5" + gem "listen" + gem "table_print", "~> 1.5", ">= 1.5.6" # giuNice table printing of data for the console + gem "colorize", "~> 0.8.1" # Print colorized text in debugger/console + gem "shoulda-matchers", "~> 5.3.0" + gem "turbo_test" + gem "erb_lint", require: false + eval_gemfile "./gemfiles/rubocop.gemfile" end group :ci, :test do - gem 'action_mailer_matchers', '~> 1.2' - gem 'database_cleaner-active_record' - gem 'stripe-ruby-mock', '~> 2.4.1', require: 'stripe_mock', git: 'https://github.com/commitchange/stripe-ruby-mock.git', branch: '2.4.1' - gem 'test-unit', '~> 3.6' - gem 'timecop', '~> 0.9.10' - gem 'webmock', '~> 3.24' - gem 'wisper-rspec', '~> 1.1.0' + gem "action_mailer_matchers", "~> 1.2" + gem "database_cleaner-active_record" + gem "stripe-ruby-mock", "~> 2.4.1", require: "stripe_mock", git: "https://github.com/commitchange/stripe-ruby-mock.git", branch: "2.4.1" + gem "test-unit", "~> 3.6" + gem "timecop", "~> 0.9.10" + gem "webmock", "~> 3.24" + gem "wisper-rspec", "~> 1.1.0" end group :production do @@ -87,18 +87,18 @@ group :production do # like heroku, uncomment the `heroku-deflater` line. # # gem 'heroku-deflater', '~> 0.6.3' # https://github.com/romanbsd/heroku-deflater - gem 'rack-timeout', '~> 0.7.0' + gem "rack-timeout", "~> 0.7.0" end -gem 'bess', path: 'gems/bess' +gem "bess", path: "gems/bess" -gem 'houdini_full_contact', path: 'gems/houdini_full_contact' +gem "houdini_full_contact", path: "gems/houdini_full_contact" gem "react_on_rails", "12.6.0" -gem 'kaminari' +gem "kaminari" -gem 'http_accept_language' +gem "http_accept_language" gem "js-routes" diff --git a/Rakefile b/Rakefile index 9a1483531a..3d7bf1979a 100755 --- a/Rakefile +++ b/Rakefile @@ -4,6 +4,6 @@ # 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', __dir__) +require File.expand_path("config/application", __dir__) Commitchange::Application.load_tasks diff --git a/app/controllers/api/api_controller.rb b/app/controllers/api/api_controller.rb index bfa3464fa0..12ce68c630 100644 --- a/app/controllers/api/api_controller.rb +++ b/app/controllers/api/api_controller.rb @@ -3,21 +3,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Api::ApiController < ActionController::Base # rubocop:disable Rails/ApplicationController - # We disable Rails/ApplicationController bec - include Controllers::Locale - include Controllers::Nonprofit::Authorization + # We disable Rails/ApplicationController bec + include Controllers::Locale + include Controllers::Nonprofit::Authorization - rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue - rescue_from AuthenticationError, with: :unauthorized_rescue + rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue + rescue_from AuthenticationError, with: :unauthorized_rescue - protected + protected - def record_invalid_rescue(error) - render json: { errors: error.record.errors.messages }, status: :unprocessable_entity - end + def record_invalid_rescue(error) + render json: {errors: error.record.errors.messages}, status: :unprocessable_entity + end - def unauthorized_rescue(error) - @error = error - render 'api/errors/unauthorized', status: :unauthorized - end + def unauthorized_rescue(error) + @error = error + render "api/errors/unauthorized", status: :unauthorized + end end diff --git a/app/controllers/api/campaign_gift_options_controller.rb b/app/controllers/api/campaign_gift_options_controller.rb index e80c5c59ab..30579aefa9 100644 --- a/app/controllers/api/campaign_gift_options_controller.rb +++ b/app/controllers/api/campaign_gift_options_controller.rb @@ -5,22 +5,22 @@ # A controller for interacting with a nonprofit's supporters class Api::CampaignGiftOptionsController < Api::ApiController - include Controllers::Campaign::Current - include Controllers::Campaign::Authorization + include Controllers::Campaign::Current + include Controllers::Campaign::Authorization - before_action :authenticate_campaign_editor! + before_action :authenticate_campaign_editor! - def index - @campaign_gift_options = - current_campaign - .campaign_gift_options - .order('id DESC') - .page(params[:page]) - .per(params[:per]) - end + def index + @campaign_gift_options = + current_campaign + .campaign_gift_options + .order("id DESC") + .page(params[:page]) + .per(params[:per]) + end - # If not logged in, causes a 401 error - def show - @campaign_gift_option = current_campaign.campaign_gift_options.find(params[:id]) - end + # If not logged in, causes a 401 error + def show + @campaign_gift_option = current_campaign.campaign_gift_options.find(params[:id]) + end end diff --git a/app/controllers/api/campaigns_controller.rb b/app/controllers/api/campaigns_controller.rb index 88b25363fc..a2ef551e3a 100644 --- a/app/controllers/api/campaigns_controller.rb +++ b/app/controllers/api/campaigns_controller.rb @@ -5,14 +5,14 @@ # A controller for interacting with a nonprofit's supporters class Api::CampaignsController < Api::ApiController - include Controllers::Campaign::Current - include Controllers::Campaign::Authorization + include Controllers::Campaign::Current + include Controllers::Campaign::Authorization - before_action :authenticate_campaign_editor!, only: :show + before_action :authenticate_campaign_editor!, only: :show - # Gets the a single nonprofit campaign - # If not logged in, causes a 401 error - def show - @campaign = current_campaign - end + # Gets the a single nonprofit campaign + # If not logged in, causes a 401 error + def show + @campaign = current_campaign + end end diff --git a/app/controllers/api/custom_field_definitions_controller.rb b/app/controllers/api/custom_field_definitions_controller.rb index 9d7f750096..544c646868 100644 --- a/app/controllers/api/custom_field_definitions_controller.rb +++ b/app/controllers/api/custom_field_definitions_controller.rb @@ -5,24 +5,24 @@ # A controller for interacting with a nonprofit's custom field definition class Api::CustomFieldDefinitionsController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits custom field definitions - # If not logged in, causes a 401 error - def index - @custom_field_definitions = - current_nonprofit - .custom_field_definitions - .order('id DESC') - .page(params[:page]) - .per(params[:per]) - end + # Gets the nonprofits custom field definitions + # If not logged in, causes a 401 error + def index + @custom_field_definitions = + current_nonprofit + .custom_field_definitions + .order("id DESC") + .page(params[:page]) + .per(params[:per]) + end - # Gets a single custom field definition - # If not logged in, causes a 401 error - def show - @custom_field_definition = current_nonprofit.custom_field_definitions.find(params[:id]) - end + # Gets a single custom field definition + # If not logged in, causes a 401 error + def show + @custom_field_definition = current_nonprofit.custom_field_definitions.find(params[:id]) + end end diff --git a/app/controllers/api/events_controller.rb b/app/controllers/api/events_controller.rb index 0400a97db5..b0d33d0d1b 100644 --- a/app/controllers/api/events_controller.rb +++ b/app/controllers/api/events_controller.rb @@ -5,14 +5,14 @@ # A controller for interacting with a nonprofit's supporters class Api::EventsController < Api::ApiController - include Controllers::Event::Current - include Controllers::Event::Authorization + include Controllers::Event::Current + include Controllers::Event::Authorization - before_action :authenticate_event_editor!, only: :show + before_action :authenticate_event_editor!, only: :show - # Gets the a single nonprofit campaign - # If not logged in, causes a 401 error - def show - @event = current_event - end + # Gets the a single nonprofit campaign + # If not logged in, causes a 401 error + def show + @event = current_event + end end diff --git a/app/controllers/api/nonprofits_controller.rb b/app/controllers/api/nonprofits_controller.rb index deefbad661..717cfbbee5 100644 --- a/app/controllers/api/nonprofits_controller.rb +++ b/app/controllers/api/nonprofits_controller.rb @@ -3,27 +3,24 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Api::NonprofitsController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - - before_action :authenticate_nonprofit_user!, only: %i[show] + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization - def create - @nonprofit = Nonprofit.new(clean_params.merge({user_id: current_user_id})) - @nonprofit.save! - render status: :created - end + before_action :authenticate_nonprofit_user!, only: %i[show] - def show - @nonprofit = current_nonprofit - end + def create + @nonprofit = Nonprofit.new(clean_params.merge({user_id: current_user_id})) + @nonprofit.save! + render status: :created + end - private - - def clean_params - params.permit(:name, :zip_code, :state_code, :city, :phone, :email, :website) - end - -end + def show + @nonprofit = current_nonprofit + end + private + def clean_params + params.permit(:name, :zip_code, :state_code, :city, :phone, :email, :website) + end +end diff --git a/app/controllers/api/payments_controller.rb b/app/controllers/api/payments_controller.rb index fab604def3..94b4226798 100644 --- a/app/controllers/api/payments_controller.rb +++ b/app/controllers/api/payments_controller.rb @@ -5,30 +5,30 @@ # A controller for interacting with a subtransactions payments class Api::PaymentsController < Api::ApiController - include Controllers::Api::Transaction::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Api::Transaction::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - def index - @payments = - current_subtransaction - .payments - .order('created DESC') - .page(params[:page]) - .per(params[:per]) - end + def index + @payments = + current_subtransaction + .payments + .order("created DESC") + .page(params[:page]) + .per(params[:per]) + end - def show - @payment = current_payment - end + def show + @payment = current_payment + end - private + private - def current_subtransaction - current_transaction.subtransaction - end + def current_subtransaction + current_transaction.subtransaction + end - def current_payment - current_subtransaction.payments.where(paymentable_id: params[:id]) - end + def current_payment + current_subtransaction.payments.where(paymentable_id: params[:id]) + end end diff --git a/app/controllers/api/roles_controller.rb b/app/controllers/api/roles_controller.rb index 9e3f6534a2..f47f56595e 100644 --- a/app/controllers/api/roles_controller.rb +++ b/app/controllers/api/roles_controller.rb @@ -3,12 +3,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Api::RolesController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # get /nonprofits/:nonprofit_id/roles - def index - @roles = current_nonprofit.roles.page(params[:page]).per(params[:per]) - end + # get /nonprofits/:nonprofit_id/roles + def index + @roles = current_nonprofit.roles.page(params[:page]).per(params[:per]) + end end diff --git a/app/controllers/api/subtransaction/payments_controller.rb b/app/controllers/api/subtransaction/payments_controller.rb index b6ba8d268a..1363a2d85d 100644 --- a/app/controllers/api/subtransaction/payments_controller.rb +++ b/app/controllers/api/subtransaction/payments_controller.rb @@ -5,28 +5,28 @@ # A controller for interacting with a transaction's payments class Api::Subtransaction::PaymentsController < Api::ApiController - include Controllers::Api::Transaction::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Api::Transaction::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits supporters - # If not logged in, causes a 401 error - def index - @payments = - current_transaction - .subtransaction - .payments - .order('created DESC') - .page(params[:page]) - .per(params[:per]) - end + # Gets the nonprofits supporters + # If not logged in, causes a 401 error + def index + @payments = + current_transaction + .subtransaction + .payments + .order("created DESC") + .page(params[:page]) + .per(params[:per]) + end - # Gets the a single nonprofit supporter - # If not logged in, causes a 401 error - def show - @payment = - current_transaction - .subtransaction - .payments.find_by(paymentable_id: params[:id]).paymentable - end + # Gets the a single nonprofit supporter + # If not logged in, causes a 401 error + def show + @payment = + current_transaction + .subtransaction + .payments.find_by(paymentable_id: params[:id]).paymentable + end end diff --git a/app/controllers/api/supporter_addresses_controller.rb b/app/controllers/api/supporter_addresses_controller.rb index 032b7a55e0..b15aff1283 100644 --- a/app/controllers/api/supporter_addresses_controller.rb +++ b/app/controllers/api/supporter_addresses_controller.rb @@ -5,24 +5,24 @@ # A controller for interacting with a nonprofit's supporters class Api::SupporterAddressesController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits supporters - # If not logged in, causes a 401 error - def index - @supporter_addresses = - current_nonprofit - .supporters - .where(id: params[:supporter_id]) - .limit(1) - .page(params[:page]).per(params[:per]) - end + # Gets the nonprofits supporters + # If not logged in, causes a 401 error + def index + @supporter_addresses = + current_nonprofit + .supporters + .where(id: params[:supporter_id]) + .limit(1) + .page(params[:page]).per(params[:per]) + end - # Gets the a single nonprofit supporter - # If not logged in, causes a 401 error - def show - @supporter_address = current_nonprofit.supporters.find(params[:id]) - end + # Gets the a single nonprofit supporter + # If not logged in, causes a 401 error + def show + @supporter_address = current_nonprofit.supporters.find(params[:id]) + end end diff --git a/app/controllers/api/supporter_notes_controller.rb b/app/controllers/api/supporter_notes_controller.rb index ca32bae417..81a26743c0 100644 --- a/app/controllers/api/supporter_notes_controller.rb +++ b/app/controllers/api/supporter_notes_controller.rb @@ -5,21 +5,21 @@ # A controller for interacting with a nonprofit's supporters class Api::SupporterNotesController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits supporters - # If not logged in, causes a 401 error - def index - @supporter_notes = current_nonprofit.supporters.find(params[:supporter_id]) - .supporter_notes.order('id DESC') - .page(params[:page]).per(params[:per]) - end + # Gets the nonprofits supporters + # If not logged in, causes a 401 error + def index + @supporter_notes = current_nonprofit.supporters.find(params[:supporter_id]) + .supporter_notes.order("id DESC") + .page(params[:page]).per(params[:per]) + end - # Gets the a single nonprofit supporter - # If not logged in, causes a 401 error - def show - @supporter_note = current_nonprofit.supporters.find(params[:supporter_id]).supporter_notes.find(params[:id]) - end + # Gets the a single nonprofit supporter + # If not logged in, causes a 401 error + def show + @supporter_note = current_nonprofit.supporters.find(params[:supporter_id]).supporter_notes.find(params[:id]) + end end diff --git a/app/controllers/api/supporters_controller.rb b/app/controllers/api/supporters_controller.rb index 410155403e..acb28f6ff4 100644 --- a/app/controllers/api/supporters_controller.rb +++ b/app/controllers/api/supporters_controller.rb @@ -5,19 +5,19 @@ # A controller for interacting with a nonprofit's supporters class Api::SupportersController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits supporters - # If not logged in, causes a 401 error - def index - @supporters = current_nonprofit.supporters.order('id DESC').page(params[:page]).per(params[:per]) - end + # Gets the nonprofits supporters + # If not logged in, causes a 401 error + def index + @supporters = current_nonprofit.supporters.order("id DESC").page(params[:page]).per(params[:per]) + end - # Gets the a single nonprofit supporter - # If not logged in, causes a 401 error - def show - @supporter = current_nonprofit.supporters.find(params[:id]) - end + # Gets the a single nonprofit supporter + # If not logged in, causes a 401 error + def show + @supporter = current_nonprofit.supporters.find(params[:id]) + end end diff --git a/app/controllers/api/tag_definitions_controller.rb b/app/controllers/api/tag_definitions_controller.rb index c9adfb8ca5..28adb6ceb5 100644 --- a/app/controllers/api/tag_definitions_controller.rb +++ b/app/controllers/api/tag_definitions_controller.rb @@ -5,24 +5,24 @@ # A controller for interacting with a nonprofit's custom field definition class Api::TagDefinitionsController < Api::ApiController - include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Nonprofit::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits custom field definitions - # If not logged in, causes a 401 error - def index - @tag_definitions = - current_nonprofit - .tag_definitions - .order('id DESC') - .page(params[:page]) - .per(params[:per]) - end + # Gets the nonprofits custom field definitions + # If not logged in, causes a 401 error + def index + @tag_definitions = + current_nonprofit + .tag_definitions + .order("id DESC") + .page(params[:page]) + .per(params[:per]) + end - # Gets a single custom field definition - # If not logged in, causes a 401 error - def show - @tag_definition = current_nonprofit.tag_definitions.find(params[:id]) - end + # Gets a single custom field definition + # If not logged in, causes a 401 error + def show + @tag_definition = current_nonprofit.tag_definitions.find(params[:id]) + end end diff --git a/app/controllers/api/ticket_levels_controller.rb b/app/controllers/api/ticket_levels_controller.rb index 97307b1448..7645fa7961 100644 --- a/app/controllers/api/ticket_levels_controller.rb +++ b/app/controllers/api/ticket_levels_controller.rb @@ -5,23 +5,23 @@ # A controller for interacting with a nonprofit's supporters class Api::TicketLevelsController < Api::ApiController - include Controllers::Event::Current - include Controllers::Event::Authorization + include Controllers::Event::Current + include Controllers::Event::Authorization - before_action :authenticate_event_editor! + before_action :authenticate_event_editor! - def index - @ticket_levels = - current_event - .ticket_levels - .order('id DESC') - .page(params[:page]) - .per(params[:per]) - end + def index + @ticket_levels = + current_event + .ticket_levels + .order("id DESC") + .page(params[:page]) + .per(params[:per]) + end - # Gets the single event ticket - # If not logged in, causes a 401 error - def show - @ticket_level = current_event.ticket_levels.find(params[:id]) - end + # Gets the single event ticket + # If not logged in, causes a 401 error + def show + @ticket_level = current_event.ticket_levels.find(params[:id]) + end end diff --git a/app/controllers/api/transactions_controller.rb b/app/controllers/api/transactions_controller.rb index f6ae2d574b..3b04d95328 100644 --- a/app/controllers/api/transactions_controller.rb +++ b/app/controllers/api/transactions_controller.rb @@ -5,23 +5,23 @@ # A controller for interacting with a nonprofit's supporters class Api::TransactionsController < Api::ApiController - include Controllers::Api::Transaction::Current - include Controllers::Nonprofit::Authorization - before_action :authenticate_nonprofit_user! + include Controllers::Api::Transaction::Current + include Controllers::Nonprofit::Authorization + before_action :authenticate_nonprofit_user! - # Gets the nonprofits supporters - # If not logged in, causes a 401 error - def index - @transactions = current_nonprofit.transactions.order('created DESC').page(params[:page]).per(params[:per]) - end + # Gets the nonprofits supporters + # If not logged in, causes a 401 error + def index + @transactions = current_nonprofit.transactions.order("created DESC").page(params[:page]).per(params[:per]) + end - # Gets the a single nonprofit supporter - # If not logged in, causes a 401 error - def show - @transaction = current_transaction - end + # Gets the a single nonprofit supporter + # If not logged in, causes a 401 error + def show + @transaction = current_transaction + end - def subtransaction - @subtransaction = current_transaction.subtransaction - end + def subtransaction + @subtransaction = current_transaction.subtransaction + end end diff --git a/app/controllers/api/users_controller.rb b/app/controllers/api/users_controller.rb index 6cc8add642..057308f472 100644 --- a/app/controllers/api/users_controller.rb +++ b/app/controllers/api/users_controller.rb @@ -3,13 +3,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Api::UsersController < Api::ApiController - include Controllers::User::Authorization + include Controllers::User::Authorization - before_action :authenticate_user! + before_action :authenticate_user! - # Returns the current user as JSON - # If not logged in, causes a 401 error - def current - @user = current_user - end + # Returns the current user as JSON + # If not logged in, causes a 401 error + def current + @user = current_user + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7acf1056f1..3a272e0085 100755 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,11 +9,12 @@ class ApplicationController < ActionController::Base around_action :switch_locale protect_from_forgery - private + private + def redirect_to_maintenance if Houdini.maintenance&.active && !current_user unless self.class == Users::SessionsController && - ((Houdini.maintenance.token && params[:maintenance_token] == Houdini.maintenance.token) || params[:format] == 'json') + ((Houdini.maintenance.token && params[:maintenance_token] == Houdini.maintenance.token) || params[:format] == "json") redirect_to Houdini.maintenance.page end end @@ -35,26 +36,26 @@ def json_saved(model, msg = nil) # 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 - result = { status: 422, json: { error: e.message } } + result = {status: 422, json: {error: e.message}} rescue HoudiniError => e logger.info "422: #{e}".red.bold - result = { status: 422, json: { error: e.message } } + result = {status: 422, json: {error: e.message}} rescue ActiveRecord::RecordNotFound => e logger.info "404: #{e}".red.bold - result = { status: 404, 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 } } + 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: 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 @@ -67,11 +68,11 @@ def password_was_confirmed(token) # devise config def after_sign_in_path_for(_resource) - request.env['omniauth.origin'] || session[:previous_url] || root_path + request.env["omniauth.origin"] || session[:previous_url] || root_path end def after_sign_up_path_for(_resource) - request.env['omniauth.origin'] || session[:previous_url] || root_path + request.env["omniauth.origin"] || session[:previous_url] || root_path end def after_update_path_for(_resource) diff --git a/app/controllers/button_debug_controller.rb b/app/controllers/button_debug_controller.rb index a5176c3d5c..bfe4f95c79 100644 --- a/app/controllers/button_debug_controller.rb +++ b/app/controllers/button_debug_controller.rb @@ -5,11 +5,11 @@ 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 diff --git a/app/controllers/campaign_gift_options_controller.rb b/app/controllers/campaign_gift_options_controller.rb index 33abac6b67..a01d68eb31 100644 --- a/app/controllers/campaign_gift_options_controller.rb +++ b/app/controllers/campaign_gift_options_controller.rb @@ -10,26 +10,26 @@ class CampaignGiftOptionsController < ApplicationController def index @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') - render json: { data: @gift_options } + render json: {data: @gift_options} end def show - render json: { data: current_campaign.campaign_gift_options.find(params[:id]) } + render json: {data: current_campaign.campaign_gift_options.find(params[:id])} end def create json_saved CreateCampaignGiftOption.create(current_campaign, campaign_gift_option_params), - 'Gift option successfully created!' + "Gift option successfully created!" end def update - json_saved UpdateCampaignGiftOption.update(current_campaign_gift_option, campaign_gift_option_params), 'Successfully updated' + json_saved UpdateCampaignGiftOption.update(current_campaign_gift_option, campaign_gift_option_params), "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]) + updated_gift_options = UpdateOrder.with_data("campaign_gift_options", params[:data]) render json: updated_gift_options end diff --git a/app/controllers/campaigns/campaign_gift_options_controller.rb b/app/controllers/campaigns/campaign_gift_options_controller.rb index f8e8fda86e..96e21a390c 100644 --- a/app/controllers/campaigns/campaign_gift_options_controller.rb +++ b/app/controllers/campaigns/campaign_gift_options_controller.rb @@ -5,7 +5,7 @@ module Campaigns class CampaignGiftOptionsController < ApplicationController include Controllers::Campaign::Current - include Controllers::Campaign::Authorization + include Controllers::Campaign::Authorization before_action :authenticate_campaign_editor!, only: %i[create destroy update update_order report] @@ -19,29 +19,29 @@ def report def index @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') - render json: { data: @gift_options } + render json: {data: @gift_options} end def show - render json: { data: current_campaign.campaign_gift_options.find(params[:id]) } + render json: {data: current_campaign.campaign_gift_options.find(params[:id])} end def create campaign = current_campaign json_saved CreateCampaignGiftOption.create(campaign, campaign_gift_option_params), - 'Gift option successfully created!' + "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, campaign_gift_option_params), 'Successfully updated' + json_saved UpdateCampaignGiftOption.update(gift_option, campaign_gift_option_params), "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', update_order_params) + updated_gift_options = UpdateOrder.with_data("campaign_gift_options", update_order_params) render json: updated_gift_options end diff --git a/app/controllers/campaigns/donations_controller.rb b/app/controllers/campaigns/donations_controller.rb index c80b6a688c..ee3ab3cfa1 100644 --- a/app/controllers/campaigns/donations_controller.rb +++ b/app/controllers/campaigns/donations_controller.rb @@ -5,18 +5,18 @@ module Campaigns class DonationsController < ApplicationController include Controllers::Campaign::Current - include Controllers::Campaign::Authorization + include Controllers::Campaign::Authorization before_action :authenticate_campaign_editor!, only: [:index] def index respond_to do |format| format.csv do - file_date = Date.today.strftime('%m-%d-%Y') + 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 end diff --git a/app/controllers/campaigns/supporters_controller.rb b/app/controllers/campaigns/supporters_controller.rb index 66580b0101..9bb72ff16c 100644 --- a/app/controllers/campaigns/supporters_controller.rb +++ b/app/controllers/campaigns/supporters_controller.rb @@ -12,7 +12,7 @@ class SupportersController < ApplicationController def index @panels_layout = true @nonprofit = current_nonprofit - @campaign = current_campaign + @campaign = current_campaign respond_to do |format| format.json do diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index b437993113..cd938f8b50 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -3,180 +3,180 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class CampaignsController < ApplicationController # rubocop:disable Metrics/ClassLength - include Controllers::Campaign::Current - include Controllers::Campaign::Authorization - - helper_method :current_campaign_editor? - 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] - - rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue - - def index # rubocop:disable Metrics/AbcSize - @nonprofit = current_nonprofit - 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 - @campaigns = @nonprofit.campaigns.includes(:nonprofit).not_deleted.not_a_child.order('created_at desc') - @deleted_campaigns = @nonprofit.campaigns.includes(:nonprofit).deleted.not_a_child.order('created_at desc') - end - - respond_to do |format| - format.html do - @active_campaigns = @campaigns.active - @past_campaigns = @campaigns.past - @unpublished_campaigns = @campaigns.unpublished - end - - format.json do - @campaigns = @campaigns.limit(params[:limit]) if params[:limit].present? - end - end - end - - def show # rubocop:disable Metrics/AbcSize - @campaign = current_campaign - @timezone = Format::Timezone.to_proxy(current_nonprofit.timezone) - if @campaign.deleted && !current_campaign_editor? - redirect_to nonprofit_path(current_nonprofit) - flash.now[:notice] = t('campaigns.sorry_couldnt_find_campaign') - return - end - @nonprofit = current_nonprofit - @url = Format::Url.concat(root_url, @campaign.url) - - if @campaign.child_campaign? - @parent_campaign = @campaign.parent_campaign - @peer_to_peer_campaign_param = @parent_campaign.id - else - @peer_to_peer_campaign_param = @campaign.id - end - - @campaign_background_image = @campaign.background_image.attached? && - url_for(@campaign.background_image_by_size(:normal)) - end - - def activities - @campaign = current_campaign - render json: QueryDonations.for_campaign_activities(@campaign.id) - end - - def create - @campaign = CreateCampaign.create({ campaign: campaign_params, profile: profile_params }, current_nonprofit) - render 'campaigns/create', campaign: @campaign, status: :created - end - - def update # rubocop:disable Metrics/AbcSize - end_datetime = current_campaign.end_datetime - Time.use_zone(current_nonprofit.timezone || 'UTC') do - end_datetime = Chronic.parse(campaign_params[:end_datetime]) if campaign_params[:end_datetime].present? - end - current_campaign.update!(**campaign_params, end_datetime: end_datetime) - @campaign = current_campaign - flash.now[:notice] = t('campaigns.successfully_updated') - render 'campaigns/update', status: :ok - end - - # post 'nonprofits/:np_id/campaigns/:campaign_id/duplicate' - def duplicate - render_json do - InsertDuplicate.campaign(current_campaign.id, current_user.profile.id) - end - end - - def soft_delete - current_campaign.update(deleted: params[:delete]) - render json: {} - end - - def metrics - render json: QueryCampaignMetrics.on_donations(current_campaign.id) - end - - def timeline - render json: QueryCampaigns.timeline(current_campaign.id) - end - - # returns supporters count as well as total cents for one time, recurring, - # offsite and the previous three combined. used on campaign dashboard - def totals - render json: QueryCampaigns.totals(current_campaign.id) - end - - def name_and_id - render json: QueryCampaigns.name_and_id(current_nonprofit.id) - end - - def peer_to_peer # rubocop:disable Metrics/AbcSize - session[:donor_signup_url] = request.env['REQUEST_URI'] - @nonprofit = Nonprofit.find(params[:npo_id]) - @parent_campaign = Campaign.find(params[:campaign_id]) - - raise ActionController::RoutingError, 'Not Found' if params[:campaign_id].present? && !@parent_campaign - - return unless current_user - - @profile = current_user.profile - - return unless @parent_campaign - - @child_campaign = Campaign.where( - profile_id: @profile.id, - parent_campaign_id: @parent_campaign.id - ).first - end - - private - - def check_nonprofit_status - # raise ActionController::RoutingError, 'Not Found' if !current_role?(:super_admin) && !current_nonprofit.published - end - - def campaign_params # rubocop:disable Metrics/MethodLength - params.require(:campaign).permit( - :name, - :tagline, - :slug, - :total_supporters, - :goal_amount, - :nonprofit_id, - :profile_id, - :main_image, - :remove_main_image, - :background_image, - :remove_background_image, - :banner_image, - :remove_banner_image, - :published, - :video_url, - :vimeo_video_id, - :youtube_video_id, - :summary, - :body, - :goal_amount_dollars, - :show_total_raised, - :show_total_count, - :hide_activity_feed, - :end_datetime, - :deleted, - :hide_goal, - :hide_thermometer, - :hide_title, - :receipt_message, - :hide_custom_amounts, - :parent_campaign_id, - :reason_for_supporting, - :default_reason_for_supporting - ) - end - - def profile_params - params.permit(:profile).permit(:name, :city, :state_code) - end - - def record_invalid_rescue(error) - render json: { errors: error.record.errors.messages }, status: :unprocessable_entity - end + include Controllers::Campaign::Current + include Controllers::Campaign::Authorization + + helper_method :current_campaign_editor? + 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] + + rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue + + def index # rubocop:disable Metrics/AbcSize + @nonprofit = current_nonprofit + 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 + @campaigns = @nonprofit.campaigns.includes(:nonprofit).not_deleted.not_a_child.order("created_at desc") + @deleted_campaigns = @nonprofit.campaigns.includes(:nonprofit).deleted.not_a_child.order("created_at desc") + end + + respond_to do |format| + format.html do + @active_campaigns = @campaigns.active + @past_campaigns = @campaigns.past + @unpublished_campaigns = @campaigns.unpublished + end + + format.json do + @campaigns = @campaigns.limit(params[:limit]) if params[:limit].present? + end + end + end + + def show # rubocop:disable Metrics/AbcSize + @campaign = current_campaign + @timezone = Format::Timezone.to_proxy(current_nonprofit.timezone) + if @campaign.deleted && !current_campaign_editor? + redirect_to nonprofit_path(current_nonprofit) + flash.now[:notice] = t("campaigns.sorry_couldnt_find_campaign") + return + end + @nonprofit = current_nonprofit + @url = Format::Url.concat(root_url, @campaign.url) + + if @campaign.child_campaign? + @parent_campaign = @campaign.parent_campaign + @peer_to_peer_campaign_param = @parent_campaign.id + else + @peer_to_peer_campaign_param = @campaign.id + end + + @campaign_background_image = @campaign.background_image.attached? && + url_for(@campaign.background_image_by_size(:normal)) + end + + def activities + @campaign = current_campaign + render json: QueryDonations.for_campaign_activities(@campaign.id) + end + + def create + @campaign = CreateCampaign.create({campaign: campaign_params, profile: profile_params}, current_nonprofit) + render "campaigns/create", campaign: @campaign, status: :created + end + + def update # rubocop:disable Metrics/AbcSize + end_datetime = current_campaign.end_datetime + Time.use_zone(current_nonprofit.timezone || "UTC") do + end_datetime = Chronic.parse(campaign_params[:end_datetime]) if campaign_params[:end_datetime].present? + end + current_campaign.update!(**campaign_params, end_datetime: end_datetime) + @campaign = current_campaign + flash.now[:notice] = t("campaigns.successfully_updated") + render "campaigns/update", status: :ok + end + + # post 'nonprofits/:np_id/campaigns/:campaign_id/duplicate' + def duplicate + render_json do + InsertDuplicate.campaign(current_campaign.id, current_user.profile.id) + end + end + + def soft_delete + current_campaign.update(deleted: params[:delete]) + render json: {} + end + + def metrics + render json: QueryCampaignMetrics.on_donations(current_campaign.id) + end + + def timeline + render json: QueryCampaigns.timeline(current_campaign.id) + end + + # returns supporters count as well as total cents for one time, recurring, + # offsite and the previous three combined. used on campaign dashboard + def totals + render json: QueryCampaigns.totals(current_campaign.id) + end + + def name_and_id + render json: QueryCampaigns.name_and_id(current_nonprofit.id) + end + + def peer_to_peer # rubocop:disable Metrics/AbcSize + session[:donor_signup_url] = request.env["REQUEST_URI"] + @nonprofit = Nonprofit.find(params[:npo_id]) + @parent_campaign = Campaign.find(params[:campaign_id]) + + raise ActionController::RoutingError, "Not Found" if params[:campaign_id].present? && !@parent_campaign + + return unless current_user + + @profile = current_user.profile + + return unless @parent_campaign + + @child_campaign = Campaign.where( + profile_id: @profile.id, + parent_campaign_id: @parent_campaign.id + ).first + end + + private + + def check_nonprofit_status + # raise ActionController::RoutingError, 'Not Found' if !current_role?(:super_admin) && !current_nonprofit.published + end + + def campaign_params # rubocop:disable Metrics/MethodLength + params.require(:campaign).permit( + :name, + :tagline, + :slug, + :total_supporters, + :goal_amount, + :nonprofit_id, + :profile_id, + :main_image, + :remove_main_image, + :background_image, + :remove_background_image, + :banner_image, + :remove_banner_image, + :published, + :video_url, + :vimeo_video_id, + :youtube_video_id, + :summary, + :body, + :goal_amount_dollars, + :show_total_raised, + :show_total_count, + :hide_activity_feed, + :end_datetime, + :deleted, + :hide_goal, + :hide_thermometer, + :hide_title, + :receipt_message, + :hide_custom_amounts, + :parent_campaign_id, + :reason_for_supporting, + :default_reason_for_supporting + ) + end + + def profile_params + params.permit(:profile).permit(:name, :city, :state_code) + end + + def record_invalid_rescue(error) + render json: {errors: error.record.errors.messages}, status: :unprocessable_entity + end end diff --git a/app/controllers/concerns/controllers/api/transaction/current.rb b/app/controllers/concerns/controllers/api/transaction/current.rb index 18d3a64d8d..10e3b171f9 100644 --- a/app/controllers/concerns/controllers/api/transaction/current.rb +++ b/app/controllers/concerns/controllers/api/transaction/current.rb @@ -3,14 +3,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Api::Transaction::Current - extend ActiveSupport::Concern - include Controllers::Nonprofit::Current + extend ActiveSupport::Concern + include Controllers::Nonprofit::Current - included do - private + included do + private - def current_transaction - @current_transaction ||= current_nonprofit.transactions.find(params[:transaction_id] || params[:id]) - end - end + def current_transaction + @current_transaction ||= current_nonprofit.transactions.find(params[:transaction_id] || params[:id]) + end + end end diff --git a/app/controllers/concerns/controllers/campaign/authorization.rb b/app/controllers/concerns/controllers/campaign/authorization.rb index a63385c6bb..8e88003071 100644 --- a/app/controllers/concerns/controllers/campaign/authorization.rb +++ b/app/controllers/concerns/controllers/campaign/authorization.rb @@ -3,24 +3,24 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Campaign::Authorization - extend ActiveSupport::Concern - include Controllers::Nonprofit::Authorization + extend ActiveSupport::Concern + include Controllers::Nonprofit::Authorization - included do - private + included do + private - def current_campaign_editor? - !params[:preview] && ( - current_nonprofit_user? || - current_role?(:campaign_editor, current_campaign.id) || - current_role?(:super_admin) - ) - end + def current_campaign_editor? + !params[:preview] && ( + current_nonprofit_user? || + current_role?(:campaign_editor, current_campaign.id) || + current_role?(:super_admin) + ) + end - def authenticate_campaign_editor! - return if current_campaign_editor? + def authenticate_campaign_editor! + return if current_campaign_editor? - reject_with_sign_in 'You need to be a campaign editor to do that.' - end - end + reject_with_sign_in "You need to be a campaign editor to do that." + end + end end diff --git a/app/controllers/concerns/controllers/campaign/current.rb b/app/controllers/concerns/controllers/campaign/current.rb index fd6ba624d1..cd0c338084 100644 --- a/app/controllers/concerns/controllers/campaign/current.rb +++ b/app/controllers/concerns/controllers/campaign/current.rb @@ -3,17 +3,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Campaign::Current - extend ActiveSupport::Concern - include Controllers::Nonprofit::Current + extend ActiveSupport::Concern + include Controllers::Nonprofit::Current - included do - private + included do + private - def current_campaign - @campaign ||= FetchCampaign.with_params params, current_nonprofit - raise ActionController::RoutingError, 'Campaign not found' if @campaign.nil? + def current_campaign + @campaign ||= FetchCampaign.with_params params, current_nonprofit + raise ActionController::RoutingError, "Campaign not found" if @campaign.nil? - @campaign - end - end + @campaign + end + end end diff --git a/app/controllers/concerns/controllers/event/authorization.rb b/app/controllers/concerns/controllers/event/authorization.rb index 607cfe4e19..bd20775cad 100644 --- a/app/controllers/concerns/controllers/event/authorization.rb +++ b/app/controllers/concerns/controllers/event/authorization.rb @@ -3,29 +3,29 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Event::Authorization - extend ActiveSupport::Concern - include Controllers::Nonprofit::Authorization + extend ActiveSupport::Concern + include Controllers::Nonprofit::Authorization - included do - private + included do + private - def current_event_admin? - current_nonprofit_admin? - end + def current_event_admin? + current_nonprofit_admin? + end - def current_event_editor? - !params[:preview] && ( - current_nonprofit_user? || current_role?( - :event_editor, - current_event.id - ) || current_role?(:super_admin) - ) - end + def current_event_editor? + !params[:preview] && ( + current_nonprofit_user? || current_role?( + :event_editor, + current_event.id + ) || current_role?(:super_admin) + ) + end - def authenticate_event_editor! - return if current_event_editor? + def authenticate_event_editor! + return if current_event_editor? - reject_with_sign_in 'You need to be the event organizer or a nonprofit administrator before doing that.' - end - end + reject_with_sign_in "You need to be the event organizer or a nonprofit administrator before doing that." + end + end end diff --git a/app/controllers/concerns/controllers/event/current.rb b/app/controllers/concerns/controllers/event/current.rb index 62443e4dcf..0b6e06b7da 100644 --- a/app/controllers/concerns/controllers/event/current.rb +++ b/app/controllers/concerns/controllers/event/current.rb @@ -3,17 +3,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Event::Current - extend ActiveSupport::Concern - include Controllers::Nonprofit::Current + extend ActiveSupport::Concern + include Controllers::Nonprofit::Current - included do - private + included do + private - def current_event - @event ||= FetchEvent.with_params params, current_nonprofit - raise ActionController::RoutingError, 'Event not found' if @event.nil? + def current_event + @event ||= FetchEvent.with_params params, current_nonprofit + raise ActionController::RoutingError, "Event not found" if @event.nil? - @event - end - end + @event + end + end end diff --git a/app/controllers/concerns/controllers/locale.rb b/app/controllers/concerns/controllers/locale.rb index c173bac3ca..087f389412 100644 --- a/app/controllers/concerns/controllers/locale.rb +++ b/app/controllers/concerns/controllers/locale.rb @@ -3,34 +3,34 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Locale - extend ActiveSupport::Concern + extend ActiveSupport::Concern - included do - around_action :switch_locale + included do + around_action :switch_locale - private + private - # We decide on the locale based on the request headers, extracted by 'http_accept_language' gem, - # unless the request comes with a locale param, then we override it. - def switch_locale(&action) - locale = if available_locales.include?(params[:locale]) - params[:locale].tr('-', '_') - else - extract_locale_from_accept_language_header - end - logger.debug "* Locale set to '#{locale}'" - I18n.with_locale(locale, &action) - end + # We decide on the locale based on the request headers, extracted by 'http_accept_language' gem, + # unless the request comes with a locale param, then we override it. + def switch_locale(&action) + locale = if available_locales.include?(params[:locale]) + params[:locale].tr("-", "_") + else + extract_locale_from_accept_language_header + end + logger.debug "* Locale set to '#{locale}'" + I18n.with_locale(locale, &action) + end - def extract_locale_from_accept_language_header - require 'http_accept_language' unless defined? HttpAcceptLanguage - parser = HttpAcceptLanguage::Parser.new(request.env['HTTP_ACCEPT_LANGUAGE']) - matched = parser.language_region_compatible_from(available_locales)&.tr('-', '_') - matched || Houdini.intl.language - end + def extract_locale_from_accept_language_header + require "http_accept_language" unless defined? HttpAcceptLanguage + parser = HttpAcceptLanguage::Parser.new(request.env["HTTP_ACCEPT_LANGUAGE"]) + matched = parser.language_region_compatible_from(available_locales)&.tr("-", "_") + matched || Houdini.intl.language + end - def available_locales - Houdini.intl.available_locales.map { |locale| locale.to_s.tr('_', '-') } - end - end + def available_locales + Houdini.intl.available_locales.map { |locale| locale.to_s.tr("_", "-") } + end + end end diff --git a/app/controllers/concerns/controllers/nonprofit/authorization.rb b/app/controllers/concerns/controllers/nonprofit/authorization.rb index c65035b525..de9b3919c3 100644 --- a/app/controllers/concerns/controllers/nonprofit/authorization.rb +++ b/app/controllers/concerns/controllers/nonprofit/authorization.rb @@ -3,36 +3,36 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Nonprofit::Authorization - extend ActiveSupport::Concern - include Controllers::User::Authorization + extend ActiveSupport::Concern + include Controllers::User::Authorization - included do - helper_method :current_nonprofit_user? + included do + helper_method :current_nonprofit_user? - private + private - def authenticate_nonprofit_user! - reject_with_sign_in unless current_nonprofit_user? - end + def authenticate_nonprofit_user! + reject_with_sign_in unless current_nonprofit_user? + end - def authenticate_nonprofit_admin! - reject_with_sign_in unless current_nonprofit_admin? - end + def authenticate_nonprofit_admin! + reject_with_sign_in unless current_nonprofit_admin? + end - def current_nonprofit_user? - return false if params[:preview] - return false unless current_nonprofit_without_exception + def current_nonprofit_user? + return false if params[:preview] + return false unless current_nonprofit_without_exception - @current_nonprofit_user ||= current_role?( - %i[nonprofit_admin nonprofit_associate], - current_nonprofit_without_exception.id - ) || current_role?(:super_admin) - end + @current_nonprofit_user ||= current_role?( + %i[nonprofit_admin nonprofit_associate], + current_nonprofit_without_exception.id + ) || current_role?(:super_admin) + end - def current_nonprofit_admin? - return false if !current_user || current_user.roles.empty? + def current_nonprofit_admin? + return false if !current_user || current_user.roles.empty? - @current_nonprofit_admin ||= current_role?(:nonprofit_admin, current_nonprofit.id) || current_role?(:super_admin) - end - end + @current_nonprofit_admin ||= current_role?(:nonprofit_admin, current_nonprofit.id) || current_role?(:super_admin) + end + end end diff --git a/app/controllers/concerns/controllers/nonprofit/current.rb b/app/controllers/concerns/controllers/nonprofit/current.rb index 60d47be413..6bd7a37374 100644 --- a/app/controllers/concerns/controllers/nonprofit/current.rb +++ b/app/controllers/concerns/controllers/nonprofit/current.rb @@ -3,19 +3,19 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Nonprofit::Current - extend ActiveSupport::Concern - included do - private + extend ActiveSupport::Concern + included do + private - def current_nonprofit - @nonprofit = current_nonprofit_without_exception - raise ActionController::RoutingError, 'Nonprofit not found' if @nonprofit.nil? + def current_nonprofit + @nonprofit = current_nonprofit_without_exception + raise ActionController::RoutingError, "Nonprofit not found" if @nonprofit.nil? - @nonprofit - end + @nonprofit + end - def current_nonprofit_without_exception - FetchNonprofit.with_params params, administered_nonprofit - end - end + def current_nonprofit_without_exception + FetchNonprofit.with_params params, administered_nonprofit + end + end end diff --git a/app/controllers/concerns/controllers/supporter/current.rb b/app/controllers/concerns/controllers/supporter/current.rb index ca5f59a670..1c5c2e71b1 100644 --- a/app/controllers/concerns/controllers/supporter/current.rb +++ b/app/controllers/concerns/controllers/supporter/current.rb @@ -3,13 +3,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::Supporter::Current - include Controllers::Nonprofit::Current - extend ActiveSupport::Concern - included do - private + include Controllers::Nonprofit::Current + extend ActiveSupport::Concern + included do + private - def current_supporter - current_nonprofit.supporters.find(params[:supporter_id] || params[:id]) - end - end + def current_supporter + current_nonprofit.supporters.find(params[:supporter_id] || params[:id]) + end + end end diff --git a/app/controllers/concerns/controllers/user/authorization.rb b/app/controllers/concerns/controllers/user/authorization.rb index 9267f7ecce..757bfd190c 100644 --- a/app/controllers/concerns/controllers/user/authorization.rb +++ b/app/controllers/concerns/controllers/user/authorization.rb @@ -3,80 +3,80 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::User::Authorization - extend ActiveSupport::Concern - - # rubocop:disable Metrics/BlockLength - # rubocop:disable Layout/LineLength - included do - helper_method :current_role?, :administered_nonprofit - - protected - - def authenticate_user! - reject_with_sign_in unless current_user - end - - def reject_with_sign_in(msg = nil) - respond_to do |format| - format.json { raise AuthenticationError } - format.any { block_with_sign_in(msg) } - end - end - - def block_with_sign_in(msg = nil) - if current_user - redirect_to root_path(redirect_url: request.fullpath) - else - redirect_to new_user_session_path(redirect_url: request.fullpath), flash: { error: msg } - end - end - - def current_role?(role_names, host_id = nil) - return false unless current_user - - role_names = Array(role_names) - QueryRoles.user_has_role?(current_user.id, role_names, host_id) - end - - def authenticate_confirmed_user!(msg = nil) - if !current_user - reject_with_sign_in(msg) - elsif !current_user.confirmed? && !current_role?(%i[super_associate super_admin]) - respond_to do |format| - format.json { raise AuthenticationError } - format.any { redirect_to new_user_confirmation_path, flash: { error: 'You need to confirm your account to do that.' } } - end - end - end - - def authenticate_super_associate! - reject_with_sign_in 'Please login.' unless current_role?(:super_admin) || current_role?(:super_associate) - end - - def authenticate_super_admin! - reject_with_sign_in 'Please login.' unless current_role?(:super_admin) - 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.*}] - - return if request.format.symbol == :json || no_redirects.map { |p| referrer.match(p) }.any? - - session[:previous_url] = referrer - end - - def administered_nonprofit - return nil unless current_user - - ::Nonprofit.where(id: QueryRoles.host_ids(current_user_id, %i[nonprofit_admin nonprofit_associate])).last - end - - def current_user_id - current_user&.id - end - end + extend ActiveSupport::Concern + + # rubocop:disable Metrics/BlockLength + # rubocop:disable Layout/LineLength + included do + helper_method :current_role?, :administered_nonprofit + + protected + + def authenticate_user! + reject_with_sign_in unless current_user + end + + def reject_with_sign_in(msg = nil) + respond_to do |format| + format.json { raise AuthenticationError } + format.any { block_with_sign_in(msg) } + end + end + + def block_with_sign_in(msg = nil) + if current_user + redirect_to root_path(redirect_url: request.fullpath) + else + redirect_to new_user_session_path(redirect_url: request.fullpath), flash: {error: msg} + end + end + + def current_role?(role_names, host_id = nil) + return false unless current_user + + role_names = Array(role_names) + QueryRoles.user_has_role?(current_user.id, role_names, host_id) + end + + def authenticate_confirmed_user!(msg = nil) + if !current_user + reject_with_sign_in(msg) + elsif !current_user.confirmed? && !current_role?(%i[super_associate super_admin]) + respond_to do |format| + format.json { raise AuthenticationError } + format.any { redirect_to new_user_confirmation_path, flash: {error: "You need to confirm your account to do that."} } + end + end + end + + def authenticate_super_associate! + reject_with_sign_in "Please login." unless current_role?(:super_admin) || current_role?(:super_associate) + end + + def authenticate_super_admin! + reject_with_sign_in "Please login." unless current_role?(:super_admin) + 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.*}] + + return if request.format.symbol == :json || no_redirects.map { |p| referrer.match(p) }.any? + + session[:previous_url] = referrer + end + + def administered_nonprofit + return nil unless current_user + + ::Nonprofit.where(id: QueryRoles.host_ids(current_user_id, %i[nonprofit_admin nonprofit_associate])).last + end + + def current_user_id + current_user&.id + end + end end # rubocop:enable all diff --git a/app/controllers/concerns/controllers/x_frame.rb b/app/controllers/concerns/controllers/x_frame.rb index fee68cc959..5c122f0230 100644 --- a/app/controllers/concerns/controllers/x_frame.rb +++ b/app/controllers/concerns/controllers/x_frame.rb @@ -3,14 +3,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Controllers::XFrame - extend ActiveSupport::Concern + extend ActiveSupport::Concern - included do - private + included do + private - # allows the page to be put in a frame, i.e. remove the X-Frame-Options header - def allow_framing - response.headers.delete('X-Frame-Options') if response.headers.has_key?('X-Frame-Options') - end - end + # allows the page to be put in a frame, i.e. remove the X-Frame-Options header + def allow_framing + response.headers.delete("X-Frame-Options") if response.headers.has_key?("X-Frame-Options") + end + end end diff --git a/app/controllers/direct_uploads_controller.rb b/app/controllers/direct_uploads_controller.rb index 70ea06ba47..a436f2bf88 100644 --- a/app/controllers/direct_uploads_controller.rb +++ b/app/controllers/direct_uploads_controller.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class DirectUploadsController < ActiveStorage::DirectUploadsController - include Controllers::Nonprofit::Authorization - skip_before_action :verify_authenticity_token, only: [:create] # rubocop:disable Rails/LexicallyScopedActionFilter - before_action :authenticate_confirmed_user! + include Controllers::Nonprofit::Authorization + skip_before_action :verify_authenticity_token, only: [:create] # rubocop:disable Rails/LexicallyScopedActionFilter + before_action :authenticate_confirmed_user! end diff --git a/app/controllers/emails_controller.rb b/app/controllers/emails_controller.rb index 433ac67daf..820ca7effc 100644 --- a/app/controllers/emails_controller.rb +++ b/app/controllers/emails_controller.rb @@ -8,6 +8,6 @@ class EmailsController < ApplicationController def create email = params[:email] GenericMailer.generic_mail(email[:from_email], email[:from_name], email[:message], email[:subject], email[:to_email], email[:to_name]).deliver_later - render json: { notification: 'Email successfully sent' }, status: :created + render json: {notification: "Email successfully sent"}, status: :created end end diff --git a/app/controllers/event_discounts_controller.rb b/app/controllers/event_discounts_controller.rb index adf0a0b457..0603954b1e 100644 --- a/app/controllers/event_discounts_controller.rb +++ b/app/controllers/event_discounts_controller.rb @@ -8,7 +8,7 @@ class EventDiscountsController < ApplicationController before_action :authenticate_event_editor!, except: [:index] def create - render json: { data: {event_discount: current_event.event_discounts.create(event_discount_params[:event_discount]) } } + render json: {data: {event_discount: current_event.event_discounts.create(event_discount_params[:event_discount])}} end def index @@ -16,9 +16,8 @@ def index end def update - current_event_discount.update event_discount_params[:event_discount] - render json: { status: 200, data: current_event_discount } + render json: {status: 200, data: current_event_discount} end def destroy @@ -26,7 +25,7 @@ def destroy end private - + def current_event_discount current_event.event_discounts.find(params[:id]) end diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index ab9ed70eba..03d35be638 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -16,11 +16,11 @@ def index end def listings - render json: QueryEventMetrics.for_listings('nonprofit', current_nonprofit.id, params) + render json: QueryEventMetrics.for_listings("nonprofit", current_nonprofit.id, params) end def show - @event = params[:event_slug] ? Event.find_by_slug!(params[:event_slug]) : Event.find_by_id!(params[:id]) + @event = params[:event_slug] ? Event.find_by_slug!(params[:event_slug]) : Event.find(params[:id]) @event_background_image = @event.background_image.attached? && url_for(@event.background_image_by_size(:normal)) @nonprofit = @event.nonprofit if @event.deleted && !current_event_editor? @@ -35,27 +35,27 @@ def create render_json do start_datetime = nil end_datetime = nil - Time.use_zone(current_nonprofit.timezone || 'UTC') do + Time.use_zone(current_nonprofit.timezone || "UTC") do start_datetime = Chronic.parse(event_params[:start_datetime]) if event_params[:start_datetime].present? end_datetime = Chronic.parse(event_params[:end_datetime]) if event_params[:end_datetime].present? end event = current_nonprofit.events.create!(**event_params, start_datetime: start_datetime, end_datetime: end_datetime) - flash[:notice] = 'Your draft event has been created! Well done.' - { url: "/events/#{event.slug}" } + flash[:notice] = "Your draft event has been created! Well done." + {url: "/events/#{event.slug}"} end end def update start_datetime = current_event.start_datetime end_datetime = current_event.end_datetime - Time.use_zone(current_nonprofit.timezone || 'UTC') do + Time.use_zone(current_nonprofit.timezone || "UTC") do start_datetime = Chronic.parse(event_params[:start_datetime]) if event_params[:start_datetime].present? end_datetime = Chronic.parse(event_params[:end_datetime]) if event_params[:end_datetime].present? end current_event.update!(**event_params, start_datetime: start_datetime, end_datetime: end_datetime) @event = current_event - flash[:notice] = 'Successfully updated' + flash[:notice] = "Successfully updated" end # post 'nonprofits/:np_id/events/:event_id/duplicate' @@ -70,7 +70,7 @@ def activities def soft_delete current_event.update_attribute(:deleted, params[:delete]) render json: {} - end + end def metrics render json: QueryEventMetrics.with_event_ids([current_event.id]).first @@ -80,7 +80,7 @@ def stats @event = current_event @url = Format::Url.concat(root_url, @event.url) @event_background_image = @event.background_image.attached? && url_for(@event.background_image_by_size(:normal)) - render layout: 'layouts/embed' + render layout: "layouts/embed" end def name_and_id @@ -94,6 +94,6 @@ def event_params end def record_invalid_rescue(error) - render json: { errors: error.record.errors.full_messages }, status: :unprocessable_entity + render json: {errors: error.record.errors.full_messages}, status: :unprocessable_entity end end diff --git a/app/controllers/image_attachments_controller.rb b/app/controllers/image_attachments_controller.rb index 5270d77014..963535634f 100644 --- a/app/controllers/image_attachments_controller.rb +++ b/app/controllers/image_attachments_controller.rb @@ -9,7 +9,7 @@ def create # http://editor.froala.com/server-integrations/php-image-upload @image = ImageAttachment.new(clean_params_create) if @image.save - render json: { link: url_for(@image.file) } + render json: {link: url_for(@image.file)} else render json: @image.errors.full_messages, status: :unprocessable_entity end @@ -26,6 +26,7 @@ def remove end private + def clean_params_create params.require(:file) end diff --git a/app/controllers/nonprofits/activities_controller.rb b/app/controllers/nonprofits/activities_controller.rb index a162b9aebf..8b168ccb03 100644 --- a/app/controllers/nonprofits/activities_controller.rb +++ b/app/controllers/nonprofits/activities_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class ActivitiesController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! # get /nonprofits/:nonprofit_id/supporters/:supporter_id/activities diff --git a/app/controllers/nonprofits/bank_accounts_controller.rb b/app/controllers/nonprofits/bank_accounts_controller.rb index 770fafb5ac..bf09d5d8ad 100644 --- a/app/controllers/nonprofits/bank_accounts_controller.rb +++ b/app/controllers/nonprofits/bank_accounts_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class BankAccountsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_admin! @@ -15,7 +15,7 @@ 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 + render json: ["Please confirm your password"], status: :unprocessable_entity end end @@ -31,10 +31,10 @@ def confirm bank_account = nonprofit.bank_account if params[:token] == bank_account.confirmation_token bank_account.update_attribute(:pending_verification, false) - flash[:notice] = 'Your bank account is now confirmed!' + flash[:notice] = "Your bank account is now confirmed!" redirect_to nonprofits_payouts_path(nonprofit) else - redirect_to(nonprofits_donations_path(nonprofit), flash: { error: 'We could not confirm this bank account. Please follow the exact link provided in the confirmation email.' }) + redirect_to(nonprofits_donations_path(nonprofit), flash: {error: "We could not confirm this bank account. Please follow the exact link provided in the confirmation email."}) end end @@ -50,10 +50,10 @@ def cancel bank_account = nonprofit.bank_account if params[:token] == bank_account.confirmation_token bank_account.destroy - flash[:notice] = 'Your bank account has been removed.' + flash[:notice] = "Your bank account has been removed." redirect_to nonprofits_donations_path(nonprofit) else - redirect_to(nonprofits_donations_path(nonprofit), flash: { error: 'We could not remove this bank account. Please follow the exact link provided in the email.' }) + redirect_to(nonprofits_donations_path(nonprofit), flash: {error: "We could not remove this bank account. Please follow the exact link provided in the email."}) end end diff --git a/app/controllers/nonprofits/button_controller.rb b/app/controllers/nonprofits/button_controller.rb index 5ba9b2da07..bdc95d3b76 100644 --- a/app/controllers/nonprofits/button_controller.rb +++ b/app/controllers/nonprofits/button_controller.rb @@ -5,14 +5,14 @@ module Nonprofits class ButtonController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization 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 + end def basic @nonprofit = current_nonprofit diff --git a/app/controllers/nonprofits/charges_controller.rb b/app/controllers/nonprofits/charges_controller.rb index d022b8e507..7796698fcc 100644 --- a/app/controllers/nonprofits/charges_controller.rb +++ b/app/controllers/nonprofits/charges_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class ChargesController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user!, only: :index diff --git a/app/controllers/nonprofits/custom_field_definitions_controller.rb b/app/controllers/nonprofits/custom_field_definitions_controller.rb index 4e0deb643f..e093d4e9e0 100644 --- a/app/controllers/nonprofits/custom_field_definitions_controller.rb +++ b/app/controllers/nonprofits/custom_field_definitions_controller.rb @@ -10,9 +10,9 @@ class CustomFieldDefinitionsController < ApplicationController def index @custom_field_definitions = current_nonprofit - .custom_field_definitions - .order('id DESC') - .not_deleted + .custom_field_definitions + .order("id DESC") + .not_deleted end def create @@ -28,10 +28,9 @@ def destroy private def custom_field_definition_params - params.require(:custom_field_definition).permit( :name) + params.require(:custom_field_definition).permit(:name) end - def current_custom_field_definition current_nonprofit.custom_field_definitions.find(params[:id]) end diff --git a/app/controllers/nonprofits/custom_field_joins_controller.rb b/app/controllers/nonprofits/custom_field_joins_controller.rb index 6faa8e7ee6..9c8d1891ea 100644 --- a/app/controllers/nonprofits/custom_field_joins_controller.rb +++ b/app/controllers/nonprofits/custom_field_joins_controller.rb @@ -5,14 +5,14 @@ module Nonprofits class CustomFieldJoinsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! def index @custom_field_joins = current_nonprofit - .supporters.find(custom_field_params[:supporter_id]) - .custom_field_joins - .order('created_at DESC') + .supporters.find(custom_field_params[:supporter_id]) + .custom_field_joins + .order("created_at DESC") end # used for modify a single supporter's custom fields or a group of @@ -23,10 +23,10 @@ def modify return end - if custom_field_params[:selecting_all] - supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, custom_field_params[:query]).select('supporters.id').execute.map { |h| h['id'] } + supporter_ids = if custom_field_params[:selecting_all] + QuerySupporters.full_filter_expr(current_nonprofit.id, custom_field_params[:query]).select("supporters.id").execute.map { |h| h["id"] } else - supporter_ids = custom_field_params[:supporter_ids]. map(&:to_i) + custom_field_params[:supporter_ids].map(&:to_i) end render InsertCustomFieldJoins.in_bulk(current_nonprofit.id, supporter_ids, custom_field_params[:custom_fields]) diff --git a/app/controllers/nonprofits/donations_controller.rb b/app/controllers/nonprofits/donations_controller.rb index 49d2bb69d8..3b9ac72db5 100644 --- a/app/controllers/nonprofits/donations_controller.rb +++ b/app/controllers/nonprofits/donations_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class DonationsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user!, only: %i[index update] before_action :authenticate_campaign_editor!, only: [:create_offsite] @@ -17,9 +17,9 @@ def index # post /nonprofits/:nonprofit_id/donations def create - if params[:token] - @result = InsertDonation.with_stripe(donations_params.merge(token:params[:token]), current_user) - + if params[:token] + @result = InsertDonation.with_stripe(donations_params.merge(token: params[:token]), current_user) + elsif params[:direct_debit_detail_id] render JsonResp.new(donations_params) do |_data| requires(:amount).as_int @@ -29,10 +29,9 @@ def create optional(:dedication, :designation).as_string optional(:campaign_id, :event_id).as_int end.when_valid do |data| - InsertDonation.with_sepa(data) end - end + end end # post /nonprofits/:nonprofit_id/donations/create_offsite @@ -44,7 +43,7 @@ def create_offsite optional(:campaign_id, :event_id).as_int optional(:date).as_date optional(:offsite_payment).nested do - optional(:kind).one_of('cash', 'check') + optional(:kind).one_of("cash", "check") optional(:check_number) end end.when_valid { |data| InsertDonation.offsite(data) } @@ -66,7 +65,7 @@ def followup def current_campaign if !@campaign && donations_params && donations_params[:campaign_id] - @campaign = Campaign.where('id = ? ', donations_params[:campaign_id]).first + @campaign = Campaign.where("id = ? ", donations_params[:campaign_id]).first end @campaign end @@ -77,11 +76,12 @@ def current_campaign_editor? def authenticate_campaign_editor! unless current_campaign_editor? - block_with_sign_in 'You need to be a campaign editor to do that.' + block_with_sign_in "You need to be a campaign editor to do that." end end private + def donations_params params.require(:donation).permit(:date, :amount, :recurring, :anonymous, :email, :designation, :dedication, :comment, :origin_url, :nonprofit_id, :card_id, :supporter_id, :profile_id, :campaign_id, :payment_id, :event_id, :direct_debit_detail_id, :token) end diff --git a/app/controllers/nonprofits/email_lists_controller.rb b/app/controllers/nonprofits/email_lists_controller.rb index 367bca2e0a..a75a7d87f8 100644 --- a/app/controllers/nonprofits/email_lists_controller.rb +++ b/app/controllers/nonprofits/email_lists_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class EmailListsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! diff --git a/app/controllers/nonprofits/imports_controller.rb b/app/controllers/nonprofits/imports_controller.rb index ca00ecc412..b95d654656 100644 --- a/app/controllers/nonprofits/imports_controller.rb +++ b/app/controllers/nonprofits/imports_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class ImportsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! # post /nonprofits/:nonprofit_id/imports diff --git a/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb b/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb index c22b29427b..4c5cc2d1ec 100644 --- a/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb +++ b/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class MiscellaneousNpInfosController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization helper_method :current_nonprofit_user? before_action :authenticate_nonprofit_user! diff --git a/app/controllers/nonprofits/nonprofit_keys_controller.rb b/app/controllers/nonprofits/nonprofit_keys_controller.rb index 5335b39ce0..1e516831df 100644 --- a/app/controllers/nonprofits/nonprofit_keys_controller.rb +++ b/app/controllers/nonprofits/nonprofit_keys_controller.rb @@ -6,7 +6,7 @@ module Nonprofits class NonprofitKeysController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! # get /nonprofits/:nonprofit_id/nonprofit_keys @@ -19,7 +19,7 @@ def index # 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']}" + 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 @@ -32,10 +32,10 @@ def mailchimp_landing 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' + redirect_to "/settings" return end - redirect_to nonprofits_supporters_path @nonprofit, 'show-modal' => 'mailchimpSettingsModal' - end + redirect_to nonprofits_supporters_path @nonprofit, "show-modal" => "mailchimpSettingsModal" end + end end diff --git a/app/controllers/nonprofits/payments_controller.rb b/app/controllers/nonprofits/payments_controller.rb index 40e14db928..bc4c36d41e 100644 --- a/app/controllers/nonprofits/payments_controller.rb +++ b/app/controllers/nonprofits/payments_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class PaymentsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! @@ -29,7 +29,7 @@ def export @nonprofit = current_nonprofit @user = current_user_id ExportPayments.initiate_export(@nonprofit.id, params, @user) - rescue StandardError => e + rescue => e e end if e.nil? @@ -56,7 +56,7 @@ def destroy @payment = current_nonprofit.payments.find(params[:id]) if @payment.offsite_payment.nil? render json: {}, status: :unprocessable_entity - return # You may only destroy offline payments + nil # You may only destroy offline payments else @payment.donation.destroy if @payment.donation.present? @payment.tickets.destroy_all if @payment.tickets.present? diff --git a/app/controllers/nonprofits/payouts_controller.rb b/app/controllers/nonprofits/payouts_controller.rb index 6a29d8c6b6..e23bb00dfa 100644 --- a/app/controllers/nonprofits/payouts_controller.rb +++ b/app/controllers/nonprofits/payouts_controller.rb @@ -5,34 +5,34 @@ module Nonprofits class PayoutsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization 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: payout_params[:before_date]) - - if payout['failure_message'].present? - flash[:notice] = "The payout failed: #{payout['failure_message']}" + 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: payout_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.' + 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') + @payouts = @nonprofit.payouts.order("created_at DESC") balances = QueryPayments.nonprofit_balances(params[:nonprofit_id]) - @available_total = balances['available_gross'] - @pending_total = balances['pending_gross'] + @available_total = balances["available_gross"] + @pending_total = balances["pending_gross"] @can_make_payouts = @nonprofit.can_make_payouts end @@ -43,7 +43,7 @@ def show 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')}" + filename = "payout-#{payout.created_at.strftime("%m-%d-%Y")}" send_data(Format::Csv.from_vectors(payments), filename: "#{filename}.csv") end end @@ -54,6 +54,5 @@ def show def payout_params params.permit(:before_date) end - - end + end end diff --git a/app/controllers/nonprofits/recurring_donations_controller.rb b/app/controllers/nonprofits/recurring_donations_controller.rb index e2cb14587e..5e2dae6db6 100644 --- a/app/controllers/nonprofits/recurring_donations_controller.rb +++ b/app/controllers/nonprofits/recurring_donations_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class RecurringDonationsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user!, except: [:create] @@ -44,7 +44,7 @@ def export params[:root_url] = root_url ExportRecurringDonations.initiate_export(@nonprofit.id, params, current_user.id) - rescue StandardError => e + rescue => e e end if e.nil? @@ -57,8 +57,8 @@ def export def show @recurring_donation = current_recurring_donation - respond_to do |format| - format.json do + respond_to do |format| + format.json do render locals: {recurring_donation: @recurring_donation} end end diff --git a/app/controllers/nonprofits/refunds_controller.rb b/app/controllers/nonprofits/refunds_controller.rb index ab205c1ef6..9d2828a223 100644 --- a/app/controllers/nonprofits/refunds_controller.rb +++ b/app/controllers/nonprofits/refunds_controller.rb @@ -5,13 +5,13 @@ module Nonprofits class RefundsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! # post /charges/:charge_id/refunds def create - charge = current_nonprofit.charges.find(params[:charge_id]) + charge = current_nonprofit.charges.find(params[:charge_id]) charge_params = params.require(:refund).permit(:amount).merge(user_id: current_user.id) render_json { InsertRefunds.with_stripe(charge, charge_params) } end diff --git a/app/controllers/nonprofits/reports_controller.rb b/app/controllers/nonprofits/reports_controller.rb index c80bb58c7a..c021b135c2 100644 --- a/app/controllers/nonprofits/reports_controller.rb +++ b/app/controllers/nonprofits/reports_controller.rb @@ -5,7 +5,7 @@ module Nonprofits class ReportsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization before_action :authenticate_nonprofit_user! def end_of_year diff --git a/app/controllers/nonprofits/supporter_notes_controller.rb b/app/controllers/nonprofits/supporter_notes_controller.rb index 4fdf43bc53..53bfd9a280 100644 --- a/app/controllers/nonprofits/supporter_notes_controller.rb +++ b/app/controllers/nonprofits/supporter_notes_controller.rb @@ -16,8 +16,10 @@ def create # put /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id def update - render_json { UpdateSupporterNotes.update(current_supporter_note, - supporter_note_content.merge({user_id: current_user&.id})) } + render_json { + UpdateSupporterNotes.update(current_supporter_note, + supporter_note_content.merge({user_id: current_user&.id})) + } end # delete /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id @@ -26,7 +28,7 @@ def destroy end private - + def current_supporter_note current_supporter.supporter_notes.includes(:activities).find(params[:id]) end diff --git a/app/controllers/nonprofits/supporters_controller.rb b/app/controllers/nonprofits/supporters_controller.rb index d1e31e3d3a..9446a755da 100644 --- a/app/controllers/nonprofits/supporters_controller.rb +++ b/app/controllers/nonprofits/supporters_controller.rb @@ -21,7 +21,7 @@ def index end format.csv do - file_date = Date.today.strftime('%m-%d-%Y') + 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 @@ -33,7 +33,7 @@ def export @nonprofit = current_nonprofit @user = current_user_id ExportSupporters.initiate_export(@nonprofit.id, params, @user) - rescue StandardError => e + rescue => e e end if e.nil? @@ -51,7 +51,7 @@ def index_metrics end def show - render json: { data: QuerySupporters.for_crm_profile(params[:nonprofit_id], [params[:id]]).first } + render json: {data: QuerySupporters.for_crm_profile(params[:nonprofit_id], [params[:id]]).first} end def email_address @@ -59,15 +59,13 @@ def email_address end def full_contact - begin - if current_supporter.method_defined? :full_contact_infos && (fc = current_supporter.full_contact_infos.first) - render json: { full_contact: QueryFullContactInfos.fetch_associated_tables(fc.id) } - else - render json: { full_contact: nil } - end - rescue - render json: { full_contact: nil } + if current_supporter.method_defined?(fc = current_supporter.full_contact_infos.first) + render json: {full_contact: QueryFullContactInfos.fetch_associated_tables(fc.id)} + else + render json: {full_contact: nil} end + rescue + render json: {full_contact: nil} end def info_card @@ -85,10 +83,10 @@ def update 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'] } + supporter_ids = if params[:selecting_all] + 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) + params[:supporter_ids].map(&:to_i) end render_json { UpdateSupporter.bulk_delete(current_nonprofit.id, supporter_ids) } end diff --git a/app/controllers/nonprofits/tag_joins_controller.rb b/app/controllers/nonprofits/tag_joins_controller.rb index dcf59ad270..0b3162651a 100644 --- a/app/controllers/nonprofits/tag_joins_controller.rb +++ b/app/controllers/nonprofits/tag_joins_controller.rb @@ -5,22 +5,22 @@ module Nonprofits class TagJoinsController < ApplicationController include Controllers::Nonprofit::Current - include Controllers::Nonprofit::Authorization + include Controllers::Nonprofit::Authorization 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 - 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 = if params[:selecting_all] + 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) + params[:supporter_ids].map(&:to_i) end render InsertTagJoins.in_bulk(current_nonprofit.id, current_user.profile.id, supporter_ids, params[:tags]) end diff --git a/app/controllers/nonprofits_controller.rb b/app/controllers/nonprofits_controller.rb index 2e555cfac3..7925ff17a8 100755 --- a/app/controllers/nonprofits_controller.rb +++ b/app/controllers/nonprofits_controller.rb @@ -9,7 +9,7 @@ class NonprofitsController < ApplicationController 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!, if: proc {|c| ( c.action_name == "destroy") || (c.action_name == "show" && !current_nonprofit.published) } + before_action :authenticate_super_admin!, if: proc { |c| (c.action_name == "destroy") || (c.action_name == "show" && !current_nonprofit.published) } # we have to allow nonprofits/:id/donation and nonprofits/:id/btn to be framed after_action :allow_framing, only: %i[donate btn] @@ -21,16 +21,16 @@ def show @url = Format::Url.concat(root_url, @nonprofit.url) @supporters = @nonprofit.supporters.not_deleted - events = @nonprofit.events.not_deleted.order('start_datetime desc') - campaigns = @nonprofit.campaigns.not_deleted.not_a_child.order('created_at desc') + 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? - @nonprofit_background_image = @nonprofit.background_image.attached? ? - url_for(@nonprofit.background_image_by_size(:normal)) : + @nonprofit_background_image = @nonprofit.background_image.attached? ? + url_for(@nonprofit.background_image_by_size(:normal)) : url_for(Houdini.defaults.image.nonprofit) respond_to do |format| @@ -52,36 +52,35 @@ def dashboard_todos end def update - flash[:notice] = 'Update successful!' + flash[:notice] = "Update successful!" current_nonprofit.update! nonprofit_params.except(:verification_status) - @current_nonprofit render :show end def destroy current_nonprofit.destroy - flash[:notice] = 'Nonprofit removed' + flash[:notice] = "Nonprofit removed" render json: {} end # get /nonprofits/:id/donate def donate @nonprofit = current_nonprofit - @referer = params[:origin] || request.env['HTTP_REFERER'] + @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' } } + 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' } } + respond_to { |format| format.html { render layout: "layouts/embed" } } end # post /nonprofits/:id/supporter_with_tag @@ -126,8 +125,8 @@ def countries_list(locale) if Houdini.intl.all_countries countries = all_countries.select { |code, _name| Houdini.intl.all_countries.include? code } - countries = countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } - countries + countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } + else all_countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 9eeae14be3..e5dc393484 100755 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -11,12 +11,12 @@ class ProfilesController < ApplicationController # 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}")) + @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 + flash[:notice] = "That user does not have a public profile." + redirect_to(request.env["HTTP_REFERER"] || root_url) + nil end end @@ -33,33 +33,33 @@ 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 @profile = if current_role?(:super_admin) # can update other profiles - Profile.find(params[:id]) - else - current_user.profile - end + Profile.find(params[:id]) + else + current_user.profile + end @profile.update(profile_params) - json_saved @profile, 'Profile updated' + 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) + !current_role?(:super_admin) && + (!current_user || + !current_user.profile || + current_user.profile.id != params[:id].to_i) block_with_sign_in end end diff --git a/app/controllers/recurring_donations_controller.rb b/app/controllers/recurring_donations_controller.rb index 82f078b255..7e4e8578ef 100644 --- a/app/controllers/recurring_donations_controller.rb +++ b/app/controllers/recurring_donations_controller.rb @@ -5,56 +5,56 @@ 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) + 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) 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 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 + if params[:edit_token] != @data["recurring_donation"]["edit_token"] + render json: {error: "Invalid token"}, status: :unprocessable_entity else - updated = UpdateRecurringDonations.cancel(params[:id], current_user ? current_user.email : @data['supporter']['email']) + updated = UpdateRecurringDonations.cancel(params[:id], current_user ? current_user.email : @data["supporter"]["email"]) render json: updated end end def update data = QueryRecurringDonations.fetch_for_edit params[:id] - if data && params[:edit_token] == data['recurring_donation']['edit_token'] - data['supporter'] = UpdateSupporter.general_info(params[:supporter][:id], params[:supporter]) if params[:supporter] - data['recurring_donation'] ||= {} - data['recurring_donation'] = UpdateRecurringDonations.update_card_id(data['recurring_donation'], params[:token]) if params[:token] - data['recurring_donation'] = UpdateRecurringDonations.update_paydate(data['recurring_donation'], params[:paydate]) if params[:paydate] + if data && params[:edit_token] == data["recurring_donation"]["edit_token"] + data["supporter"] = UpdateSupporter.general_info(params[:supporter][:id], params[:supporter]) if params[:supporter] + data["recurring_donation"] ||= {} + data["recurring_donation"] = UpdateRecurringDonations.update_card_id(data["recurring_donation"], params[:token]) if params[:token] + 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 def update_amount - recurring_donation = RecurringDonation.where('id = ?', params[:id]).first - if recurring_donation && params[:edit_token] == recurring_donation['edit_token'] + recurring_donation = RecurringDonation.where("id = ?", params[:id]).first + if recurring_donation && params[:edit_token] == recurring_donation["edit_token"] begin amount_response = UpdateRecurringDonations.update_amount(recurring_donation, 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 StandardError => e + rescue => 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 diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 86a07cfe44..0ce56f9a70 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -10,19 +10,19 @@ class RolesController < ApplicationController def create role = Role.create_for_nonprofit(role_params[:name].to_sym, role_params[:email], FetchNonprofit.with_params(params)) - json_saved role, 'User successfully added!' + 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) if roles.empty? - render json: { error: "We couldn't find that admin" }, status: :unprocessable_entity + render json: {error: "We couldn't find that admin"}, status: :unprocessable_entity else roles.destroy_all - flash[:notice] = 'User successfully removed' + flash[:notice] = "User successfully removed" render json: {} - end + end end private diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index ca4388c961..2f0b389755 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -17,12 +17,12 @@ def index end @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 + 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 @profile = @user.profile diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index 0e1bde6089..cf89bb24b6 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -3,23 +3,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class StaticController < ApplicationController - layout 'layouts/static' + layout "layouts/static" def terms_and_privacy - @theme = 'minimal' + @theme = "minimal" end def ccs - begin - Houdini.ccs.retrieve_ccs do |ccs| - if ccs.is_a? String - redirect_to ccs - else - send_data(ccs, type: 'application/gzip') - end + Houdini.ccs.retrieve_ccs do |ccs| + if ccs.is_a? String + redirect_to ccs + else + send_data(ccs, type: "application/gzip") end - rescue => e - render body: nil, status: 500 end + rescue + render body: nil, status: 500 end end diff --git a/app/controllers/super_admins_controller.rb b/app/controllers/super_admins_controller.rb index b7d54bb41c..4341b6aae8 100644 --- a/app/controllers/super_admins_controller.rb +++ b/app/controllers/super_admins_controller.rb @@ -3,11 +3,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE 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) @@ -20,24 +21,24 @@ def search_profiles def search_fullcontact begin result = FullContact.person(email: params[:search]) - rescue Exception => e - result = '' + rescue Exception + result = "" end render json: [result] end def resend_user_confirmation ParamValidation.new(params || {}, - profile_id: { required: true, is_integer: true }) + profile_id: {required: true, is_integer: true}) - profile = Profile.includes(:user).where('id = ?', params[:profile_id]).first + profile = Profile.includes(:user).where("id = ?", params[:profile_id]).first 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 @@ -46,14 +47,14 @@ def recurring_donations_without_cards format.html format.csv do 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'] + 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 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] + 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 @@ -66,12 +67,12 @@ def export_supporters_with_rds nonprofit = params[:np] ids = params[:ids] results = QuerySupporters.for_export(nonprofit, ids: ids) - results[0].push('Management URLS') + results[0].push("Management URLS") results.drop(1).each do |row| recurring_donations = 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(recurring_donations) 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 diff --git a/app/controllers/ticket_levels_controller.rb b/app/controllers/ticket_levels_controller.rb index c68f1f8cdd..a7f177e937 100644 --- a/app/controllers/ticket_levels_controller.rb +++ b/app/controllers/ticket_levels_controller.rb @@ -10,7 +10,7 @@ class TicketLevelsController < ApplicationController def index event_id = current_event.id - render json: { data: QueryTicketLevels.with_event_id(event_id, current_role?(:event_editor, event_id) || current_role?(:super_admin) || current_role?(:nonprofit_admin, current_event.nonprofit_id)) } + render json: {data: QueryTicketLevels.with_event_id(event_id, current_role?(:event_editor, event_id) || current_role?(:super_admin) || current_role?(:nonprofit_admin, current_event.nonprofit_id))} end def show @@ -19,25 +19,25 @@ def show def create ticket_level = current_event.ticket_levels.create ticket_level_params - json_saved ticket_level, 'Ticket level created!' + json_saved ticket_level, "Ticket level created!" end def update current_ticket_level.update ticket_level_params - json_saved current_ticket_level, 'Ticket level updated' + 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}]} def update_order - updated_ticket_levels = UpdateOrder.with_data('ticket_levels', params[:data]) + updated_ticket_levels = UpdateOrder.with_data("ticket_levels", params[:data]) render json: updated_ticket_levels end def destroy current_ticket_level.destroy render json: {} - end + end private diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 3b7c1dd6f6..6cedde8e7f 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -12,7 +12,7 @@ class TicketsController < ApplicationController # post /nonprofits/:nonprofit_id/events/:event_id/tickets def create - authenticate_event_editor! if params[:kind] == 'offsite' + authenticate_event_editor! if params[:kind] == "offsite" render_json do params[:current_user] = current_user InsertTickets.create(params) @@ -35,7 +35,7 @@ def index respond_to do |format| format.html format.csv do - file_date = Date.today.strftime('%m-%d-%Y') + 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") diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb index 2565cd9f5d..4a5ac168e8 100644 --- a/app/controllers/users/confirmations_controller.rb +++ b/app/controllers/users/confirmations_controller.rb @@ -8,7 +8,7 @@ def show @user = User.confirm_by_token(params[:confirmation_token]) if !@user.auto_generated || !@user.valid? - flash[:notice] = 'We successfully confirmed your account' + flash[:notice] = "We successfully confirmed your account" redirect_to session[:donor_signup_url] || root_url else respond_to do |format| @@ -27,7 +27,7 @@ def confirm @user = User.find(params[:id]) if @user.valid? && @user.update(params[:user].except(:confirmation_token)) - flash[:notice] = 'Your account is all set!' + flash[:notice] = "Your account is all set!" sign_in @user redirect_to session[:donor_signup_url] || root_url else @@ -36,6 +36,6 @@ def confirm end def is_confirmed - render json: { is_confirmed: User.find(params[:user_id]).confirmed? } + render json: {is_confirmed: User.find(params[:user_id]).confirmed?} end end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index 50470164b3..b12f570bb1 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -36,25 +36,26 @@ def update errs = current_user.errors.full_messages else success = false - errs = { password: :incorrect } + errs = {password: :incorrect} end if success - if params[:user][:email].present? - flash[:notice] = 'We need to confirm your new email address. Check your inbox for a confirmation link.' + flash[:notice] = if params[:user][:email].present? + "We need to confirm your new email address. Check your inbox for a confirmation link." else - flash[:notice] = 'Account updated!' + "Account updated!" end 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 - private + private + def clean_params - params.permit(:user => [:name, :email, :password_confirmation, :password]) + params.permit(user: [:name, :email, :password_confirmation, :password]) end end diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index baececd06e..7d6698fd12 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -3,20 +3,20 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Users::SessionsController < Devise::SessionsController - layout 'layouts/material', only: :new + layout "layouts/material", only: :new respond_to :json, only: [:new, :create] skip_before_action :verify_authenticity_token - # POST /resource/sign_in - # we override becuase we don't want to redirect when a session is created - def create + # POST /resource/sign_in + # we override becuase we don't want to redirect when a session is created + def create self.resource = warden.authenticate!(auth_options) set_flash_message!(:notice, :signed_in) sign_in(resource_name, resource) yield resource if block_given? @user = resource - 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 @@ -24,7 +24,7 @@ def confirm_auth token = SecureRandom.uuid session[:pw_token] = token session[:pw_timestamp] = Time.current.to_s - render json: { token: token }, status: :ok + render json: {token: token}, status: :ok else render json: ["Incorrect password. Please enter your #{Houdini.general.name} %> password."], status: :unprocessable_entity end diff --git a/app/controllers/widget_controller.rb b/app/controllers/widget_controller.rb index 1b90e39afc..6ed2007d4a 100644 --- a/app/controllers/widget_controller.rb +++ b/app/controllers/widget_controller.rb @@ -3,25 +3,25 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class WidgetController < ApplicationController - # we don't want anything to intefer with loading these docs - skip_forgery_protection + # we don't want anything to intefer with loading these docs + skip_forgery_protection - def v2 - expires_in 10.minutes - head :found, location: helpers.asset_pack_url('donate-button-v2.js'), content_type: 'application/javascript' - end + def v2 + expires_in 10.minutes + head :found, location: helpers.asset_pack_url("donate-button-v2.js"), content_type: "application/javascript" + end - def i18n - head :found, location: helpers.asset_pack_url('i18n.js'), content_type: 'application/javascript' - end + def i18n + head :found, location: helpers.asset_pack_url("i18n.js"), content_type: "application/javascript" + end - def v1_css - expires_in 10.minutes - head :found, location: helpers.stylesheet_url('widget/donate-button.css'), content_type: 'text/css' - end + def v1_css + expires_in 10.minutes + head :found, location: helpers.stylesheet_url("widget/donate-button.css"), content_type: "text/css" + end - def v2_css - expires_in 10.minutes - head :found, location: helpers.stylesheet_url('widget/donate-button-v2.css'), content_type: 'text/css' - end + def v2_css + expires_in 10.minutes + head :found, location: helpers.stylesheet_url("widget/donate-button-v2.css"), content_type: "text/css" + end end diff --git a/app/helpers/api/nonprofits_helper.rb b/app/helpers/api/nonprofits_helper.rb index af95f8486d..254395b588 100644 --- a/app/helpers/api/nonprofits_helper.rb +++ b/app/helpers/api/nonprofits_helper.rb @@ -3,11 +3,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Api::NonprofitsHelper - def nonprofit_slug_url(nonprofit) - nonprofit_location_url city: nonprofit.city_slug, state_code: nonprofit.state_code_slug, name: nonprofit.slug - end - - def nonprofit_slug_path(nonprofit) - nonprofit_location_path city: nonprofit.city_slug, state_code: nonprofit.state_code_slug, name: nonprofit.slug - end + def nonprofit_slug_url(nonprofit) + nonprofit_location_url city: nonprofit.city_slug, state_code: nonprofit.state_code_slug, name: nonprofit.slug + end + + def nonprofit_slug_path(nonprofit) + nonprofit_location_path city: nonprofit.city_slug, state_code: nonprofit.state_code_slug, name: nonprofit.slug + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b4f8db3564..aa5c8a365c 100755 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -15,7 +15,7 @@ def devise_mapping @devise_mapping ||= Devise.mappings[:user] end - def print_currency(cents, unit = 'EUR', sign = true, use_precision = false) + def print_currency(cents, unit = "EUR", sign = true, use_precision = false) Format::Currency.print_currency(cents, unit, sign, use_precision) end @@ -27,32 +27,32 @@ def print_percent(rate) # Format date to m/d/Y. Ex: 01/31/2022 def format_date_to_mdY(date_object, timezone = nil) - return '' if date_object.nil? + return "" if date_object.nil? date_object = date_object.in_time_zone(timezone) if timezone - date_object.strftime('%m/%d/%Y') + date_object.strftime("%m/%d/%Y") end def simple_time(time_object, timezone = nil) - return '' if time_object.nil? + return "" if time_object.nil? time_object = time_object.in_time_zone(timezone) if timezone - time_object.strftime('%l:%M%P') + time_object.strftime("%l:%M%P") end # Format date with complete month name. Ex: "January 31, 2022" def format_date_with_month_name(date_object) - date_object.strftime('%B %d, %Y') + date_object.strftime("%B %d, %Y") end # Format date to datetime with timezone. Ex: 01/31/2022 11:00PM (+03:00) def format_date_to_datetime_timezone(date_object, timezone = nil) date_object = date_object.in_time_zone(timezone) if timezone - date_object.strftime('%m/%d/%Y %I:%M%P (%Z)') + date_object.strftime("%m/%d/%Y %I:%M%P (%Z)") 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]] + [%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 @@ -61,7 +61,7 @@ def add_http(url) if url[%r{^http://}] || url[%r{^https://}] url else - 'http://' + url + "http://" + url end end end diff --git a/app/helpers/card_helper.rb b/app/helpers/card_helper.rb index 9b0d4b54e2..baed85766a 100644 --- a/app/helpers/card_helper.rb +++ b/app/helpers/card_helper.rb @@ -4,14 +4,14 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE 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' + 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 diff --git a/app/helpers/devise_helper.rb b/app/helpers/devise_helper.rb index e5b9bd55b7..a3d8661917 100644 --- a/app/helpers/devise_helper.rb +++ b/app/helpers/devise_helper.rb @@ -5,7 +5,7 @@ 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 diff --git a/app/jobs/admin_failed_gift_job.rb b/app/jobs/admin_failed_gift_job.rb index 15f3869379..d4cb402e7a 100644 --- a/app/jobs/admin_failed_gift_job.rb +++ b/app/jobs/admin_failed_gift_job.rb @@ -1,5 +1,4 @@ class AdminFailedGiftJob < EmailJob - def perform(donation, campaign_gift_option) AdminMailer.notify_failed_gift(donation, campaign_gift_option).deliver_now end diff --git a/app/jobs/bank_account_create_job.rb b/app/jobs/bank_account_create_job.rb index f30c5c2346..8f62f74e61 100644 --- a/app/jobs/bank_account_create_job.rb +++ b/app/jobs/bank_account_create_job.rb @@ -1,5 +1,4 @@ class BankAccountCreateJob < EmailJob - def perform(bank_account) NonprofitMailer.new_bank_account_notification(bank_account).deliver_now end diff --git a/app/jobs/campaign_creation_email_followup_job.rb b/app/jobs/campaign_creation_email_followup_job.rb index 2ed4589065..7ff99ca5fd 100644 --- a/app/jobs/campaign_creation_email_followup_job.rb +++ b/app/jobs/campaign_creation_email_followup_job.rb @@ -1,5 +1,4 @@ class CampaignCreationEmailFollowupJob < EmailJob - def perform(campaign) CampaignMailer.creation_followup(campaign).deliver_now end diff --git a/app/jobs/campaign_creation_federated_email_job.rb b/app/jobs/campaign_creation_federated_email_job.rb index c80d8f9004..998165d441 100644 --- a/app/jobs/campaign_creation_federated_email_job.rb +++ b/app/jobs/campaign_creation_federated_email_job.rb @@ -1,5 +1,4 @@ class CampaignCreationFederatedEmailJob < EmailJob - def perform(campaign) CampaignMailer.federated_creation_followup(campaign).deliver_now end diff --git a/app/jobs/direct_debit_create_notify_donor_job.rb b/app/jobs/direct_debit_create_notify_donor_job.rb index d720fc3227..bd4f50e85e 100644 --- a/app/jobs/direct_debit_create_notify_donor_job.rb +++ b/app/jobs/direct_debit_create_notify_donor_job.rb @@ -1,5 +1,4 @@ class DirectDebitCreateNotifyDonorJob < EmailJob - def perform(donation_id, locale) DonationMailer.donor_direct_debit_notification(donation_id, locale).deliver_now end diff --git a/app/jobs/direct_debit_create_notify_nonprofit_job.rb b/app/jobs/direct_debit_create_notify_nonprofit_job.rb index 56767564e4..724d447c2c 100644 --- a/app/jobs/direct_debit_create_notify_nonprofit_job.rb +++ b/app/jobs/direct_debit_create_notify_nonprofit_job.rb @@ -1,5 +1,4 @@ class DirectDebitCreateNotifyNonprofitJob < EmailJob - def perform(donation_id) DonationMailer.nonprofit_payment_notification(donation_id).deliver_now end diff --git a/app/jobs/email_job.rb b/app/jobs/email_job.rb index e30bd65c52..c215a1e518 100644 --- a/app/jobs/email_job.rb +++ b/app/jobs/email_job.rb @@ -1,5 +1,5 @@ class EmailJob < ApplicationJob queue_as :email_queue - retry_on Exception, wait: ->(executions) { executions **2.195 }, attempts: MAX_EMAIL_JOB_ATTEMPTS || 1 + retry_on Exception, wait: ->(executions) { executions**2.195 }, attempts: MAX_EMAIL_JOB_ATTEMPTS || 1 end diff --git a/app/jobs/event_create_creator_email_job.rb b/app/jobs/event_create_creator_email_job.rb index 391b936e4f..98de1718f0 100644 --- a/app/jobs/event_create_creator_email_job.rb +++ b/app/jobs/event_create_creator_email_job.rb @@ -1,5 +1,4 @@ class EventCreateCreatorEmailJob < EmailJob - def perform(event) EventMailer.creation_followup(event).deliver_now end diff --git a/app/jobs/export_payments_completed_job.rb b/app/jobs/export_payments_completed_job.rb index 49619415d4..64491d6f72 100644 --- a/app/jobs/export_payments_completed_job.rb +++ b/app/jobs/export_payments_completed_job.rb @@ -1,5 +1,4 @@ class ExportPaymentsCompletedJob < EmailJob - def perform(export) ExportMailer.export_payments_completed_notification(export).deliver_now end diff --git a/app/jobs/export_payments_failed_job.rb b/app/jobs/export_payments_failed_job.rb index 8acbcb2a73..be47ee346c 100644 --- a/app/jobs/export_payments_failed_job.rb +++ b/app/jobs/export_payments_failed_job.rb @@ -1,5 +1,4 @@ class ExportPaymentsFailedJob < EmailJob - def perform(export) ExportMailer.export_payments_failed_notification(export).deliver_now end diff --git a/app/jobs/export_recurring_donations_completed_job.rb b/app/jobs/export_recurring_donations_completed_job.rb index 245dfdda2e..bf24b1837d 100644 --- a/app/jobs/export_recurring_donations_completed_job.rb +++ b/app/jobs/export_recurring_donations_completed_job.rb @@ -1,5 +1,4 @@ class ExportRecurringDonationsCompletedJob < EmailJob - def perform(export) ExportMailer.export_recurring_donations_completed_notification(@export).deliver_now end diff --git a/app/jobs/export_recurring_donations_failed_job.rb b/app/jobs/export_recurring_donations_failed_job.rb index b1dd904e9d..91024b12b2 100644 --- a/app/jobs/export_recurring_donations_failed_job.rb +++ b/app/jobs/export_recurring_donations_failed_job.rb @@ -1,5 +1,4 @@ class ExportRecurringDonationsFailedJob < EmailJob - def perform(export) ExportMailer.export_recurring_donations_failed_notification(export).deliver_now end diff --git a/app/jobs/export_supporter_notes_completed_job.rb b/app/jobs/export_supporter_notes_completed_job.rb index bfcf999312..3df47cd263 100644 --- a/app/jobs/export_supporter_notes_completed_job.rb +++ b/app/jobs/export_supporter_notes_completed_job.rb @@ -1,5 +1,4 @@ class ExportSupporterNotesCompletedJob < EmailJob - def perform(export) ExportMailer.export_supporter_notes_completed_notification(export).deliver_now end diff --git a/app/jobs/export_supporter_notes_failed_job.rb b/app/jobs/export_supporter_notes_failed_job.rb index ba59a7ba3f..87ca566c26 100644 --- a/app/jobs/export_supporter_notes_failed_job.rb +++ b/app/jobs/export_supporter_notes_failed_job.rb @@ -1,5 +1,4 @@ class ExportSupporterNotesFailedJob < EmailJob - def perform(export) ExportMailer.export_supporter_notes_failed_notification(export).deliver_now end diff --git a/app/jobs/export_supporters_completed_job.rb b/app/jobs/export_supporters_completed_job.rb index 0d06045f60..96e448e5af 100644 --- a/app/jobs/export_supporters_completed_job.rb +++ b/app/jobs/export_supporters_completed_job.rb @@ -1,5 +1,4 @@ class ExportSupportersCompletedJob < EmailJob - def perform(export) ExportMailer.export_supporters_completed_notification(export).deliver_now end diff --git a/app/jobs/export_supporters_failed_job.rb b/app/jobs/export_supporters_failed_job.rb index 4da0f3752a..dcedcf1451 100644 --- a/app/jobs/export_supporters_failed_job.rb +++ b/app/jobs/export_supporters_failed_job.rb @@ -1,5 +1,4 @@ class ExportSupportersFailedJob < EmailJob - def perform(export) ExportMailer.export_supporters_failed_notification(export).deliver_now end diff --git a/app/jobs/failed_recurring_donation_payment_donor_email_job.rb b/app/jobs/failed_recurring_donation_payment_donor_email_job.rb index 90054cd405..5dbeca8a99 100644 --- a/app/jobs/failed_recurring_donation_payment_donor_email_job.rb +++ b/app/jobs/failed_recurring_donation_payment_donor_email_job.rb @@ -1,5 +1,4 @@ class FailedRecurringDonationPaymentDonorEmailJob < EmailJob - def perform(donation) DonationMailer.donor_failed_recurring_donation(donation.id).deliver_now end diff --git a/app/jobs/failed_recurring_donation_payment_nonprofit_email_job.rb b/app/jobs/failed_recurring_donation_payment_nonprofit_email_job.rb index c9ed53a754..8054d703f3 100644 --- a/app/jobs/failed_recurring_donation_payment_nonprofit_email_job.rb +++ b/app/jobs/failed_recurring_donation_payment_nonprofit_email_job.rb @@ -1,5 +1,4 @@ class FailedRecurringDonationPaymentNonprofitEmailJob < EmailJob - def perform(donation) DonationMailer.nonprofit_failed_recurring_donation(donation.id).deliver_now end diff --git a/app/jobs/import_completed_job.rb b/app/jobs/import_completed_job.rb index 82fb6336df..b6d1eff7d7 100644 --- a/app/jobs/import_completed_job.rb +++ b/app/jobs/import_completed_job.rb @@ -1,5 +1,4 @@ class ImportCompletedJob < EmailJob - def perform(import) ImportMailer.import_completed_notification(import.id).deliver_now end diff --git a/app/jobs/nonprofit_create_job.rb b/app/jobs/nonprofit_create_job.rb index 10a3c2e206..f42f94293f 100644 --- a/app/jobs/nonprofit_create_job.rb +++ b/app/jobs/nonprofit_create_job.rb @@ -1,5 +1,4 @@ class NonprofitCreateJob < EmailJob - def perform(nonprofit) NonprofitMailer.welcome(nonprofit.id).deliver_now end diff --git a/app/jobs/payment_notification_email_donor_job.rb b/app/jobs/payment_notification_email_donor_job.rb index 5c49b97bd1..5206f51877 100644 --- a/app/jobs/payment_notification_email_donor_job.rb +++ b/app/jobs/payment_notification_email_donor_job.rb @@ -1,5 +1,4 @@ class PaymentNotificationEmailDonorJob < EmailJob - def perform(donation, locale) DonationMailer.donor_payment_notification(donation.id, locale).deliver_now end diff --git a/app/jobs/payment_notification_email_nonprofit_job.rb b/app/jobs/payment_notification_email_nonprofit_job.rb index 0b246b0294..f9e5ded384 100644 --- a/app/jobs/payment_notification_email_nonprofit_job.rb +++ b/app/jobs/payment_notification_email_nonprofit_job.rb @@ -1,6 +1,5 @@ class PaymentNotificationEmailNonprofitJob < EmailJob - - def perform(donation, user=nil) + def perform(donation, user = nil) DonationMailer.nonprofit_payment_notification(donation.id, user&.id).deliver_now end end diff --git a/app/jobs/payout_pending_job.rb b/app/jobs/payout_pending_job.rb index 240cfe7d53..cd5870e0ac 100644 --- a/app/jobs/payout_pending_job.rb +++ b/app/jobs/payout_pending_job.rb @@ -1,5 +1,4 @@ class PayoutPendingJob < EmailJob - def perform(payout) NonprofitMailer.pending_payout_notification(payout.id).deliver_now end diff --git a/app/jobs/recurring_donation_cancelled_job.rb b/app/jobs/recurring_donation_cancelled_job.rb index e23699c2af..344012a847 100644 --- a/app/jobs/recurring_donation_cancelled_job.rb +++ b/app/jobs/recurring_donation_cancelled_job.rb @@ -1,5 +1,4 @@ class RecurringDonationCancelledJob < EmailJob - def perform(donation) DonationMailer.nonprofit_recurring_donation_cancellation(donation.id).deliver_now end diff --git a/app/jobs/recurring_donation_change_amount_donor_email_job.rb b/app/jobs/recurring_donation_change_amount_donor_email_job.rb index 24aada633c..d3ffc8f8b0 100644 --- a/app/jobs/recurring_donation_change_amount_donor_email_job.rb +++ b/app/jobs/recurring_donation_change_amount_donor_email_job.rb @@ -1,5 +1,4 @@ class RecurringDonationChangeAmountDonorEmailJob < EmailJob - def perform(recurring_donation, previous_amount) DonationMailer.donor_recurring_donation_change_amount(recurring_donation.id, previous_amount).deliver_now end diff --git a/app/jobs/recurring_donation_change_amount_nonprofit_email_job.rb b/app/jobs/recurring_donation_change_amount_nonprofit_email_job.rb index 9039cb9d0e..a9a2e6a8b5 100644 --- a/app/jobs/recurring_donation_change_amount_nonprofit_email_job.rb +++ b/app/jobs/recurring_donation_change_amount_nonprofit_email_job.rb @@ -1,5 +1,4 @@ class RecurringDonationChangeAmountNonprofitEmailJob < EmailJob - def perform(recurring_donation, previous_amount) DonationMailer.nonprofit_recurring_donation_change_amount(recurring_donation.id, previous_amount).deliver_now end diff --git a/app/jobs/refund_notification_donor_email_job.rb b/app/jobs/refund_notification_donor_email_job.rb index 946eb46254..e38f19007b 100644 --- a/app/jobs/refund_notification_donor_email_job.rb +++ b/app/jobs/refund_notification_donor_email_job.rb @@ -1,5 +1,4 @@ class RefundNotificationDonorEmailJob < EmailJob - def perform(refund) UserMailer.refund_receipt(refund).deliver_now end diff --git a/app/jobs/refund_notification_job.rb b/app/jobs/refund_notification_job.rb index 0c7632d06a..e67e398183 100644 --- a/app/jobs/refund_notification_job.rb +++ b/app/jobs/refund_notification_job.rb @@ -1,5 +1,4 @@ class RefundNotificationJob < EmailJob - def perform(refund) RefundNotificationDonorEmailJob.perform_later(refund) RefundNotificationNonprofitEmailJob.perform_later(refund) diff --git a/app/jobs/refund_notification_nonprofit_email_job.rb b/app/jobs/refund_notification_nonprofit_email_job.rb index bef576f184..657c5303d7 100644 --- a/app/jobs/refund_notification_nonprofit_email_job.rb +++ b/app/jobs/refund_notification_nonprofit_email_job.rb @@ -1,5 +1,4 @@ class RefundNotificationNonprofitEmailJob < EmailJob - def perform(refund) NonprofitMailer.refund_notification(refund.id).deliver_now end diff --git a/app/jobs/role_added_job.rb b/app/jobs/role_added_job.rb index 1706e35adf..db655cfa42 100644 --- a/app/jobs/role_added_job.rb +++ b/app/jobs/role_added_job.rb @@ -1,5 +1,4 @@ class RoleAddedJob < EmailJob - def perform(role) NonprofitAdminMailer.existing_invite(role).deliver_now end diff --git a/app/jobs/stripe_account_create_job.rb b/app/jobs/stripe_account_create_job.rb index a1e82be8ad..513a88ac1c 100644 --- a/app/jobs/stripe_account_create_job.rb +++ b/app/jobs/stripe_account_create_job.rb @@ -1,5 +1,4 @@ class StripeAccountCreateJob < EmailJob - def perform(nonprofit) NonprofitMailer.setup_verification(nonprofit.id).deliver_now end diff --git a/app/jobs/supporters_export_create_job.rb b/app/jobs/supporters_export_create_job.rb index 8ad1f1d505..13be45a70d 100644 --- a/app/jobs/supporters_export_create_job.rb +++ b/app/jobs/supporters_export_create_job.rb @@ -1,5 +1,4 @@ class SupportersExportCreateJob < EmailJob - def perform(*args) ExportSupporters.run_export(*args) end diff --git a/app/jobs/user_invite_create_job.rb b/app/jobs/user_invite_create_job.rb index 243c4e62d0..1898d490c3 100644 --- a/app/jobs/user_invite_create_job.rb +++ b/app/jobs/user_invite_create_job.rb @@ -1,5 +1,4 @@ class UserInviteCreateJob < EmailJob - def perform(role, raw_token) NonprofitAdminMailer.new_invite(role, raw_token).deliver_now end diff --git a/app/jobs/verification_completed_job.rb b/app/jobs/verification_completed_job.rb index 7e939161f2..091df90357 100644 --- a/app/jobs/verification_completed_job.rb +++ b/app/jobs/verification_completed_job.rb @@ -1,5 +1,4 @@ class VerificationCompletedJob < EmailJob - def perform(nonprofit) NonprofitMailer.successful_verification_notice(nonprofit).deliver_now end diff --git a/app/jobs/verification_failed_job.rb b/app/jobs/verification_failed_job.rb index 708af2044e..524cad1f3c 100644 --- a/app/jobs/verification_failed_job.rb +++ b/app/jobs/verification_failed_job.rb @@ -1,5 +1,4 @@ class VerificationFailedJob < EmailJob - def perform(nonprofit) NonprofitMailer.failed_verification_notice(onprofit).deliver_now end diff --git a/app/legacy_lib/billing_plans.rb b/app/legacy_lib/billing_plans.rb index b4f928d85e..da3c8f85e2 100644 --- a/app/legacy_lib/billing_plans.rb +++ b/app/legacy_lib/billing_plans.rb @@ -2,21 +2,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'qx' +require "qx" module BillingPlans def self.get_percentage_fee(nonprofit_id) - ParamValidation.new({ nonprofit_id: nonprofit_id }, nonprofit_id: { required: true, is_integer: true }) + ParamValidation.new({nonprofit_id: nonprofit_id}, nonprofit_id: {required: true, is_integer: true}) unless Nonprofit.exists?(nonprofit_id) raise ParamValidation::ValidationError.new("#{nonprofit_id} does not exist", key: :nonprofit_id) end - result = Qx.select('billing_plans.percentage_fee') - .from('billing_plans') - .join('billing_subscriptions bs', 'bs.billing_plan_id = billing_plans.id') - .where('bs.nonprofit_id=$id', id: nonprofit_id) - .execute - result.empty? ? 0 : result.last['percentage_fee'] + result = Qx.select("billing_plans.percentage_fee") + .from("billing_plans") + .join("billing_subscriptions bs", "bs.billing_plan_id = billing_plans.id") + .where("bs.nonprofit_id=$id", id: nonprofit_id) + .execute + result.empty? ? 0 : result.last["percentage_fee"] end end diff --git a/app/legacy_lib/calculate_fees.rb b/app/legacy_lib/calculate_fees.rb index da1ef85879..c6b1d1d4f1 100644 --- a/app/legacy_lib/calculate_fees.rb +++ b/app/legacy_lib/calculate_fees.rb @@ -2,15 +2,15 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'param_validation' +require "param_validation" module CalculateFees BaseFeeRate = 0.022 # 2.2% PerTransaction = 30 # 30 cents def self.for_single_amount(amount, platform_fee = 0.0) - ParamValidation.new({ fee: platform_fee, amount: amount }, - amount: { min: 0, is_integer: true }, - fee: { min: 0.0, is_float: true }) + ParamValidation.new({fee: platform_fee, amount: amount}, + amount: {min: 0, is_integer: true}, + fee: {min: 0.0, is_float: true}) fee = BaseFeeRate + platform_fee (amount * fee).ceil.to_i + PerTransaction end diff --git a/app/legacy_lib/calculate_suggested_amounts.rb b/app/legacy_lib/calculate_suggested_amounts.rb index d3e524af9e..6493eb2caf 100644 --- a/app/legacy_lib/calculate_suggested_amounts.rb +++ b/app/legacy_lib/calculate_suggested_amounts.rb @@ -2,22 +2,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative './numeric' -require 'param_validation' +require_relative "numeric" +require "param_validation" module CalculateSuggestedAmounts MIN = 25 MAX = 100_000_000 - BRACKETS = [{ range: MIN...1000, delta: 100 }, - { range: 1000...5000, delta: 500 }, - { range: 5000...MAX, delta: 2500 }].freeze + BRACKETS = [{range: MIN...1000, delta: 100}, + {range: 1000...5000, delta: 500}, + {range: 5000...MAX, delta: 2500}].freeze # Calculates a set of suggested donation amounts based upon our internal special algorithm # This is most useful for suggesting amounts a recurring donor could change to # @return [Array] suggested amounts for your donation # @param [Number] amount the amount in cents to start from def self.calculate(amount) - ParamValidation.new({ amount: amount }, amount: { required: true, is_a: Numeric, min: MIN, max: MAX }) + ParamValidation.new({amount: amount}, amount: {required: true, is_a: Numeric, min: MIN, max: MAX}) result = [] step_down_val = step_down_value(amount) @@ -42,7 +42,7 @@ def self.step_down_value(amount) # not on a delta, just send a floor if delta_floor != amount - return delta_floor < MIN ? nil : delta_floor + return (delta_floor < MIN) ? nil : delta_floor end potential_lower_amount = amount - initial_bracket[:delta] @@ -68,7 +68,7 @@ def self.step_up_value(amount) # not on a delta, just send a ceil if delta_ceil != amount - return delta_ceil >= MAX ? nil : delta_ceil + return (delta_ceil >= MAX) ? nil : delta_ceil end potential_higher_amount = amount + bracket[:delta] diff --git a/app/legacy_lib/chunked_uploader.rb b/app/legacy_lib/chunked_uploader.rb index 145fb1a63d..1853c28ae6 100644 --- a/app/legacy_lib/chunked_uploader.rb +++ b/app/legacy_lib/chunked_uploader.rb @@ -3,22 +3,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module ChunkedUploader - # Copy a string using chunks instead of all as one string. This is useful reducing memory usage when you want to do a huge export - # + # # This code copies each chunk to a tempfile and then opens the tempfile and passes the IO object to the block # @param [Enumerable] chunk_enum an enumerable of strings. # @block accepts an IO for passing to upload def self.upload(chunk_enum, &block) file_name = File.join(Dir.tmpdir, SecureRandom.uuid) - File.open(file_name, 'w') do |file| + File.open(file_name, "w") do |file| chunk_enum.each do |chunk| file.write(chunk) end end - File.open(file_name, 'r') do |file| + File.open(file_name, "r") do |file| yield(file) end diff --git a/app/legacy_lib/construct_nonprofit.rb b/app/legacy_lib/construct_nonprofit.rb index de5810ac9f..e7c86a7118 100644 --- a/app/legacy_lib/construct_nonprofit.rb +++ b/app/legacy_lib/construct_nonprofit.rb @@ -5,7 +5,7 @@ module ConstructNonprofit def self.construct(user, h) - h[:verification_status] = 'unverified' + h[:verification_status] = "unverified" h[:published] = true h[:statement] = h[:name][0..16] h.except!(:website) if h[:website].blank? diff --git a/app/legacy_lib/copy_naming_algorithm.rb b/app/legacy_lib/copy_naming_algorithm.rb index 5d00300796..e45f537b3c 100644 --- a/app/legacy_lib/copy_naming_algorithm.rb +++ b/app/legacy_lib/copy_naming_algorithm.rb @@ -5,7 +5,7 @@ class CopyNamingAlgorithm DEFAULT_MAX_LENGTH = 255 DEFAULT_MAX_COPIES = 255 - DEFAULT_SEPARATOR_BEFORE_COPY_NUMBER = '_' + DEFAULT_SEPARATOR_BEFORE_COPY_NUMBER = "_" def copy_addition raise NotImplementedError @@ -33,7 +33,7 @@ def get_name_for_entity(name_entity) def create_copy_name(name_to_copy) # remove copy addition and number - base_name = name_to_copy.gsub(/#{Regexp.quote(copy_addition)}(#{Regexp.quote(separator_before_copy_number)}\d+)?\z/, '') + base_name = name_to_copy.gsub(/#{Regexp.quote(copy_addition)}(#{Regexp.quote(separator_before_copy_number)}\d+)?\z/, "") name_entities_to_check_against = get_already_used_name_entities(base_name).collect { |entity| get_name_for_entity(entity) }.to_a (0..max_copies - 1).each do |copy_num| name_to_test = generate_name(base_name, copy_num) diff --git a/app/legacy_lib/create_campaign.rb b/app/legacy_lib/create_campaign.rb index d5073fe0e0..0b2392ed32 100644 --- a/app/legacy_lib/create_campaign.rb +++ b/app/legacy_lib/create_campaign.rb @@ -3,21 +3,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module CreateCampaign - CAMPAIGN_NAME_LENGTH_LIMIT = 60 + CAMPAIGN_NAME_LENGTH_LIMIT = 60 - # @return [Object] a json object for historical purposes - def self.create(params, nonprofit) # rubocop:disable Metrics/AbcSize - Time.use_zone(nonprofit.timezone || 'UTC') do - params[:campaign][:end_datetime] = Chronic.parse(params[:end_datetime]) if params[:end_datetime].present? - end + # @return [Object] a json object for historical purposes + def self.create(params, nonprofit) # rubocop:disable Metrics/AbcSize + Time.use_zone(nonprofit.timezone || "UTC") do + params[:campaign][:end_datetime] = Chronic.parse(params[:end_datetime]) if params[:end_datetime].present? + end - if params[:campaign][:parent_campaign_id] - profile_id = params[:campaign][:profile_id] - Profile.find(profile_id).update params[:profile] - CreatePeerToPeerCampaign.create(params[:campaign], profile_id) - else - nonprofit.campaigns.create! params[:campaign] + if params[:campaign][:parent_campaign_id] + profile_id = params[:campaign][:profile_id] + Profile.find(profile_id).update params[:profile] + CreatePeerToPeerCampaign.create(params[:campaign], profile_id) + else + nonprofit.campaigns.create! params[:campaign] - end - end + end + end end diff --git a/app/legacy_lib/create_campaign_gift.rb b/app/legacy_lib/create_campaign_gift.rb index 31e4b5f68f..19877fd322 100644 --- a/app/legacy_lib/create_campaign_gift.rb +++ b/app/legacy_lib/create_campaign_gift.rb @@ -8,21 +8,21 @@ module CreateCampaignGift # * donation_id def self.create(params) ParamValidation.new(params, - campaign_gift_option_id: { - required: true, - is_integer: true - }, - donation_id: { - required: true, - is_integer: true - }) + campaign_gift_option_id: { + required: true, + is_integer: true + }, + donation_id: { + required: true, + is_integer: true + }) - donation = Donation.includes(:nonprofit).includes(:supporter).includes(:recurring_donation).includes(:campaign_gifts).where('id = ?', params[:donation_id]).first + donation = Donation.includes(:nonprofit).includes(:supporter).includes(:recurring_donation).includes(:campaign_gifts).where("id = ?", params[:donation_id]).first unless donation raise ParamValidation::ValidationError.new("#{params[:donation_id]} is not a valid donation id.", key: :donation_id) end - campaign_gift_option = CampaignGiftOption.includes(:campaign).where('id = ?', params[:campaign_gift_option_id]).first + campaign_gift_option = CampaignGiftOption.includes(:campaign).where("id = ?", params[:campaign_gift_option_id]).first unless campaign_gift_option raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} is not a valid campaign gift option", key: :campaign_gift_option_id) end @@ -36,7 +36,7 @@ def self.create(params) raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} is not for the same campaign as donation #{params[:donation_id]}", key: :campaign_gift_option_id) end - if !donation.recurring_donation.nil? && (!campaign_gift_option.amount_recurring.nil? && campaign_gift_option.amount_recurring > 0) + if !donation.recurring_donation.nil? && !campaign_gift_option.amount_recurring.nil? && campaign_gift_option.amount_recurring > 0 # it's a recurring_donation. Is it enough? for the gift level? unless donation.recurring_donation.amount == campaign_gift_option.amount_recurring AdminFailedGiftJob.perform_later(donation, campaign_gift_option) @@ -64,7 +64,7 @@ def self.create(params) def self.validate_campaign_gift(cg) donation = cg.donation campaign_gift_option = cg.campaign_gift_option - if !donation.recurring_donation.nil? && (!campaign_gift_option.amount_recurring.nil? && campaign_gift_option.amount_recurring > 0) + if !donation.recurring_donation.nil? && !campaign_gift_option.amount_recurring.nil? && campaign_gift_option.amount_recurring > 0 # it's a recurring_donation. Is it enough? for the gift level? unless donation.recurring_donation.amount == campaign_gift_option.amount_recurring raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a recurring donation of at least #{campaign_gift_option.amount_recurring}", key: :campaign_gift_option_id) diff --git a/app/legacy_lib/create_custom_field_definition.rb b/app/legacy_lib/create_custom_field_definition.rb index 8e0cef4c84..6188c68e3a 100644 --- a/app/legacy_lib/create_custom_field_definition.rb +++ b/app/legacy_lib/create_custom_field_definition.rb @@ -4,7 +4,6 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module CreateCustomFieldDefinition def self.create(nonprofit, params) - custom_field_definition = nonprofit.custom_field_definitions.create(params) - custom_field_definition + nonprofit.custom_field_definitions.create(params) end end diff --git a/app/legacy_lib/create_custom_field_join.rb b/app/legacy_lib/create_custom_field_join.rb index a4598c3d8e..47f05699f9 100644 --- a/app/legacy_lib/create_custom_field_join.rb +++ b/app/legacy_lib/create_custom_field_join.rb @@ -4,8 +4,7 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module CreateCustomFieldJoin def self.create(supporter, _profile_id, params) - custom_field = supporter.custom_field_joins.create(params) - custom_field + supporter.custom_field_joins.create(params) end # In the future, this should create an activity feed entry @@ -29,8 +28,8 @@ def self.modify(np, user, supporter_ids, custom_fields) ) else create(supporter, user.profile.id, - custom_field_definition_id: custom_field[:custom_field_definition_id], - value: custom_field[:value]) + custom_field_definition_id: custom_field[:custom_field_definition_id], + value: custom_field[:value]) end end end diff --git a/app/legacy_lib/create_peer_to_peer_campaign.rb b/app/legacy_lib/create_peer_to_peer_campaign.rb index 4b7e0a8da6..7738011eae 100644 --- a/app/legacy_lib/create_peer_to_peer_campaign.rb +++ b/app/legacy_lib/create_peer_to_peer_campaign.rb @@ -3,28 +3,28 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module CreatePeerToPeerCampaign - def self.create(campaign_params, profile_id) # rubocop:disable Metrics/AbcSize - parent_campaign = Campaign.find(campaign_params[:parent_campaign_id]) + def self.create(campaign_params, profile_id) # rubocop:disable Metrics/AbcSize + parent_campaign = Campaign.find(campaign_params[:parent_campaign_id]) - p2p_params = campaign_params.except(:nonprofit_id, :summary, :goal_amount) - p2p_params.merge!(parent_campaign.child_params) + p2p_params = campaign_params.except(:nonprofit_id, :summary, :goal_amount) + p2p_params.merge!(parent_campaign.child_params) - profile = Profile.find(profile_id) - base_slug = Format::Url.convert_to_slug "#{p2p_params[:name]}-#{profile.name}" - algo = SlugP2pCampaignNamingAlgorithm.new(p2p_params[:nonprofit_id]) - p2p_params[:slug] = algo.create_copy_name(base_slug) + profile = Profile.find(profile_id) + base_slug = Format::Url.convert_to_slug "#{p2p_params[:name]}-#{profile.name}" + algo = SlugP2pCampaignNamingAlgorithm.new(p2p_params[:nonprofit_id]) + p2p_params[:slug] = algo.create_copy_name(base_slug) - campaign = Campaign.create!(**p2p_params, profile: profile) + campaign = Campaign.create!(**p2p_params, profile: profile) - campaign.published = true - campaign.profile = profile - campaign.save - campaign.main_image.attach(parent_campaign.main_image.blob) if parent_campaign.main_image.attached? + campaign.published = true + campaign.profile = profile + campaign.save + campaign.main_image.attach(parent_campaign.main_image.blob) if parent_campaign.main_image.attached? - campaign.background_image.attach(parent_campaign.background_image.blob) if parent_campaign.background_image.attached? + campaign.background_image.attach(parent_campaign.background_image.blob) if parent_campaign.background_image.attached? - campaign.banner_image.attach(parent_campaign.banner_image.blob) if parent_campaign.banner_image.attached? + campaign.banner_image.attach(parent_campaign.banner_image.blob) if parent_campaign.banner_image.attached? - campaign - end + campaign + end end diff --git a/app/legacy_lib/create_stripe_account.rb b/app/legacy_lib/create_stripe_account.rb index 645b88eea8..00fb129677 100644 --- a/app/legacy_lib/create_stripe_account.rb +++ b/app/legacy_lib/create_stripe_account.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'stripe' +require "stripe" module CreateStripeAccount def self.for_nonprofit(user, params) @@ -13,25 +13,25 @@ def self.for_nonprofit(user, params) business_name: params[:name], business_url: params[:website], legal_entity: { - type: 'company', + type: "company", address: { line1: params[:address], city: params[:city], state: params[:state_code], postal_code: params[:zip_code], - country: 'US' + country: "US" }, business_name: params[:name], business_tax_id: params[:ein], first_name: fst_name, last_name: lst_name }, - product_description: 'Nonprofit donations', + product_description: "Nonprofit donations", tos_acceptance: { date: Time.current.to_i, ip: user.current_sign_in_ip }, - transfer_schedule: { interval: 'manual' } + transfer_schedule: {interval: "manual"} ) end end diff --git a/app/legacy_lib/cypher.rb b/app/legacy_lib/cypher.rb index e6d9294e7d..45afed731b 100644 --- a/app/legacy_lib/cypher.rb +++ b/app/legacy_lib/cypher.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'openssl' +require "openssl" # This module is useful for encrypting columns into the database # For the encrypted column, store it as "text" types @@ -14,19 +14,19 @@ module Cypher def self.encrypt(data) cipher = create_cipher cipher.encrypt - cipher.key = Base64.decode64(ENV['CYPHER_KEY']) + cipher.key = Base64.decode64(ENV["CYPHER_KEY"]) iv = cipher.random_iv encrypted = cipher.update(data) + cipher.final - { iv: Base64.encode64(iv), key: Base64.encode64(encrypted) } + {iv: Base64.encode64(iv), key: Base64.encode64(encrypted)} end # hash must have properties for :iv and :key def self.decrypt(hash) - iv = Base64.decode64(hash['iv']) - encrypted = Base64.decode64(hash['key']) + iv = Base64.decode64(hash["iv"]) + encrypted = Base64.decode64(hash["key"]) decipher = create_cipher decipher.decrypt - decipher.key = Base64.decode64(ENV['CYPHER_KEY']) + decipher.key = Base64.decode64(ENV["CYPHER_KEY"]) decipher.iv = iv decipher.update(encrypted) + decipher.final @@ -35,6 +35,6 @@ def self.decrypt(hash) private def self.create_cipher - OpenSSL::Cipher::AES256.new(:CBC) + OpenSSL::Cipher.new("aes-256-cbc") end end diff --git a/app/legacy_lib/delete_custom_field_joins.rb b/app/legacy_lib/delete_custom_field_joins.rb index f332381ee8..507b9cbfb1 100644 --- a/app/legacy_lib/delete_custom_field_joins.rb +++ b/app/legacy_lib/delete_custom_field_joins.rb @@ -6,13 +6,13 @@ module DeleteCustomFieldJoins @columns = %w[id custom_field_definition_id supporter_id value created_at updated_at metadata] def self.find_multiple_custom_field_joins bad_results = Qx.select("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_definition_id) AS our_concat, COUNT(id) AS our_count") - .from(:custom_field_joins) - .group_by('our_concat') - .having('COUNT(id) > 1').parse + .from(:custom_field_joins) + .group_by("our_concat") + .having("COUNT(id) > 1").parse custom_field_joins_from_qx = CustomFieldJoin - .where("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_definition_id) IN (SELECT our_concat FROM (#{bad_results}) AS ignore)") - .select('id, custom_field_definition_id, supporter_id, created_at, updated_at') + .where("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_definition_id) IN (SELECT our_concat FROM (#{bad_results}) AS ignore)") + .select("id, custom_field_definition_id, supporter_id, created_at, updated_at") grouped_custom_field_joins = custom_field_joins_from_qx.group_by { |tj| "#{tj.supporter_id}_#{tj.custom_field_definition_id}" } ids_to_delete = [] @@ -26,13 +26,13 @@ def self.find_multiple_custom_field_joins def self.copy_and_delete(ids_to_delete) if ids_to_delete.any? - Qx.insert_into(:custom_field_joins_backup, @columns).select(@columns).from(:custom_field_joins).where('id IN ($ids)', ids: ids_to_delete).execute - CustomFieldJoin.where('id IN (?)', ids_to_delete).delete_all + Qx.insert_into(:custom_field_joins_backup, @columns).select(@columns).from(:custom_field_joins).where("id IN ($ids)", ids: ids_to_delete).execute + CustomFieldJoin.where("id IN (?)", ids_to_delete).delete_all end end def self.revert Qx.insert_into(:custom_field_joins, @columns).select(@columns).from(:custom_field_joins_backup).execute - Qx.execute_raw('DELETE FROM custom_field_joins_backup') + Qx.execute_raw("DELETE FROM custom_field_joins_backup") end end diff --git a/app/legacy_lib/email.rb b/app/legacy_lib/email.rb index 2bee787e25..3100bc225a 100644 --- a/app/legacy_lib/email.rb +++ b/app/legacy_lib/email.rb @@ -3,6 +3,6 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Email - Regex ||= /\A[^ ]+@[^ ]+\.[^ ]+/i.freeze + Regex ||= /\A[^ ]+@[^ ]+\.[^ ]+/i # PsqlRegex ||= '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+[.][A-Za-z]+$' end diff --git a/app/legacy_lib/export_payments.rb b/app/legacy_lib/export_payments.rb index 0a728fca7e..de15d18c3e 100644 --- a/app/legacy_lib/export_payments.rb +++ b/app/legacy_lib/export_payments.rb @@ -5,37 +5,37 @@ module ExportPayments def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_hash: true }, - user_id: { required: true, is_integer: true }) - npo = Nonprofit.where('id = ?', npo_id).first + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_hash: true}, + user_id: {required: true, is_integer: true}) + npo = Nonprofit.where("id = ?", npo_id).first unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: 'ExportPayments', parameters: params.to_json) + e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: "ExportPayments", parameters: params.to_json) PaymentExportCreateJob.perform_later(npo_id, params.to_json, user_id, e.id) end def self.run_export(npo_id, params, user_id, export_id) # need to check that - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id, export_id: export_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_json: true }, - user_id: { required: true, is_integer: true }, - export_id: { required: true, is_integer: true }) + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id, export_id: export_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_json: true}, + user_id: {required: true, is_integer: true}, + export_id: {required: true, is_integer: true}) - params = JSON.parse(params, object_class: HashWithIndifferentAccess) + params = JSON.parse(params, object_class: ActiveSupport::HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once - ParamValidation.new({ params: params }, - params: { is_hash: true }) + ParamValidation.new({params: params}, + params: {is_hash: true}) begin export = Export.find(export_id) rescue ActiveRecord::RecordNotFound @@ -48,16 +48,16 @@ def self.run_export(npo_id, params, user_id, export_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime("%m-%d-%Y--%H-%M-%S") filename = "tmp/csv-exports/payments-#{file_date}-#{SecureRandom.uuid}.csv" ChunkedUploader.upload(QueryPayments.for_export_enumerable(npo_id, params, 30_000).map(&:to_csv)) do |io| - CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: 'text/csv', content_disposition: 'attachment') + CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: "text/csv", content_disposition: "attachment") end url = CHUNKED_UPLOAD_SERVICE.url(filename) export.url = url @@ -66,7 +66,7 @@ def self.run_export(npo_id, params, user_id, export_id) export.save! ExportPaymentsCompletedJob.perform_later(export) - rescue StandardError => e + rescue => e if export export.status = :failed export.exception = e.to_s diff --git a/app/legacy_lib/export_recurring_donations.rb b/app/legacy_lib/export_recurring_donations.rb index 87403863f4..f233ac8d01 100644 --- a/app/legacy_lib/export_recurring_donations.rb +++ b/app/legacy_lib/export_recurring_donations.rb @@ -5,37 +5,37 @@ module ExportRecurringDonations def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_hash: true }, - user_id: { required: true, is_integer: true }) - npo = Nonprofit.where('id = ?', npo_id).first + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_hash: true}, + user_id: {required: true, is_integer: true}) + npo = Nonprofit.where("id = ?", npo_id).first unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: 'ExportRecurringDonations', parameters: params.to_json) + e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: "ExportRecurringDonations", parameters: params.to_json) RecurringDonationsExportCreateJob.perform_later(npo_id, params.to_json, user_id, e.id) end def self.run_export(npo_id, params, user_id, export_id) # need to check that - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id, export_id: export_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_json: true }, - user_id: { required: true, is_integer: true }, - export_id: { required: true, is_integer: true }) + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id, export_id: export_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_json: true}, + user_id: {required: true, is_integer: true}, + export_id: {required: true, is_integer: true}) - params = JSON.parse(params, object_class: HashWithIndifferentAccess) + params = JSON.parse(params, object_class: ActiveSupport::HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once - ParamValidation.new({ params: params }, - params: { is_hash: true }) + ParamValidation.new({params: params}, + params: {is_hash: true}) begin export = Export.find(export_id) rescue ActiveRecord::RecordNotFound @@ -48,16 +48,16 @@ def self.run_export(npo_id, params, user_id, export_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime("%m-%d-%Y--%H-%M-%S") filename = "tmp/csv-exports/recurring_donations-#{file_date}-#{SecureRandom.uuid}.csv" ChunkedUploader.upload(QueryRecurringDonations.for_export_enumerable(npo_id, params, 30_000).map(&:to_csv)) do |io| - CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: 'text/csv', content_disposition: 'attachment') + CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: "text/csv", content_disposition: "attachment") end url = CHUNKED_UPLOAD_SERVICE.url(filename) export.url = url @@ -66,7 +66,7 @@ def self.run_export(npo_id, params, user_id, export_id) export.save! ExportRecurringDonationsCompletedJob.perform_later(export) - rescue StandardError => e + rescue => e if export export.status = :failed export.exception = e.to_s diff --git a/app/legacy_lib/export_supporter_notes.rb b/app/legacy_lib/export_supporter_notes.rb index 5b1e2292e9..a95af0e434 100644 --- a/app/legacy_lib/export_supporter_notes.rb +++ b/app/legacy_lib/export_supporter_notes.rb @@ -4,37 +4,37 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module ExportSupporterNotes def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_hash: true }, - user_id: { required: true, is_integer: true }) - npo = Nonprofit.where('id = ?', npo_id).first + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_hash: true}, + user_id: {required: true, is_integer: true}) + npo = Nonprofit.where("id = ?", npo_id).first unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: 'ExportSupporterNotes', parameters: params.to_json) + e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: "ExportSupporterNotes", parameters: params.to_json) SupporterNotesExportCreateJob.perform_later(npo_id, params.to_json, user_id, e.id) - end + end def self.run_export(npo_id, params, user_id, export_id) # need to check that - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id, export_id: export_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_json: true }, - user_id: { required: true, is_integer: true }, - export_id: { required: true, is_integer: true }) + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id, export_id: export_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_json: true}, + user_id: {required: true, is_integer: true}, + export_id: {required: true, is_integer: true}) - params = JSON.parse(params, object_class: HashWithIndifferentAccess) + params = JSON.parse(params, object_class: ActiveSupport::HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once - ParamValidation.new({ params: params }, - params: { is_hash: true }) + ParamValidation.new({params: params}, + params: {is_hash: true}) begin export = Export.find(export_id) rescue ActiveRecord::RecordNotFound @@ -47,16 +47,16 @@ def self.run_export(npo_id, params, user_id, export_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime("%m-%d-%Y--%H-%M-%S") filename = "tmp/csv-exports/supporters-notes-#{file_date}-#{SecureRandom.uuid}.csv" ChunkedUploader.upload(QuerySupporters.supporter_note_export_enumerable(npo_id, params, 30_000).map(&:to_csv)) do |io| - CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: 'text/csv', content_disposition: 'attachment') + CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: "text/csv", content_disposition: "attachment") end url = CHUNKED_UPLOAD_SERVICE.url(filename) export.url = url @@ -64,7 +64,7 @@ def self.run_export(npo_id, params, user_id, export_id) export.ended = Time.now export.save! ExportSupporterNotesCompletedJob.perform_later(export) - rescue StandardError => e + rescue => e if export export.status = :failed export.exception = e.to_s diff --git a/app/legacy_lib/export_supporters.rb b/app/legacy_lib/export_supporters.rb index 866093bccd..605c9a2700 100644 --- a/app/legacy_lib/export_supporters.rb +++ b/app/legacy_lib/export_supporters.rb @@ -2,36 +2,36 @@ module ExportSupporters def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_hash: true }, - user_id: { required: true, is_integer: true }) - npo = Nonprofit.where('id = ?', npo_id).first + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_hash: true}, + user_id: {required: true, is_integer: true}) + npo = Nonprofit.where("id = ?", npo_id).first unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: 'ExportSupporters', parameters: params.to_json) + e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: "ExportSupporters", parameters: params.to_json) SupportersExportCreateJob.perform_later(npo_id, params.to_json, user_id, e.id) end def self.run_export(npo_id, params, user_id, export_id) # need to check that - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id, export_id: export_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_json: true }, - user_id: { required: true, is_integer: true }, - export_id: { required: true, is_integer: true }) + ParamValidation.new({npo_id: npo_id, params: params, user_id: user_id, export_id: export_id}, + npo_id: {required: true, is_integer: true}, + params: {required: true, is_json: true}, + user_id: {required: true, is_integer: true}, + export_id: {required: true, is_integer: true}) - params = JSON.parse(params, object_class: HashWithIndifferentAccess) + params = JSON.parse(params, object_class: ActiveSupport::HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once - ParamValidation.new({ params: params }, params: { is_hash: true }) + ParamValidation.new({params: params}, params: {is_hash: true}) begin export = Export.find(export_id) rescue ActiveRecord::RecordNotFound @@ -44,16 +44,16 @@ def self.run_export(npo_id, params, user_id, export_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end - user = User.where('id = ?', user_id).first + user = User.where("id = ?", user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime("%m-%d-%Y--%H-%M-%S") filename = "tmp/csv-exports/supporters-#{file_date}-#{SecureRandom.uuid}.csv" ChunkedUploader.upload(QuerySupporters.for_export_enumerable(npo_id, params, 30_000).map(&:to_csv)) do |io| - CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: 'text/csv', content_disposition: 'attachment') + CHUNKED_UPLOAD_SERVICE.upload(filename, io, content_type: "text/csv", content_disposition: "attachment") end url = CHUNKED_UPLOAD_SERVICE.url(filename) export.url = url @@ -62,7 +62,7 @@ def self.run_export(npo_id, params, user_id, export_id) export.save! ExportSupportersCompletedJob.perform_later export - rescue StandardError => e + rescue => e if export export.status = :failed export.exception = e.to_s diff --git a/app/legacy_lib/fetch_campaign.rb b/app/legacy_lib/fetch_campaign.rb index aab584c96e..faaa0a0048 100644 --- a/app/legacy_lib/fetch_campaign.rb +++ b/app/legacy_lib/fetch_campaign.rb @@ -6,9 +6,9 @@ module FetchCampaign def self.with_params(params, nonprofit = nil) nonprofit ||= FetchNonprofit.with_params(params) if params[:campaign_slug] - return nonprofit.campaigns.where(slug: params[:campaign_slug]).last + nonprofit.campaigns.where(slug: params[:campaign_slug]).last elsif params[:campaign_id] || params[:id] - return nonprofit.campaigns.find(params[:campaign_id] || params[:id]) + nonprofit.campaigns.find(params[:campaign_id] || params[:id]) end end end diff --git a/app/legacy_lib/fetch_event.rb b/app/legacy_lib/fetch_event.rb index 77430cd2c0..8a9e584f3c 100644 --- a/app/legacy_lib/fetch_event.rb +++ b/app/legacy_lib/fetch_event.rb @@ -6,9 +6,9 @@ module FetchEvent def self.with_params(params, nonprofit = nil) nonprofit ||= FetchNonprofit.with_params(params) if params[:event_slug] - return nonprofit.events.find_by_slug(params[:event_slug]) + nonprofit.events.find_by_slug(params[:event_slug]) elsif params[:event_id] || params[:id] - return nonprofit.events.find(params[:event_id] || params[:id]) + nonprofit.events.find(params[:event_id] || params[:id]) end end end diff --git a/app/legacy_lib/fetch_miscellaneous_np_info.rb b/app/legacy_lib/fetch_miscellaneous_np_info.rb index e9d468a697..1f60008685 100644 --- a/app/legacy_lib/fetch_miscellaneous_np_info.rb +++ b/app/legacy_lib/fetch_miscellaneous_np_info.rb @@ -4,9 +4,9 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module FetchMiscellaneousNpInfo def self.fetch(np_id) - ParamValidation.new({ np_id: np_id }, np_id: { required: true, is_integer: true }) + ParamValidation.new({np_id: np_id}, np_id: {required: true, is_integer: true}) raise ParamValidation::ValidationError.new("Nonprofit #{np_id} does not exist", key: :np_id) unless Nonprofit.exists?(np_id) - MiscellaneousNpInfo.where('nonprofit_id = ?', np_id).first_or_initialize + MiscellaneousNpInfo.where("nonprofit_id = ?", np_id).first_or_initialize end end diff --git a/app/legacy_lib/fetch_nonprofit_email.rb b/app/legacy_lib/fetch_nonprofit_email.rb index 57cbe4969b..8b4d9916e2 100644 --- a/app/legacy_lib/fetch_nonprofit_email.rb +++ b/app/legacy_lib/fetch_nonprofit_email.rb @@ -5,11 +5,11 @@ module FetchNonprofitEmail def self.with_charge(charge) nonprofit = charge.nonprofit - nonprofit.email.blank? ? Houdini.hoster.support_email : nonprofit.email + nonprofit.email.presence || Houdini.hoster.support_email end def self.with_donation(donation) nonprofit = donation.nonprofit - nonprofit.email.blank? ? Houdini.hoster.support_email : nonprofit.email + nonprofit.email.presence || Houdini.hoster.support_email end end diff --git a/app/legacy_lib/fetch_stripe_account.rb b/app/legacy_lib/fetch_stripe_account.rb index 9388f7dbf1..f27b1da0f9 100644 --- a/app/legacy_lib/fetch_stripe_account.rb +++ b/app/legacy_lib/fetch_stripe_account.rb @@ -8,7 +8,7 @@ module FetchStripeAccount def self.with_account_id(stripe_account_id) begin stripe_acct = Stripe::Account.retrieve(stripe_account_id) - rescue StandardError + rescue stripe_acct = nil end stripe_acct diff --git a/app/legacy_lib/fetch_todo_status.rb b/app/legacy_lib/fetch_todo_status.rb index 7443eba70f..a4eafd4a7b 100644 --- a/app/legacy_lib/fetch_todo_status.rb +++ b/app/legacy_lib/fetch_todo_status.rb @@ -23,7 +23,7 @@ def self.for_dashboard(np) has_bank: np.bank_account.present?, is_paying: np.billing_plan.present?, has_imported: np.supporters.pluck(:imported_at).any?, - is_verified: np.verification_status == 'verified' && np.bank_account.present?, + is_verified: np.verification_status == "verified" && np.bank_account.present?, has_thank_you: np.thank_you_note.present? } end diff --git a/app/legacy_lib/format/address.rb b/app/legacy_lib/format/address.rb index 5caf1c01e9..a950a2337a 100644 --- a/app/legacy_lib/format/address.rb +++ b/app/legacy_lib/format/address.rb @@ -6,11 +6,11 @@ module Format module Address def self.full_address(street, city, state, zip = nil) # Albuquerque | NM | Albuquerque NM | 1234 Street Ln, Albuquerque NM - [[street, city].compact.join(', '), state, zip].compact.join(' ') + [[street, city].compact.join(", "), state, zip].compact.join(" ") end def self.city_and_state(city, state) - [city, state].join(', ') if !city.blank? && !state.blank? + [city, state].join(", ") if !city.blank? && !state.blank? end def self.city_or_state(city, state) @@ -18,8 +18,8 @@ def self.city_or_state(city, state) end def self.with_supporter(s) - return '' if s.nil? + return "" if s.nil? - [[s.address, s.city, s.state_code].reject(&:blank?).join(', '), s.zip_code].reject(&:blank?).join(' ') + [[s.address, s.city, s.state_code].reject(&:blank?).join(", "), s.zip_code].reject(&:blank?).join(" ") end -end; end + end; end diff --git a/app/legacy_lib/format/csv.rb b/app/legacy_lib/format/csv.rb index a30a404a1c..78275ff955 100644 --- a/app/legacy_lib/format/csv.rb +++ b/app/legacy_lib/format/csv.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'csv' -require 'format/currency' +require "csv" +require "format/currency" module Format module Csv diff --git a/app/legacy_lib/format/currency.rb b/app/legacy_lib/format/currency.rb index 11d8850e6a..5a3efae01a 100644 --- a/app/legacy_lib/format/currency.rb +++ b/app/legacy_lib/format/currency.rb @@ -8,7 +8,7 @@ module Currency # @param [String] units # @return [Integer] def self.dollars_to_cents(units) - (units.delete(',').gsub(Houdini.intl.currencies[0], '').to_f * 100).to_i + (units.delete(",").gsub(Houdini.intl.currencies[0], "").to_f * 100).to_i end # Converts currency subunits into units. @@ -16,8 +16,8 @@ def self.dollars_to_cents(units) # @return [String] def self.cents_to_dollars(subunits) (subunits.to_f / 100.0).to_s - .gsub(/^(\d+)\.0$/, '\1') # remove trailing zero if no decimals (eg. "1.0" -> "1") - .gsub(/^(\d+)\.(\d)$/, '\1.\20') # add a second zero if single decimal (eg. "9.9" -> "9.90") + .gsub(/^(\d+)\.0$/, '\1') # remove trailing zero if no decimals (eg. "1.0" -> "1") + .gsub(/^(\d+)\.(\d)$/, '\1.\20') # add a second zero if single decimal (eg. "9.9" -> "9.90") end # Print money based on informed currency @@ -26,10 +26,10 @@ def self.cents_to_dollars(subunits) # @param [Boolean] sign whether it should show the sign of the amount # @param [Boolean] use_precision whether it should have two decimal cases # @return [String] the text with the amount of money in the informed currency (Ex.: $10.00) - def self.print_currency(cents, unit = 'EUR', sign = true, use_precision = false) + def self.print_currency(cents, unit = "EUR", sign = true, use_precision = false) dollars = cents.to_f / 100.0 - dollars = ActiveSupport::NumberHelper.number_to_currency(dollars, unit: unit.to_s, precision: !use_precision && dollars.round == dollars ? 0 : 2) + dollars = ActiveSupport::NumberHelper.number_to_currency(dollars, unit: unit.to_s, precision: (!use_precision && dollars.round == dollars) ? 0 : 2) dollars = dollars[1..-1] unless sign dollars end -end; end + end; end diff --git a/app/legacy_lib/format/date.rb b/app/legacy_lib/format/date.rb index db6c9298f3..44e560b1c6 100644 --- a/app/legacy_lib/format/date.rb +++ b/app/legacy_lib/format/date.rb @@ -2,17 +2,16 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'chronic' +require "chronic" module Format module Date - def self.parse(str) Chronic.parse(str) end def self.from(str) - DateTime.strptime(str, '%m/%d/%Y') + DateTime.strptime(str, "%m/%d/%Y") end def self.to_readable(date) @@ -20,37 +19,37 @@ def self.to_readable(date) end def self.full(date, timezone = nil) - return '' if date.nil? + return "" if date.nil? date = Chronic.parse(date) if date.is_a?(String) date = date.in_time_zone(timezone) if timezone - date.strftime('%m/%-d/%Y %l:%M%P') + date.strftime("%m/%-d/%Y %l:%M%P") end def self.full_range(date1, date2, timezone = nil) return full(date1, timezone) if date2.nil? return full(date2, timezone) if date1.nil? if simple(date1) == simple(date2) - return full(date1, timezone) + ' - ' + time(date2, timezone) + full(date1, timezone) + " - " + time(date2, timezone) else - return full(date1, timezone) + ' - ' + full(date2, timezone) + full(date1, timezone) + " - " + full(date2, timezone) end end def self.simple(date, timezone = nil) - return '' if date.nil? + return "" if date.nil? date = Chronic.parse(date) if date.is_a?(String) date = date.in_time_zone(timezone) if timezone - date.strftime('%m/%d/%Y') + date.strftime("%m/%d/%Y") end def self.time(datetime, timezone = nil) - return '' if datetime.nil? + return "" if datetime.nil? datetime = Chronic.parse(datetime) if datetime.is_a?(String) datetime = datetime.in_time_zone(timezone) if timezone - datetime.strftime('%l:%M%P') + datetime.strftime("%l:%M%P") end def self.us_timezones @@ -66,4 +65,4 @@ def self.parse_partial_str(str) Time.new(*str.match(/(\d\d\d\d)-?(\d\d)?-?(\d\d)?/).to_a[1..-1].compact.map(&:to_i)) end -end; end + end; end diff --git a/app/legacy_lib/format/dedication.rb b/app/legacy_lib/format/dedication.rb index dabf98d9da..9ff33e1c40 100644 --- a/app/legacy_lib/format/dedication.rb +++ b/app/legacy_lib/format/dedication.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'json' +require "json" module Format module Dedication def self.from_json(json_text) begin hash = JSON.parse(json_text) - rescue StandardError + rescue return json_text end - "Donation made in #{hash['type'] || 'honor'} of #{hash['name']}. Note: #{hash['note']}" + "Donation made in #{hash["type"] || "honor"} of #{hash["name"]}. Note: #{hash["note"]}" end end end diff --git a/app/legacy_lib/format/geography.rb b/app/legacy_lib/format/geography.rb index 8c17d22d39..df6a036985 100644 --- a/app/legacy_lib/format/geography.rb +++ b/app/legacy_lib/format/geography.rb @@ -7,294 +7,294 @@ module Geography StateCodes = %w[AL AK AZ AR CA CO CT DE DC FL GA HI ID IL IN IA KS KY LA ME MD MA MI MN MS MO MT NE NV NH NJ NM NY NC ND OH OK OR PA PR RI SC SD TN TX UT VT VA WA WV WI WY].freeze StateMappings = { - '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' + "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" }.freeze Countries = [ - 'Afghanistan', - 'Albania', - 'Algeria', - 'American Samoa', - 'Andorra', - 'Angola', - 'Anguilla', - 'Antarctica', - 'Antigua and Barbuda', - 'Argentina', - 'Armenia', - 'Aruba', - 'Australia', - 'Austria', - 'Azerbaijan', - 'Bahamas', - 'Bahrain', - 'Bangladesh', - 'Barbados', - 'Belarus', - 'Belgium', - 'Belize', - 'Benin', - 'Bermuda', - 'Bhutan', - 'Bolivia', - 'Bosnia and Herzegovina', - 'Botswana', - 'Bouvet Island', - 'Brazil', - 'British Indian Ocean Territory', - 'Brunei Darussalam', - 'Bulgaria', - 'Burkina Faso', - 'Burundi', - 'Cambodia', - 'Cameroon', - 'Canada', - 'Cape Verde', - 'Cayman Islands', - 'Central African Republic', - 'Chad', - 'Chile', - 'China', - 'Christmas Island', - 'Cocos (Keeling) Islands', - 'Colombia', - 'Comoros', - 'Congo', - 'Cook Islands', - 'Costa Rica', + "Afghanistan", + "Albania", + "Algeria", + "American Samoa", + "Andorra", + "Angola", + "Anguilla", + "Antarctica", + "Antigua and Barbuda", + "Argentina", + "Armenia", + "Aruba", + "Australia", + "Austria", + "Azerbaijan", + "Bahamas", + "Bahrain", + "Bangladesh", + "Barbados", + "Belarus", + "Belgium", + "Belize", + "Benin", + "Bermuda", + "Bhutan", + "Bolivia", + "Bosnia and Herzegovina", + "Botswana", + "Bouvet Island", + "Brazil", + "British Indian Ocean Territory", + "Brunei Darussalam", + "Bulgaria", + "Burkina Faso", + "Burundi", + "Cambodia", + "Cameroon", + "Canada", + "Cape Verde", + "Cayman Islands", + "Central African Republic", + "Chad", + "Chile", + "China", + "Christmas Island", + "Cocos (Keeling) Islands", + "Colombia", + "Comoros", + "Congo", + "Cook Islands", + "Costa Rica", "Cote D'ivoire", - 'Croatia', - 'Cuba', - 'Cyprus', - 'Czech Republic', - 'Denmark', - 'Djibouti', - 'Dominica', - 'Dominican Republic', - 'Ecuador', - 'Egypt', - 'El Salvador', - 'Equatorial Guinea', - 'Eritrea', - 'Estonia', - 'Ethiopia', - 'Falkland Islands (Malvinas)', - 'Faroe Islands', - 'Fiji', - 'Finland', - 'France', - 'French Guiana', - 'French Polynesia', - 'French Southern Territories', - 'Gabon', - 'Gambia', - 'Georgia', - 'Germany', - 'Ghana', - 'Gibraltar', - 'Greece', - 'Greenland', - 'Grenada', - 'Guadeloupe', - 'Guam', - 'Guatemala', - 'Guinea', - 'Guinea-bissau', - 'Guyana', - 'Haiti', - 'Heard Island and Mcdonald Islands', - 'Honduras', - 'Hong Kong', - 'Hungary', - 'Iceland', - 'India', - 'Indonesia', - 'Iran', - 'Iraq', - 'Ireland', - 'Israel', - 'Italy', - 'Jamaica', - 'Japan', - 'Jordan', - 'Kazakhstan', - 'Kenya', - 'Kiribati', - 'Korea (South)', - 'Kuwait', - 'Kyrgyzstan', + "Croatia", + "Cuba", + "Cyprus", + "Czech Republic", + "Denmark", + "Djibouti", + "Dominica", + "Dominican Republic", + "Ecuador", + "Egypt", + "El Salvador", + "Equatorial Guinea", + "Eritrea", + "Estonia", + "Ethiopia", + "Falkland Islands (Malvinas)", + "Faroe Islands", + "Fiji", + "Finland", + "France", + "French Guiana", + "French Polynesia", + "French Southern Territories", + "Gabon", + "Gambia", + "Georgia", + "Germany", + "Ghana", + "Gibraltar", + "Greece", + "Greenland", + "Grenada", + "Guadeloupe", + "Guam", + "Guatemala", + "Guinea", + "Guinea-bissau", + "Guyana", + "Haiti", + "Heard Island and Mcdonald Islands", + "Honduras", + "Hong Kong", + "Hungary", + "Iceland", + "India", + "Indonesia", + "Iran", + "Iraq", + "Ireland", + "Israel", + "Italy", + "Jamaica", + "Japan", + "Jordan", + "Kazakhstan", + "Kenya", + "Kiribati", + "Korea (South)", + "Kuwait", + "Kyrgyzstan", "Lao People's Democratic Republic", - 'Latvia', - 'Lebanon', - 'Lesotho', - 'Liberia', - 'Libyan Arab Jamahiriya', - 'Liechtenstein', - 'Lithuania', - 'Luxembourg', - 'Macao', - 'Macedonia', - 'Madagascar', - 'Malawi', - 'Malaysia', - 'Maldives', - 'Mali', - 'Malta', - 'Marshall Islands', - 'Martinique', - 'Mauritania', - 'Mauritius', - 'Mayotte', - 'Mexico', - 'Micronesia', - 'Moldova', - 'Monaco', - 'Mongolia', - 'Montserrat', - 'Morocco', - 'Mozambique', - 'Myanmar', - 'Namibia', - 'Nauru', - 'Nepal', - 'Netherlands', - 'Netherlands Antilles', - 'New Caledonia', - 'New Zealand', - 'Nicaragua', - 'Niger', - 'Nigeria', - 'Niue', - 'Norfolk Island', - 'Northern Mariana Islands', - 'Norway', - 'Oman', - 'Pakistan', - 'Palau', - 'Palestinian Territory', - 'Panama', - 'Papua New Guinea', - 'Paraguay', - 'Peru', - 'Philippines', - 'Pitcairn', - 'Poland', - 'Portugal', - 'Puerto Rico', - 'Qatar', - 'Reunion', - 'Romania', - 'Russia', - 'Rwanda', - 'Saint Helena', - 'Saint Kitts and Nevis', - 'Saint Lucia', - 'Saint Pierre and Miquelon', - 'Saint Vincent and The Grenadines', - 'Samoa', - 'San Marino', - 'Sao Tome and Principe', - 'Saudi Arabia', - 'Senegal', - 'Serbia and Montenegro', - 'Seychelles', - 'Sierra Leone', - 'Singapore', - 'Slovakia', - 'Slovenia', - 'Solomon Islands', - 'Somalia', - 'South Africa', - 'South Georgia and The South Sandwich Islands', - 'Spain', - 'Sri Lanka', - 'Sudan', - 'Suriname', - 'Svalbard and Jan Mayen', - 'Swaziland', - 'Sweden', - 'Switzerland', - 'Syria ', - 'Taiwan', - 'Tajikistan', - 'Tanzania', - 'Thailand', - 'Timor-leste', - 'Togo', - 'Tokelau', - 'Tonga', - 'Trinidad and Tobago', - 'Tunisia', - 'Turkey', - 'Turkmenistan', - 'Tuvalu', - 'Uganda', - 'Ukraine', - 'United Arab Emirates', - 'United Kingdom', - 'United States', - 'Uruguay', - 'Uzbekistan', - 'Vanuatu', - 'Venezuela', - 'Viet Nam', - 'Virgin Islands', - 'Wallis and Futuna', - 'Western Sahara', - 'Yemen', - 'Zambia', - 'Zimbabwe' + "Latvia", + "Lebanon", + "Lesotho", + "Liberia", + "Libyan Arab Jamahiriya", + "Liechtenstein", + "Lithuania", + "Luxembourg", + "Macao", + "Macedonia", + "Madagascar", + "Malawi", + "Malaysia", + "Maldives", + "Mali", + "Malta", + "Marshall Islands", + "Martinique", + "Mauritania", + "Mauritius", + "Mayotte", + "Mexico", + "Micronesia", + "Moldova", + "Monaco", + "Mongolia", + "Montserrat", + "Morocco", + "Mozambique", + "Myanmar", + "Namibia", + "Nauru", + "Nepal", + "Netherlands", + "Netherlands Antilles", + "New Caledonia", + "New Zealand", + "Nicaragua", + "Niger", + "Nigeria", + "Niue", + "Norfolk Island", + "Northern Mariana Islands", + "Norway", + "Oman", + "Pakistan", + "Palau", + "Palestinian Territory", + "Panama", + "Papua New Guinea", + "Paraguay", + "Peru", + "Philippines", + "Pitcairn", + "Poland", + "Portugal", + "Puerto Rico", + "Qatar", + "Reunion", + "Romania", + "Russia", + "Rwanda", + "Saint Helena", + "Saint Kitts and Nevis", + "Saint Lucia", + "Saint Pierre and Miquelon", + "Saint Vincent and The Grenadines", + "Samoa", + "San Marino", + "Sao Tome and Principe", + "Saudi Arabia", + "Senegal", + "Serbia and Montenegro", + "Seychelles", + "Sierra Leone", + "Singapore", + "Slovakia", + "Slovenia", + "Solomon Islands", + "Somalia", + "South Africa", + "South Georgia and The South Sandwich Islands", + "Spain", + "Sri Lanka", + "Sudan", + "Suriname", + "Svalbard and Jan Mayen", + "Swaziland", + "Sweden", + "Switzerland", + "Syria ", + "Taiwan", + "Tajikistan", + "Tanzania", + "Thailand", + "Timor-leste", + "Togo", + "Tokelau", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Turkmenistan", + "Tuvalu", + "Uganda", + "Ukraine", + "United Arab Emirates", + "United Kingdom", + "United States", + "Uruguay", + "Uzbekistan", + "Vanuatu", + "Venezuela", + "Viet Nam", + "Virgin Islands", + "Wallis and Futuna", + "Western Sahara", + "Yemen", + "Zambia", + "Zimbabwe" ].freeze # Convert a full state name like "New Mexico" into a code like "NM" @@ -305,4 +305,4 @@ def self.full_state_to_code(str) StateMappings[str.downcase] end -end; end + end; end diff --git a/app/legacy_lib/format/html.rb b/app/legacy_lib/format/html.rb index 2f54733b92..55bf299779 100644 --- a/app/legacy_lib/format/html.rb +++ b/app/legacy_lib/format/html.rb @@ -5,7 +5,7 @@ module Format module HTML def self.has_only_empty_tags(html_str) - return true if html_str && html_str.gsub(/<[^>]*>/ui, '').gsub(' ', '').strip == '' + true if html_str && html_str.gsub(/<[^>]*>/ui, "").gsub(" ", "").strip == "" end end end diff --git a/app/legacy_lib/format/indefinitize.rb b/app/legacy_lib/format/indefinitize.rb index fc86289e0d..1e43455fee 100644 --- a/app/legacy_lib/format/indefinitize.rb +++ b/app/legacy_lib/format/indefinitize.rb @@ -7,11 +7,11 @@ module Indefinitize VOWELS = %w[a e i o u].freeze def self.article(word) - VOWELS.include?(word[0].downcase) ? 'an' : 'a' + VOWELS.include?(word[0].downcase) ? "an" : "a" end def self.with_article(word) - article(word) + ' ' + word + article(word) + " " + word end end end diff --git a/app/legacy_lib/format/interpolate.rb b/app/legacy_lib/format/interpolate.rb index 547a521a88..4eb9ba7ebf 100644 --- a/app/legacy_lib/format/interpolate.rb +++ b/app/legacy_lib/format/interpolate.rb @@ -5,9 +5,9 @@ module Format module Interpolate def self.with_hash(str, hash) - return '' if str.nil? + return "" if str.nil? - str.gsub(/{{.+}}/) { |key| hash[key.gsub(/[{}]/, '')] } + str.gsub(/{{.+}}/) { |key| hash[key.gsub(/[{}]/, "")] } end end end diff --git a/app/legacy_lib/format/name.rb b/app/legacy_lib/format/name.rb index 7280766f31..ed1f4ca39d 100644 --- a/app/legacy_lib/format/name.rb +++ b/app/legacy_lib/format/name.rb @@ -2,19 +2,19 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'active_support/core_ext' +require "active_support/core_ext" module Format module Name def self.split_full(name) - return '' if name.nil? + return "" if name.nil? name.split(/\ (\w+\s*)$/) end # Format a nonprofit name into an email header def self.email_from_np(np_name) - "\"#{np_name.delete(',').delete('"')}\" <#{Houdini.hoster.support_email}>" + "\"#{np_name.delete(",").delete('"')}\" <#{Houdini.hoster.support_email}>" end end end diff --git a/app/legacy_lib/format/phone.rb b/app/legacy_lib/format/phone.rb index 0d93e6514f..4a88b3a985 100644 --- a/app/legacy_lib/format/phone.rb +++ b/app/legacy_lib/format/phone.rb @@ -9,15 +9,15 @@ def self.readable(number) # (505) 263-6320 # or: # 263-6320 - return '' if number.blank? + return "" if number.blank? - stripped = number.gsub(/[-\(\)\.\s]/, '') # remove extra chars and space + stripped = number.gsub(/[-\(\)\.\s]/, "") # remove extra chars and space if stripped.length == 10 - return "(#{stripped[0..2]}) #{stripped[3..5]}-#{stripped[6..9]}" + "(#{stripped[0..2]}) #{stripped[3..5]}-#{stripped[6..9]}" elsif stripped.length == 7 - return "#{stripped[0..2]}-#{stripped[3..6]}" + "#{stripped[0..2]}-#{stripped[3..6]}" else - return number + number end end -end; end + end; end diff --git a/app/legacy_lib/format/remove_diacritics.rb b/app/legacy_lib/format/remove_diacritics.rb index 2777c6b1d4..981c8ff789 100644 --- a/app/legacy_lib/format/remove_diacritics.rb +++ b/app/legacy_lib/format/remove_diacritics.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'i18n' +require "i18n" module Format module RemoveDiacritics @@ -10,7 +10,7 @@ def self.from_hash(hash, keys) # returns a new hash with any diacritics replaced with a plain character # only from values corresponding to specified keys: # {"city" => "São Paulo"} ["city"] will return {"city" => "Sao Paulo"} - Hash[hash.map { |k, v| [k, (keys.include? k) ? I18n.transliterate(v) : v] }] + Hash[hash.map { |k, v| [k, keys.include?(k) ? I18n.transliterate(v) : v] }] end end end diff --git a/app/legacy_lib/format/timezone.rb b/app/legacy_lib/format/timezone.rb index 0c4d107927..93b6c27ad6 100644 --- a/app/legacy_lib/format/timezone.rb +++ b/app/legacy_lib/format/timezone.rb @@ -6,21 +6,21 @@ module Format module Timezone def self.to_proxy(str) dict = { - 'Hawaii' => 'Pacific/Honolulu', - 'Alaska' => 'America/Juneau', - 'Pacific Time (US & Canada)' => 'America/Los_Angeles', - 'Arizona' => 'America/Phoenix', - 'Mountain Time (US & Canada)' => 'America/Denver', - 'Central Time (US & Canada)' => 'America/Chicago', - 'Eastern Time (US & Canada)' => 'America/New_York', - 'Indiana (East)' => 'America/Indiana/Indianapolis' + "Hawaii" => "Pacific/Honolulu", + "Alaska" => "America/Juneau", + "Pacific Time (US & Canada)" => "America/Los_Angeles", + "Arizona" => "America/Phoenix", + "Mountain Time (US & Canada)" => "America/Denver", + "Central Time (US & Canada)" => "America/Chicago", + "Eastern Time (US & Canada)" => "America/New_York", + "Indiana (East)" => "America/Indiana/Indianapolis" } if dict.key?(str) - return dict[str] + dict[str] elsif dict.value?(str) - return str + str else - return false + false end end end diff --git a/app/legacy_lib/format/url.rb b/app/legacy_lib/format/url.rb index bc201fcdc2..fa1ccaf050 100644 --- a/app/legacy_lib/format/url.rb +++ b/app/legacy_lib/format/url.rb @@ -5,26 +5,26 @@ module Format module Url def self.without_prefix(url) - url.gsub(%r{(http(s)?://)|(www\.)|(\?.*$)|(#.*$)}, '') + url.gsub(%r{(http(s)?://)|(www\.)|(\?.*$)|(#.*$)}, "") end # Given ["What hello", "hi! lol?"] # Return ["what-hello", "hi-lol"] def self.convert_to_slug(*words) - return '' if words.empty? || !words.all? # true if any are nil or empty + return "" if words.empty? || !words.all? # true if any are nil or empty words.map do |d| d.strip.downcase - .gsub(/['`]/, '') # no apostrophes - .delete('.') # no dots - .gsub(/\s*@\s*/, ' at ') # @ -> at - .gsub(/\s*&\s*/, ' and ') # & -> and - .gsub(/\s*[^A-Za-z0-9\.\-]\s*/, '-') # replace oddballs with hyphen - .gsub(/\A[-\.]+|[-\.]+\z/, '') # strip leading/trailing hyphens - end.join('/') + .gsub(/['`]/, "") # no apostrophes + .delete(".") # no dots + .gsub(/\s*@\s*/, " at ") # @ -> at + .gsub(/\s*&\s*/, " and ") # & -> and + .gsub(/\s*[^A-Za-z0-9\.\-]\s*/, "-") # replace oddballs with hyphen + .gsub(/\A[-\.]+|[-\.]+\z/, "") # strip leading/trailing hyphens + end.join("/") end def self.concat(*urls) - urls.join('/').gsub(%r{([^:])//+}, '\1/') + urls.join("/").gsub(%r{([^:])//+}, '\1/') end -end; end + end; end diff --git a/app/legacy_lib/generate_locales.rb b/app/legacy_lib/generate_locales.rb index 2105a11c65..0f48d181f3 100644 --- a/app/legacy_lib/generate_locales.rb +++ b/app/legacy_lib/generate_locales.rb @@ -4,23 +4,22 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module GenerateLocales - def self.generate + def self.generate + I18n::JS.export + File.open(Rails.root.join("app/javascript/i18n/locales/index.js"), "w") do |file| + file << "// DO NOT MODIFY THIS FILE. AUTOGENERATED\n" + file << "const translations = {};\n\n" + I18n::JS.translations.select { |k, v| Houdini.intl.available_locales.map(&:to_s).include?(k.to_s) }.each_key do |k| + file << "translations['#{k}'] = require('./#{k}').default['#{k}'];\n" + end - I18n::JS::export - File.open(Rails.root.join('app', 'javascript', 'i18n', 'locales', 'index.js'), 'w') do |file| - file << "// DO NOT MODIFY THIS FILE. AUTOGENERATED\n" - file << "const translations = {};\n\n" - I18n::JS::translations.select{|k,v| Houdini.intl.available_locales.map(&:to_s).include?(k.to_s)}.each_key do |k| - file << "translations['#{k}'] = require('./#{k}').default['#{k}'];\n" - end + file << "\nmodule.exports = translations" + end - file << "\nmodule.exports = translations" - end - - File.open(Rails.root.join('app', 'javascript', 'i18n', 'locales', 'index.d.ts'), 'w') do |file| - file << "// DO NOT MODIFY THIS FILE. AUTOGENERATED\n" - file << "declare const translations: Record;\n\n" - file << "module.exports = translations" - end - end -end \ No newline at end of file + File.open(Rails.root.join("app/javascript/i18n/locales/index.d.ts"), "w") do |file| + file << "// DO NOT MODIFY THIS FILE. AUTOGENERATED\n" + file << "declare const translations: Record;\n\n" + file << "module.exports = translations" + end + end +end diff --git a/app/legacy_lib/health_report.rb b/app/legacy_lib/health_report.rb index 1a54594f4b..b6b28e1d99 100644 --- a/app/legacy_lib/health_report.rb +++ b/app/legacy_lib/health_report.rb @@ -8,32 +8,32 @@ module HealthReport # Returns a hash of metrics data def self.query_data # Transaction metrics - charges = Qx.select('COUNT(charges.id), SUM(charges.amount), SUM(charges.fee) as fees') - .from('charges') - .where('created_at > $d', d: 24.hours.ago) - .and_where("charges.status != 'failed'") - .ex.last + charges = Qx.select("COUNT(charges.id), SUM(charges.amount), SUM(charges.fee) as fees") + .from("charges") + .where("created_at > $d", d: 24.hours.ago) + .and_where("charges.status != 'failed'") + .ex.last # Recurring donation metrics - rec_dons = Qx.select('COUNT(id), SUM(amount)') - .from('recurring_donations') - .where('active=TRUE') - .ex.last + rec_dons = Qx.select("COUNT(id), SUM(amount)") + .from("recurring_donations") + .where("active=TRUE") + .ex.last # Info about disabled nonprofit accounts due to ident verification - disabled_nps = Qx.select('nonprofits.id', 'nonprofits.name', 'nonprofits.stripe_account_id') - .from('nonprofits') - .where("verification_status != 'verified'") - .and_where('created_at > $d', d: 3.months.ago) - .ex(format: 'csv') + disabled_nps = Qx.select("nonprofits.id", "nonprofits.name", "nonprofits.stripe_account_id") + .from("nonprofits") + .where("verification_status != 'verified'") + .and_where("created_at > $d", d: 3.months.ago) + .ex(format: "csv") { - charges_count: charges['count'], - charges_sum: charges['sum'], - charges_fees: charges['fees'], + charges_count: charges["count"], + charges_sum: charges["sum"], + charges_fees: charges["fees"], recently_disabled_nps: disabled_nps, - active_rec_don_count: rec_dons['count'], - active_rec_don_amount: rec_dons['sum'] + active_rec_don_count: rec_dons["count"], + active_rec_don_amount: rec_dons["sum"] } end diff --git a/app/legacy_lib/image.rb b/app/legacy_lib/image.rb index d1c1979688..fd5f24d0ea 100644 --- a/app/legacy_lib/image.rb +++ b/app/legacy_lib/image.rb @@ -3,13 +3,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Image - def self._url(resource_name, image_name, version = 'normal') + def self._url(resource_name, image_name, version = "normal") %( concat(#{Qexpr.quote AssetPath} , '/', #{Qexpr.quote resource_name} , '/', #{Qexpr.quote image_name} - , '/', #{resource_name + '.id'} - , '/', #{Qexpr.quote version}, '_', #{resource_name + '.' + image_name}) + , '/', #{resource_name + ".id"} + , '/', #{Qexpr.quote version}, '_', #{resource_name + "." + image_name}) ) end end diff --git a/app/legacy_lib/import_civicrm_payments.rb b/app/legacy_lib/import_civicrm_payments.rb index 60d7a9bed9..cafb35c814 100644 --- a/app/legacy_lib/import_civicrm_payments.rb +++ b/app/legacy_lib/import_civicrm_payments.rb @@ -8,50 +8,50 @@ def self.import_from_csv(csv_body, nonprofit, field_of_supporter_id) questionable_records = [] Qx.transaction do CSV::Converters[:blank_to_nil] = lambda do |field| - field && field.empty? ? nil : field + (field && field.empty?) ? nil : field end csv = CSV.new(csv_body, headers: true, converters: [:blank_to_nil]) contrib_records = csv.to_a.map(&:to_hash) pay_imp = PaymentImport.create(nonprofit: nonprofit) - supporter_id_custom_field = CustomFieldDefinition.where('nonprofit_id = ? AND name = ?', nonprofit.id, field_of_supporter_id).first + supporter_id_custom_field = CustomFieldDefinition.where("nonprofit_id = ? AND name = ?", nonprofit.id, field_of_supporter_id).first unless supporter_id_custom_field raise ParamValidation::ValidationError.new("There is no custom field for nonprofit #{nonprofit.id} and field named #{field_of_supporter_id}", key: :field_of_supporter_id) end - supporters_with_fields = Supporter.includes(:custom_field_joins).where('supporters.nonprofit_id = ? AND custom_field_joins.custom_field_definition_id = ?', nonprofit.id, supporter_id_custom_field.id) + supporters_with_fields = Supporter.includes(:custom_field_joins).where("supporters.nonprofit_id = ? AND custom_field_joins.custom_field_definition_id = ?", nonprofit.id, supporter_id_custom_field.id) contrib_records.each do |r| - our_supporter = supporters_with_fields.where('custom_field_joins.value = ?', r[field_of_supporter_id].to_s).first + our_supporter = supporters_with_fields.where("custom_field_joins.value = ?", r[field_of_supporter_id].to_s).first unless our_supporter questionable_records.push(r) next end - known_fields = ['Date Received', 'Total Amount'] + known_fields = ["Date Received", "Total Amount"] - notes = '' + notes = "" r.except(known_fields).keys.each do |k| notes += "#{k}: #{r[k]}\n" end offsite = nil - if r['payment_instrument'] == 'Check' - offsite = { kind: 'check', check_number: r['Check Number'] } + if r["payment_instrument"] == "Check" + offsite = {kind: "check", check_number: r["Check Number"]} end - puts r['Date Received'] + puts r["Date Received"] date_received = nil - Time.use_zone('Pacific Time (US & Canada)') do - date_received = Time.zone.parse(r['Date Received']) + Time.use_zone("Pacific Time (US & Canada)") do + date_received = Time.zone.parse(r["Date Received"]) puts date_received end d = InsertDonation.offsite( { - amount: Format::Currency.dollars_to_cents(r['Total Amount']), + amount: Format::Currency.dollars_to_cents(r["Total Amount"]), nonprofit_id: nonprofit.id, supporter_id: our_supporter.id, comment: notes, @@ -60,7 +60,7 @@ def self.import_from_csv(csv_body, nonprofit, field_of_supporter_id) }.with_indifferent_access ) puts d - pay_imp.donations.push(Donation.find(d[:json]['donation']['id'])) + pay_imp.donations.push(Donation.find(d[:json]["donation"]["id"])) end end questionable_records diff --git a/app/legacy_lib/include_asset.rb b/app/legacy_lib/include_asset.rb index f655ccdfa8..051508773c 100644 --- a/app/legacy_lib/include_asset.rb +++ b/app/legacy_lib/include_asset.rb @@ -16,6 +16,6 @@ def self.css(path) private def self.asset_version - ENV['ASSET_VERSION'] + ENV["ASSET_VERSION"] end end diff --git a/app/legacy_lib/insert_activities.rb b/app/legacy_lib/insert_activities.rb index 7961e59b88..6c658f8f5b 100644 --- a/app/legacy_lib/insert_activities.rb +++ b/app/legacy_lib/insert_activities.rb @@ -18,162 +18,161 @@ def self.create(data) Qx.insert_into(:activities) .values(data) .ts - .returning('*') + .returning("*") .execute end def self.for_recurring_donations(payment_ids) insert_recurring_donations_expr - .and_where('payments.id IN ($ids)', ids: payment_ids) + .and_where("payments.id IN ($ids)", ids: payment_ids) .execute end def self.insert_recurring_donations_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - 'payments.supporter_id', - "'Payment' AS attachment_type", - 'payments.id AS attachment_id', - 'payments.nonprofit_id', - 'payments.date', - "json_build_object('gross_amount', payments.gross_amount, 'start_date', donations.created_at, 'designation', donations.designation, 'dedication', donations.dedication, 'interval', recurring_donations.interval, 'time_unit', recurring_donations.time_unit)", - "'RecurringDonation' AS kind" - ])) + "payments.supporter_id", + "'Payment' AS attachment_type", + "payments.id AS attachment_id", + "payments.nonprofit_id", + "payments.date", + "json_build_object('gross_amount', payments.gross_amount, 'start_date', donations.created_at, 'designation', donations.designation, 'dedication', donations.dedication, 'interval', recurring_donations.interval, 'time_unit', recurring_donations.time_unit)", + "'RecurringDonation' AS kind" + ])) .from(:payments) - .join(:donations, 'donations.id=payments.donation_id') - .add_join(:recurring_donations, 'recurring_donations.donation_id=donations.id') + .join(:donations, "donations.id=payments.donation_id") + .add_join(:recurring_donations, "recurring_donations.donation_id=donations.id") .where("payments.kind='RecurringDonation'") end def self.for_one_time_donations(payment_ids) insert_one_time_donations_expr - .and_where('payments.id IN ($ids)', ids: payment_ids) + .and_where("payments.id IN ($ids)", ids: payment_ids) .execute end def self.insert_one_time_donations_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - 'payments.supporter_id', - "'Payment' AS attachment_type", - 'payments.id AS attachment_id', - 'payments.nonprofit_id', - 'payments.date', - "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'dedication', donations.dedication)", - "'Donation' AS kind" - ])) + "payments.supporter_id", + "'Payment' AS attachment_type", + "payments.id AS attachment_id", + "payments.nonprofit_id", + "payments.date", + "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'dedication', donations.dedication)", + "'Donation' AS kind" + ])) .from(:payments) - .join(:donations, 'donations.id=payments.donation_id') + .join(:donations, "donations.id=payments.donation_id") .where("payments.kind='Donation'") end def self.for_tickets(ticket_ids) insert_tickets_expr - .and_where('tickets.id IN ($ids)', ids: ticket_ids) + .and_where("tickets.id IN ($ids)", ids: ticket_ids) .execute end def self.insert_tickets_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - 'tickets.supporter_id', - "'Ticket' AS attachment_type", - 'tickets.id AS attachment_id', - 'event.nonprofit_id', - 'tickets.created_at AS date', - "json_build_object('gross_amount', coalesce(payment.gross_amount, 0), 'event_name', event.name, 'event_id', event.id, 'quantity', tickets.quantity)", - "'Ticket' AS kind" - ])) + "tickets.supporter_id", + "'Ticket' AS attachment_type", + "tickets.id AS attachment_id", + "event.nonprofit_id", + "tickets.created_at AS date", + "json_build_object('gross_amount', coalesce(payment.gross_amount, 0), 'event_name', event.name, 'event_id', event.id, 'quantity', tickets.quantity)", + "'Ticket' AS kind" + ])) .from(:tickets) - .join('payments AS payment', 'payment.id=tickets.payment_id') - .add_join('events AS event', 'event.id=tickets.event_id') + .join("payments AS payment", "payment.id=tickets.payment_id") + .add_join("events AS event", "event.id=tickets.event_id") end def self.for_refunds(payment_ids) insert_refunds_expr - .and_where('payments.id IN ($ids)', ids: payment_ids) + .and_where("payments.id IN ($ids)", ids: payment_ids) .execute end def self.insert_refunds_expr - Qx.insert_into(:activities, insert_cols.concat(['user_id'])) + Qx.insert_into(:activities, insert_cols.concat(["user_id"])) .select(defaults.concat([ - 'payments.supporter_id', - "'Payment' AS attachment_type", - 'payments.id AS attachment_id', - 'payments.nonprofit_id', - 'payments.date', - "json_build_object('gross_amount', payments.gross_amount, 'reason', refunds.reason, 'user_email', users.email)", - "'Refund' AS kind", - 'users.id AS user_id' - ])) + "payments.supporter_id", + "'Payment' AS attachment_type", + "payments.id AS attachment_id", + "payments.nonprofit_id", + "payments.date", + "json_build_object('gross_amount', payments.gross_amount, 'reason', refunds.reason, 'user_email', users.email)", + "'Refund' AS kind", + "users.id AS user_id" + ])) .from(:payments) - .join(:refunds, 'refunds.payment_id=payments.id') - .left_join(:users, 'refunds.user_id=users.id') + .join(:refunds, "refunds.payment_id=payments.id") + .left_join(:users, "refunds.user_id=users.id") .where("payments.kind='Refund'") end def self.for_disputes(payment_ids) insert_disputes_expr - .and_where('payments.id IN ($ids)', ids: payment_ids) + .and_where("payments.id IN ($ids)", ids: payment_ids) .execute end def self.insert_disputes_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - 'payments.supporter_id', - "'Payment' AS attachment_type", - 'payments.id AS attachment_id', - 'payments.nonprofit_id', - 'payments.date', - "json_build_object('gross_amount', payments.gross_amount, 'reason', disputes.reason, 'original_kind', other_payment.kind, 'original_date', other_payment.date)", - "'Dispute' AS kind" - ])) + "payments.supporter_id", + "'Payment' AS attachment_type", + "payments.id AS attachment_id", + "payments.nonprofit_id", + "payments.date", + "json_build_object('gross_amount', payments.gross_amount, 'reason', disputes.reason, 'original_kind', other_payment.kind, 'original_date', other_payment.date)", + "'Dispute' AS kind" + ])) .from(:payments) - .join(:disputes, 'disputes.payment_id=payments.id') - .add_join(:charges, 'disputes.charge_id=charges.id') - .add_join('payments AS other_payment', 'other_payment.id=charges.payment_id') + .join(:disputes, "disputes.payment_id=payments.id") + .add_join(:charges, "disputes.charge_id=charges.id") + .add_join("payments AS other_payment", "other_payment.id=charges.payment_id") .where("payments.kind='Dispute'") end def self.for_supporter_notes(notes) notes.map do |note| - note.activities.create(supporter: note.supporter, - nonprofit: note.supporter.nonprofit, + note.activities.create(supporter: note.supporter, + nonprofit: note.supporter.nonprofit, date: note.created_at, - kind: 'SupporterNote', + kind: "SupporterNote", user: note.user, json_data: { content: note.content, user_email: note.user&.email - } - ) + }) end end def self.for_offsite_donations(payment_ids) insert_offsite_donations_expr - .and_where('payments.id IN ($ids)', ids: payment_ids) + .and_where("payments.id IN ($ids)", ids: payment_ids) .execute end def self.insert_offsite_donations_expr - Qx.insert_into(:activities, insert_cols.concat(['user_id'])) + Qx.insert_into(:activities, insert_cols.concat(["user_id"])) .select(defaults.concat([ - 'payments.supporter_id', - "'Payment' AS attachment_type", - 'payments.id AS attachment_id', - 'payments.nonprofit_id', - 'payments.date', - "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'user_email', users.email)", - "'OffsitePayment' AS kind", - 'users.id AS user_id' - ])) + "payments.supporter_id", + "'Payment' AS attachment_type", + "payments.id AS attachment_id", + "payments.nonprofit_id", + "payments.date", + "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'user_email', users.email)", + "'OffsitePayment' AS kind", + "users.id AS user_id" + ])) .from(:payments) .where("payments.kind = 'OffsitePayment'") - .join(:offsite_payments, 'offsite_payments.payment_id=payments.id') - .add_join(:donations, 'payments.donation_id=donations.id') - .add_left_join(:users, 'users.id=offsite_payments.user_id') + .join(:offsite_payments, "offsite_payments.payment_id=payments.id") + .add_join(:donations, "payments.donation_id=donations.id") + .add_left_join(:users, "users.id=offsite_payments.user_id") end end diff --git a/app/legacy_lib/insert_bank_account.rb b/app/legacy_lib/insert_bank_account.rb index 34e516a7d7..1583e3ea16 100644 --- a/app/legacy_lib/insert_bank_account.rb +++ b/app/legacy_lib/insert_bank_account.rb @@ -11,20 +11,20 @@ module InsertBankAccount # email: app.user.email def self.with_stripe(nonprofit, user, params) - ParamValidation.new({ nonprofit: nonprofit, user: user }, - nonprofit: { - required: true, - is_a: Nonprofit - }, - user: { - required: true, - is_a: User - }) + ParamValidation.new({nonprofit: nonprofit, user: user}, + nonprofit: { + required: true, + is_a: Nonprofit + }, + user: { + required: true, + is_a: User + }) ParamValidation.new(params || {}, - stripe_bank_account_token: { - required: true, - not_blank: true - }) + stripe_bank_account_token: { + required: true, + not_blank: true + }) unless nonprofit.vetted raise ArgumentError, "#{nonprofit.id} is not vetted." @@ -42,7 +42,7 @@ def self.with_stripe(nonprofit, user, params) ba.default_for_currency = true ba.save - BankAccount.where('nonprofit_id = ?', nonprofit.id).update_all(deleted: true) + BankAccount.where("nonprofit_id = ?", nonprofit.id).update_all(deleted: true) bank_account = BankAccount.create( stripe_bank_account_id: ba.id, diff --git a/app/legacy_lib/insert_card.rb b/app/legacy_lib/insert_card.rb index 56d9a03c14..a60d72071b 100644 --- a/app/legacy_lib/insert_card.rb +++ b/app/legacy_lib/insert_card.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'hash' +require "hash" module InsertCard # Create a new card # If a stripe_customer_id is present, then update that customer's primary source; otherwise create a new customer @@ -22,12 +22,12 @@ module InsertCard def self.with_stripe(card_data, _stripe_account_id = nil, event_id = nil, current_user = nil) begin ParamValidation.new(card_data.merge(event_id: event_id), - holder_type: { required: true, included_in: %w[Nonprofit Supporter] }, - holder_id: { required: true }, - stripe_card_id: { not_blank: true, required: true }, - stripe_card_token: { not_blank: true, required: true }, - name: { not_blank: true, required: true }, - event_id: { is_reference: true }) + holder_type: {required: true, included_in: %w[Nonprofit Supporter]}, + holder_id: {required: true}, + stripe_card_id: {not_blank: true, required: true}, + stripe_card_token: {not_blank: true, required: true}, + name: {not_blank: true, required: true}, + event_id: {is_reference: true}) rescue ParamValidation::ValidationError => e raise e end @@ -35,22 +35,22 @@ def self.with_stripe(card_data, _stripe_account_id = nil, event_id = nil, curren # validate that the user is with the correct nonprofit card_data = card_data.slice(:holder_type, :holder_id, :stripe_card_id, :stripe_card_token, :name) - holder_types = { 'Nonprofit' => :nonprofit, 'Supporter' => :supporter } + holder_types = {"Nonprofit" => :nonprofit, "Supporter" => :supporter} holder_type = holder_types[card_data[:holder_type]] holder = nil begin if holder_type == :nonprofit - holder = Nonprofit.select('id, email').includes(:cards).find(card_data[:holder_id]) + holder = Nonprofit.select("id, email").includes(:cards).find(card_data[:holder_id]) elsif holder_type == :supporter - holder = Supporter.select('id, email, nonprofit_id').includes(:cards, :nonprofit).find(card_data[:holder_id]) + holder = Supporter.select("id, email, nonprofit_id").includes(:cards, :nonprofit).find(card_data[:holder_id]) end rescue ActiveRecord::RecordNotFound - raise 'Sorry, you need to provide a nonprofit or supporter' + raise "Sorry, you need to provide a nonprofit or supporter" end begin if holder_type == :supporter && event_id - event = Event.where('id = ?', event_id).first + event = Event.where("id = ?", event_id).first unless event raise ParamValidation::ValidationError.new("#{event_id} is not a valid event", key: :event_id) end @@ -65,16 +65,16 @@ def self.with_stripe(card_data, _stripe_account_id = nil, event_id = nil, curren end rescue AuthenticationError => e raise e - rescue StandardError => e + rescue => e raise "Oops! There was an error: #{e.message}" end stripe_account_hash = {} # stripe_account_id ? {stripe_account: stripe_account_id} : {} begin - if card_data[:stripe_customer_id] - stripe_customer = Stripe::Customer.retrieve(card_data[:stripe_customer_id], stripe_account_hash) + stripe_customer = if card_data[:stripe_customer_id] + Stripe::Customer.retrieve(card_data[:stripe_customer_id], stripe_account_hash) else - stripe_customer = Stripe::Customer.create(customer_data(holder, card_data), stripe_account_hash) + Stripe::Customer.create(customer_data(holder, card_data), stripe_account_hash) end stripe_customer.sources.create(source: card_data[:stripe_card_token]) @@ -107,9 +107,9 @@ def self.with_stripe(card_data, _stripe_account_id = nil, event_id = nil, curren raise "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}" end source_token -end + end def self.customer_data(holder, card_data) - { email: holder['email'], metadata: { cardholders_name: card_data[:cardholders_name], holder_id: card_data[:holder_id], holder_type: card_data[:holder_type] } } + {email: holder["email"], metadata: {cardholders_name: card_data[:cardholders_name], holder_id: card_data[:holder_id], holder_type: card_data[:holder_type]}} end end diff --git a/app/legacy_lib/insert_charge.rb b/app/legacy_lib/insert_charge.rb index 9dc026aca8..74701dcd64 100644 --- a/app/legacy_lib/insert_charge.rb +++ b/app/legacy_lib/insert_charge.rb @@ -10,41 +10,41 @@ module InsertCharge # @raise [Stripe::StripeError] the stripe account couldn't be accessed or created def self.with_stripe(data) ParamValidation.new(data || {}, - amount: { - required: true, - is_integer: true, - min: 0 - }, - nonprofit_id: { - required: true, - is_integer: true - }, - supporter_id: { - required: true, - is_integer: true - }, - card_id: { - required: true, - is_integer: true - }, - statement: { - required: true, - not_blank: true - }) - - np = Nonprofit.where('id = ?', data[:nonprofit_id]).first + amount: { + required: true, + is_integer: true, + min: 0 + }, + nonprofit_id: { + required: true, + is_integer: true + }, + supporter_id: { + required: true, + is_integer: true + }, + card_id: { + required: true, + is_integer: true + }, + statement: { + required: true, + not_blank: true + }) + + np = Nonprofit.where("id = ?", data[:nonprofit_id]).first unless np raise ParamValidation::ValidationError.new("#{data[:nonprofit_id]} is not a valid Nonprofit", key: :nonprofit_id) end - supporter = Supporter.where('id = ?', data[:supporter_id]).first + supporter = Supporter.where("id = ?", data[:supporter_id]).first unless supporter raise ParamValidation::ValidationError.new("#{data[:supporter_id]} is not a valid Supporter", key: :supporter_id) end - card = Card.where('id = ?', data[:card_id]).first + card = Card.where("id = ?", data[:card_id]).first unless card raise ParamValidation::ValidationError.new("#{data[:card_id]} is not a valid card", key: :card_id) @@ -66,17 +66,17 @@ def self.with_stripe(data) # Catch errors thrown by the stripe gem so we can respond with a 422 with an error message rather than 500 begin stripe_customer_id = card.stripe_customer_id - rescue StandardError => e + rescue => e raise e end - nonprofit_currency = Qx.select(:currency).from(:nonprofits).where('id=$id', id: data[:nonprofit_id]).execute.first['currency'] + nonprofit_currency = Qx.select(:currency).from(:nonprofits).where("id=$id", id: data[:nonprofit_id]).execute.first["currency"] stripe_charge_data = { customer: stripe_customer_id, amount: data[:amount], currency: nonprofit_currency, description: data[:statement], - statement_descriptor: data[:statement][0..21].gsub(/[<>"']/, ''), + statement_descriptor: data[:statement][0..21].gsub(/[<>"']/, ""), metadata: data[:metadata] } @@ -91,14 +91,14 @@ def self.with_stripe(data) # If it's a legacy customer, charge to the primary account and transfer with .destination # Otherwise, charge directly to the connected account begin - stripe_cust = Stripe::Customer.retrieve(stripe_customer_id) + Stripe::Customer.retrieve(stripe_customer_id) params = [stripe_charge_data.merge(destination: stripe_account_id), {}] - rescue StandardError - params = [stripe_charge_data, { stripe_account: stripe_account_id }] + rescue + params = [stripe_charge_data, {stripe_account: stripe_account_id}] end else fee = 0 - stripe_charge_data[:source] = card['stripe_card_id'] + stripe_charge_data[:source] = card["stripe_card_id"] params = [stripe_charge_data, {}] end @@ -106,7 +106,7 @@ def self.with_stripe(data) stripe_charge = Stripe::Charge.create(*params) rescue Stripe::CardError => e failure_message = "There was an error with your card: #{e.json_body[:error][:message]}" - rescue Stripe::StripeError => e + rescue Stripe::StripeError failure_message = "We're sorry, but something went wrong. We've been notified about this issue." end @@ -117,44 +117,44 @@ def self.with_stripe(data) charge.stripe_charge_id = stripe_charge&.id charge.failure_message = failure_message - charge.status = stripe_charge&.paid ? 'pending' : 'failed' + charge.status = stripe_charge&.paid ? "pending" : "failed" charge.card = card - charge.donation = Donation.where('id = ?', data[:donation_id]).first + charge.donation = Donation.where("id = ?", data[:donation_id]).first charge.supporter = supporter charge.nonprofit = np charge.save! - result['charge'] = charge + result["charge"] = charge - if stripe_charge && stripe_charge.status != 'failed' + if stripe_charge && stripe_charge.status != "failed" payment = Payment.new payment.gross_amount = data[:amount] payment.fee_total = -fee payment.net_amount = data[:amount] - fee payment.towards = data[:towards] payment.kind = data[:kind] - payment.donation = Donation.where('id = ?', data[:donation_id]).first + payment.donation = Donation.where("id = ?", data[:donation_id]).first payment.nonprofit = np payment.supporter = supporter payment.refund_total = 0 - payment.date = data[:date] || result['charge'].created_at + payment.date = data[:date] || result["charge"].created_at payment.save! - result['payment'] = payment + result["payment"] = payment charge.payment = payment charge.save! - result['charge'] = charge + result["charge"] = charge end result - rescue StandardError => e + rescue => e raise e end def self.with_sepa(data) result = {} entities = RetrieveActiveRecordItems.retrieve_from_keys(data, DirectDebitDetail => :direct_debit_detail_id, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - nonprofit_currency = entities[:nonprofit_id].currency + entities[:nonprofit_id].currency # TODO fee = 0 @@ -165,12 +165,12 @@ def self.with_sepa(data) c.direct_debit_detail = entities[:direct_debit_detail_id] c.amount = data[:amount] c.fee = fee - c.status = 'pending' + c.status = "pending" c.nonprofit = entities[:nonprofit_id] c.supporter = entities[:supporter_id] c.save! - result['charge'] = c + result["charge"] = c p = Payment.new @@ -182,10 +182,10 @@ def self.with_sepa(data) p.nonprofit = entities[:nonprofit_id] p.supporter = entities[:supporter_id] p.refund_total = 0 - p.date = data[:date] || result['charge'].created_at + p.date = data[:date] || result["charge"].created_at p.save! - result['payment'] = p + result["payment"] = p c.payment = p c.save! diff --git a/app/legacy_lib/insert_custom_field_joins.rb b/app/legacy_lib/insert_custom_field_joins.rb index ef49ea5733..ae92c789d5 100644 --- a/app/legacy_lib/insert_custom_field_joins.rb +++ b/app/legacy_lib/insert_custom_field_joins.rb @@ -9,41 +9,41 @@ module InsertCustomFieldJoins # field_data should be an array of arrays liks [['Company', 'Pixar'], # ['Shirt-size', 'Small']] def self.find_or_create(np_id, supporter_ids, field_data) - ParamValidation.new({ np_id: np_id, supporter_ids: supporter_ids, field_data: field_data }, - np_id: { - required: true, - is_integer: true - }, - supporter_ids: { - required: true, - is_array: true, - min_length: 1 - }, - field_data: { - required: true, - is_array: true, - min_length: 1 - }) + ParamValidation.new({np_id: np_id, supporter_ids: supporter_ids, field_data: field_data}, + np_id: { + required: true, + is_integer: true + }, + supporter_ids: { + required: true, + is_array: true, + min_length: 1 + }, + field_data: { + required: true, + is_array: true, + min_length: 1 + }) # make sure the np exists - np = Nonprofit.where('id = ? ', np_id).first + np = Nonprofit.where("id = ? ", np_id).first unless np raise ParamValidation::ValidationError.new("#{np_id} is not a valid non-profit", key: :np_id) end # make sure the supporters_ids exist supporter_ids.each do |id| - unless np.supporters.where('id = ?', id).exists? + unless np.supporters.where("id = ?", id).exists? raise ParamValidation::ValidationError.new("#{id} is not a valid supporter for nonprofit #{np_id}", key: :supporter_ids) end end cfm_id_to_value = field_data.map do |name, value| - cfm = CustomFieldDefinition.where('nonprofit_id = ? and name = ?', np_id, name).first + cfm = CustomFieldDefinition.where("nonprofit_id = ? and name = ?", np_id, name).first Qx.transaction do cfm ||= CustomFieldDefinition.create!(nonprofit: np, name: name) end - { custom_field_definition_id: cfm.id, value: value } + {custom_field_definition_id: cfm.id, value: value} end in_bulk(np_id, supporter_ids, cfm_id_to_value) end @@ -59,31 +59,31 @@ def self.find_or_create(np_id, supporter_ids, field_data) def self.in_bulk(np_id, supporter_ids, field_data) begin ParamValidation.new({ - np_id: np_id, - supporter_ids: supporter_ids, - field_data: field_data - }, - np_id: { required: true, is_integer: true }, - supporter_ids: { required: true, is_array: true }, - field_data: { required: true, is_array: true }) + np_id: np_id, + supporter_ids: supporter_ids, + field_data: field_data + }, + np_id: {required: true, is_integer: true}, + supporter_ids: {required: true, is_array: true}, + field_data: {required: true, is_array: true}) # array_of_hashes: { # selected: {required: true}, tag_definition_id: {required: true, is_integer: true} # } rescue ParamValidation::ValidationError => e - return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } + return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} end begin - return { json: { error: "Nonprofit #{np_id} is not valid" }, status: :unprocessable_entity } unless Nonprofit.exists?(np_id) + return {json: {error: "Nonprofit #{np_id} is not valid"}, status: :unprocessable_entity} unless Nonprofit.exists?(np_id) # verify that the supporters belong to the nonprofit - supporter_ids = Supporter.where('nonprofit_id = ? and id IN (?)', np_id, supporter_ids).pluck(:id) + supporter_ids = Supporter.where("nonprofit_id = ? and id IN (?)", np_id, supporter_ids).pluck(:id) unless supporter_ids.any? - return { json: { inserted_count: 0, removed_count: 0 }, status: :ok } + return {json: {inserted_count: 0, removed_count: 0}, status: :ok} end # filtering the tag_data to this nonprofit - valid_ids = CustomFieldDefinition.where('nonprofit_id = ? and id IN (?)', np_id, field_data.map { |fd| fd[:custom_field_definition_id] }).pluck(:id).to_a + valid_ids = CustomFieldDefinition.where("nonprofit_id = ? and id IN (?)", np_id, field_data.map { |fd| fd[:custom_field_definition_id] }).pluck(:id).to_a filtered_field_data = field_data.select { |i| valid_ids.include? i[:custom_field_definition_id].to_i } # first, delete the items which should be removed @@ -93,28 +93,28 @@ def self.in_bulk(np_id, supporter_ids, field_data) deleted = [] if to_remove.any? deleted = Qx.delete_from(:custom_field_joins) - .where('supporter_id IN ($ids)', ids: supporter_ids) - .and_where('custom_field_definition_id in ($fields)', fields: to_remove.map { |t| t[:custom_field_definition_id] }) - .returning('*') - .execute + .where("supporter_id IN ($ids)", ids: supporter_ids) + .and_where("custom_field_definition_id in ($fields)", fields: to_remove.map { |t| t[:custom_field_definition_id] }) + .returning("*") + .execute end # next add only the selected tag_joins if to_insert.any? - insert_data = supporter_ids.map { |id| to_insert.map { |cfm| { supporter_id: id, custom_field_definition_id: cfm[:custom_field_definition_id], value: cfm[:value] } } }.flatten + insert_data = supporter_ids.map { |id| to_insert.map { |cfm| {supporter_id: id, custom_field_definition_id: cfm[:custom_field_definition_id], value: cfm[:value]} } }.flatten cfj = Qx.insert_into(:custom_field_joins) - .values(insert_data) - .timestamps - .on_conflict - .conflict_columns(:supporter_id, :custom_field_definition_id).upsert(:custom_field_join_supporter_unique_idx) - .returning('*') - .execute + .values(insert_data) + .timestamps + .on_conflict + .conflict_columns(:supporter_id, :custom_field_definition_id).upsert(:custom_field_join_supporter_unique_idx) + .returning("*") + .execute else cfj = [] end rescue ActiveRecord::ActiveRecordError => e - return { json: { error: "A DB error occurred. Please contact support. \n #{e.message}" }, status: :unprocessable_entity } + return {json: {error: "A DB error occurred. Please contact support. \n #{e.message}"}, status: :unprocessable_entity} end # Create an activity for the modified tags for every supporter @@ -125,6 +125,6 @@ def self.in_bulk(np_id, supporter_ids, field_data) # Sync mailchimp lists, if present # Mailchimp.delay.sync_supporters_to_list_from_tag_joins(np_id, supporter_ids, tag_data) - { json: { inserted_count: cfj.count, removed_count: deleted.count }, status: :ok } + {json: {inserted_count: cfj.count, removed_count: deleted.count}, status: :ok} end end diff --git a/app/legacy_lib/insert_direct_debit_detail.rb b/app/legacy_lib/insert_direct_debit_detail.rb index 423f5252f7..c75ed14757 100644 --- a/app/legacy_lib/insert_direct_debit_detail.rb +++ b/app/legacy_lib/insert_direct_debit_detail.rb @@ -17,9 +17,9 @@ def self.execute(params) ) end rescue ActiveRecord::ActiveRecordError => e - return { json: { error: "Oops! There was an error saving your direct debit details, and it did not complete. Please try again in a moment. Error: #{e}" }, status: :unprocessable_entity } + return {json: {error: "Oops! There was an error saving your direct debit details, and it did not complete. Please try again in a moment. Error: #{e}"}, status: :unprocessable_entity} end - { status: :ok, json: direct_debit_detail } + {status: :ok, json: direct_debit_detail} end end diff --git a/app/legacy_lib/insert_disputes.rb b/app/legacy_lib/insert_disputes.rb index 1f8d5a8908..ec9958312c 100644 --- a/app/legacy_lib/insert_disputes.rb +++ b/app/legacy_lib/insert_disputes.rb @@ -9,43 +9,43 @@ module InsertDisputes # A payment row negative gross and net, just like a refund, but with kind "Dispute" def self.create_record(stripe_charge_id, stripe_dispute_id) # Find the existing charge - ch = Qx.select('*').from('charges').where('stripe_charge_id=$id', id: stripe_charge_id).ex.first - raise ArgumentError, 'Charge not found' if ch.nil? + ch = Qx.select("*").from("charges").where("stripe_charge_id=$id", id: stripe_charge_id).ex.first + raise ArgumentError, "Charge not found" if ch.nil? result = {} now = Time.current result[:payment] = Psql.execute( Qexpr.new.insert(:payments, [{ - gross_amount: -ch['amount'], - fee_total: 0, - net_amount: -ch['amount'], - kind: 'Dispute', - refund_total: 0, - nonprofit_id: ch['nonprofit_id'], - supporter_id: ch['supporter_id'], - donation_id: ch['donation_id'], - date: now - }]).returning('*') + gross_amount: -ch["amount"], + fee_total: 0, + net_amount: -ch["amount"], + kind: "Dispute", + refund_total: 0, + nonprofit_id: ch["nonprofit_id"], + supporter_id: ch["supporter_id"], + donation_id: ch["donation_id"], + date: now + }]).returning("*") ).first # Create a dispute record result[:dispute] = Psql.execute( Qexpr.new.insert(:disputes, [{ - gross_amount: ch['amount'], - status: :needs_response, - charge_id: ch['id'], - reason: :unrecognized, - payment_id: result[:payment]['id'], - stripe_dispute_id: stripe_dispute_id - }]).returning('*') + gross_amount: ch["amount"], + status: :needs_response, + charge_id: ch["id"], + reason: :unrecognized, + payment_id: result[:payment]["id"], + stripe_dispute_id: stripe_dispute_id + }]).returning("*") ).first # Prevent refunds from being able to happen on the payment - Qx.update(:payments).set(refund_total: ch['amount']).where(id: ch['payment_id']).ex + Qx.update(:payments).set(refund_total: ch["amount"]).where(id: ch["payment_id"]).ex # Insert an activity record - InsertActivities.for_disputes([result[:payment]['id']]) + InsertActivities.for_disputes([result[:payment]["id"]]) result end diff --git a/app/legacy_lib/insert_donation.rb b/app/legacy_lib/insert_donation.rb index ee298db15a..a4c94b48f5 100644 --- a/app/legacy_lib/insert_donation.rb +++ b/app/legacy_lib/insert_donation.rb @@ -10,9 +10,9 @@ module InsertDonation # recurring_donation if is recurring def self.with_stripe(data, current_user = nil) data = data.to_h.with_indifferent_access - + ParamValidation.new(data, common_param_validations - .merge(token: { required: true, format: UUID::Regex })) + .merge(token: {required: true, format: UUID::Regex})) source_token = QuerySourceToken.get_and_increment_source_token(data[:token], current_user) tokenizable = source_token.tokenizable @@ -20,7 +20,7 @@ def self.with_stripe(data, current_user = nil) entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) validate_entities(entities) @@ -29,30 +29,31 @@ def self.with_stripe(data, current_user = nil) raise ParamValidation::ValidationError.new("Supporter #{entities[:supporter_id].id} does not own card #{tokenizable.id}", key: :token) end - data['card_id'] = tokenizable.id + data["card_id"] = tokenizable.id result = {} data[:date] = Time.now - data = data.except(:old_donation).except('old_donation') + data = data.except(:old_donation).except("old_donation") result = result.merge(insert_charge(data)) - if result['charge']['status'] == 'failed' - raise ChargeError, result['charge']['failure_message'] + if result["charge"]["status"] == "failed" + raise ChargeError, result["charge"]["failure_message"] end # Create the donation record - result['donation'] = insert_donation(data, entities) - trx = entities[:supporter_id].transactions.build(amount: data['amount']) + result["donation"] = insert_donation(data, entities) + trx = entities[:supporter_id].transactions.build(amount: data["amount"]) update_donation_keys(result) - don = trx.donations.build(amount: result['donation'].amount, legacy_donation: result['donation']) + don = trx.donations.build(amount: result["donation"].amount, legacy_donation: result["donation"]) stripe_t = trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: data['amount']), - payments:[ + subtransactable: StripeTransaction.new(amount: data["amount"]), + payments: [ SubtransactionPayment.new( - paymentable: StripeCharge.new(payment: Payment.find(result['payment']['id']))) - ], - created: data['date'] - ); + paymentable: StripeCharge.new(payment: Payment.find(result["payment"]["id"])) + ) + ], + created: data["date"] + ) trx.save! don.save! stripe_t.save! @@ -60,19 +61,19 @@ def self.with_stripe(data, current_user = nil) stripe_t.publish_created don.publish_created trx.publish_created - result['activity'] = InsertActivities.for_one_time_donations([result['payment'].id]) - Houdini.event_publisher.announce(:donation_create, result['donation'], result['donation'].supporter.locale) + result["activity"] = InsertActivities.for_one_time_donations([result["payment"].id]) + Houdini.event_publisher.announce(:donation_create, result["donation"], result["donation"].supporter.locale) result end # Update the charge to have the payment and donation id # Update the payment to have the donation id def self.update_donation_keys(result) - result['charge'].donation = result['donation'] - result['charge'].save! + result["charge"].donation = result["donation"] + result["charge"].save! - result['payment'].donation = result['donation'] - result['payment'].save! + result["payment"].donation = result["donation"] + result["payment"].save! end # Insert a donation made from an offsite payment @@ -80,39 +81,40 @@ def self.update_donation_keys(result) # pass in amount, nonprofit_id, supporter_id, check_number # also pass in offsite_payment sub-hash (can be empty) def self.offsite(data) - ParamValidation.new(data, common_param_validations.merge(offsite_payment: { is_hash: true })) + ParamValidation.new(data, common_param_validations.merge(offsite_payment: {is_hash: true})) entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) validate_entities(entities) data = date_from_data(data) - result = { 'donation' => insert_donation(data.except('offsite_payment'), entities) } - trx = entities[:supporter_id].transactions.build(amount: data['amount'], created: data['date']) - don = trx.donations.build(amount: result['donation'].amount, legacy_donation: result['donation']) + result = {"donation" => insert_donation(data.except("offsite_payment"), entities)} + trx = entities[:supporter_id].transactions.build(amount: data["amount"], created: data["date"]) + don = trx.donations.build(amount: result["donation"].amount, legacy_donation: result["donation"]) - result['payment'] = insert_payment('OffsitePayment', 0, result['donation']['id'], data) - result['offsite_payment'] = Psql.execute( + result["payment"] = insert_payment("OffsitePayment", 0, result["donation"]["id"], data) + result["offsite_payment"] = Psql.execute( Qexpr.new.insert(:offsite_payments, [ - (data['offsite_payment'] || {}).merge( - gross_amount: data['amount'], - nonprofit_id: data['nonprofit_id'], - supporter_id: data['supporter_id'], - donation_id: result['donation']['id'], - payment_id: result['payment']['id'], - date: data['date'] - ) - ]).returning('*') + (data["offsite_payment"] || {}).merge( + gross_amount: data["amount"], + nonprofit_id: data["nonprofit_id"], + supporter_id: data["supporter_id"], + donation_id: result["donation"]["id"], + payment_id: result["payment"]["id"], + date: data["date"] + ) + ]).returning("*") ).first off_t = trx.build_subtransaction( - subtransactable: OfflineTransaction.new(amount: data['amount']), - payments:[ + subtransactable: OfflineTransaction.new(amount: data["amount"]), + payments: [ SubtransactionPayment.new( - paymentable: OfflineTransactionCharge.new(payment: Payment.find(result['payment']['id']))) - ], - created: data['date'] - ); + paymentable: OfflineTransactionCharge.new(payment: Payment.find(result["payment"]["id"])) + ) + ], + created: data["date"] + ) trx.save! don.save! off_t.save! @@ -120,30 +122,30 @@ def self.offsite(data) off_t.publish_created don.publish_created trx.publish_created - result['activity'] = InsertActivities.for_offsite_donations([result['payment']['id']]) - { status: 200, json: result } + result["activity"] = InsertActivities.for_offsite_donations([result["payment"]["id"]]) + {status: 200, json: result} end def self.with_sepa(data) data = data.with_indifferent_access ParamValidation.new(data, common_param_validations - .merge(direct_debit_detail_id: { required: true, is_reference: true })) + .merge(direct_debit_detail_id: {required: true, is_reference: true})) entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) result = {} data[:date] = Time.now result = result.merge(insert_charge(data)) - result['donation'] = insert_donation(data, entities) + result["donation"] = insert_donation(data, entities) update_donation_keys(result) - Houdini.event_publisher.announce(:donation_create, result['donation'], result['donation'].supporter.locale) + Houdini.event_publisher.announce(:donation_create, result["donation"], result["donation"].supporter.locale) # do this for making test consistent - result['activity'] = {} + result["activity"] = {} result end @@ -152,37 +154,37 @@ def self.with_sepa(data) def self.get_nonprofit_data(nonprofit_id) Nonprofit.find(nonprofit_id) .attributes - .slice('statement', 'name') + .slice("statement", "name") end def self.insert_charge(data) payment_provider = payment_provider(data) - nonprofit_data = get_nonprofit_data(data['nonprofit_id']) - kind = data['recurring_donation'] ? 'RecurringDonation' : 'Donation' + nonprofit_data = get_nonprofit_data(data["nonprofit_id"]) + kind = data["recurring_donation"] ? "RecurringDonation" : "Donation" if payment_provider == :credit_card - return InsertCharge.with_stripe( - donation_id: data['donation_id'], + InsertCharge.with_stripe( + donation_id: data["donation_id"], kind: kind, - towards: data['designation'], - metadata: { kind: kind, nonprofit_id: data['nonprofit_id'] }, - statement: "Donation #{nonprofit_data['statement'] || nonprofit_data['name']}", - amount: data['amount'], - nonprofit_id: data['nonprofit_id'], - supporter_id: data['supporter_id'], - card_id: data['card_id'], - old_donation: data['old_donation'] ? true : false + towards: data["designation"], + metadata: {kind: kind, nonprofit_id: data["nonprofit_id"]}, + statement: "Donation #{nonprofit_data["statement"] || nonprofit_data["name"]}", + amount: data["amount"], + nonprofit_id: data["nonprofit_id"], + supporter_id: data["supporter_id"], + card_id: data["card_id"], + old_donation: data["old_donation"] ? true : false ) elsif payment_provider == :sepa - return InsertCharge.with_sepa( - donation_id: data['donation_id'], + InsertCharge.with_sepa( + donation_id: data["donation_id"], kind: kind, - towards: data['designation'], - metadata: { kind: kind, nonprofit_id: data['nonprofit_id'] }, - statement: "Donation #{nonprofit_data['statement'] || nonprofit_data['name']}", - amount: data['amount'], - nonprofit_id: data['nonprofit_id'], - supporter_id: data['supporter_id'], - direct_debit_detail_id: data['direct_debit_detail_id'] + towards: data["designation"], + metadata: {kind: kind, nonprofit_id: data["nonprofit_id"]}, + statement: "Donation #{nonprofit_data["statement"] || nonprofit_data["name"]}", + amount: data["amount"], + nonprofit_id: data["nonprofit_id"], + supporter_id: data["supporter_id"], + direct_debit_detail_id: data["direct_debit_detail_id"] ) end end @@ -191,31 +193,31 @@ def self.insert_charge(data) def self.insert_payment(kind, fee_total, donation_id, data) Psql.execute( Qexpr.new.insert(:payments, [{ - donation_id: donation_id, - gross_amount: data['amount'], - nonprofit_id: data['nonprofit_id'], - supporter_id: data['supporter_id'], - refund_total: 0, - date: data['date'], - towards: data['designation'], - kind: kind, - fee_total: fee_total, - net_amount: data['amount'] - fee_total - }]).returning('*') + donation_id: donation_id, + gross_amount: data["amount"], + nonprofit_id: data["nonprofit_id"], + supporter_id: data["supporter_id"], + refund_total: 0, + date: data["date"], + towards: data["designation"], + kind: kind, + fee_total: fee_total, + net_amount: data["amount"] - fee_total + }]).returning("*") ).first end # Insert a donation row def self.insert_donation(data, entities) d = Donation.new - d.date = data['date'] - d.anonymous = data['anonymous'] - d.designation = data['designation'] - d.dedication = data['dedication'] - d.comment = data['comment'] - d.amount = data['amount'] - d.card = Card.find(data['card_id']) if data['card_id'] - d.direct_debit_detail = DirectDebitDetail.find(data['direct_debit_detail_id']) if data['direct_debit_detail_id'] + d.date = data["date"] + d.anonymous = data["anonymous"] + d.designation = data["designation"] + d.dedication = data["dedication"] + d.comment = data["comment"] + d.amount = data["amount"] + d.card = Card.find(data["card_id"]) if data["card_id"] + d.direct_debit_detail = DirectDebitDetail.find(data["direct_debit_detail_id"]) if data["direct_debit_detail_id"] d.nonprofit = entities[:nonprofit_id] d.supporter = entities[:supporter_id] d.profile = entities[:profile_id] || nil @@ -228,30 +230,30 @@ def self.insert_donation(data, entities) # Return either the parsed DateTime from a date in data, or right now def self.date_from_data(data) - data.merge('date' => data['date'].blank? ? Time.current : Chronic.parse(data['date'])) + data.merge("date" => data["date"].blank? ? Time.current : Chronic.parse(data["date"])) end def self.payment_provider(data) - if data[:card_id] || data['card_id'] + if data[:card_id] || data["card_id"] :credit_card - elsif data[:direct_debit_detail_id] || data['direct_debit_detail_id'] + elsif data[:direct_debit_detail_id] || data["direct_debit_detail_id"] :sepa end end def self.parse_date(date) date.blank? ? Time.current : Chronic.parse(date) - end + end def self.common_param_validations { - amount: { required: true, is_integer: true }, - nonprofit_id: { required: true, is_reference: true }, - supporter_id: { required: true, is_reference: true }, - designation: { is_a: String }, - dedication: { is_a: Hash }, - campaign_id: { is_reference: true }, - event_id: { is_reference: true } + amount: {required: true, is_integer: true}, + nonprofit_id: {required: true, is_reference: true}, + supporter_id: {required: true, is_reference: true}, + designation: {is_a: String}, + dedication: {is_a: Hash}, + campaign_id: {is_reference: true}, + event_id: {is_reference: true} } end diff --git a/app/legacy_lib/insert_duplicate.rb b/app/legacy_lib/insert_duplicate.rb index 85f1b904ce..1575a25f75 100644 --- a/app/legacy_lib/insert_duplicate.rb +++ b/app/legacy_lib/insert_duplicate.rb @@ -4,15 +4,15 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module InsertDuplicate def self.campaign(campaign_id, profile_id) - ParamValidation.new({ campaign_id: campaign_id, profile_id: profile_id }, - campaign_id: { required: true, is_integer: true }, - profile_id: { required: true, is_integer: true }) - campaign = Campaign.where('id = ?', campaign_id).first + ParamValidation.new({campaign_id: campaign_id, profile_id: profile_id}, + campaign_id: {required: true, is_integer: true}, + profile_id: {required: true, is_integer: true}) + campaign = Campaign.where("id = ?", campaign_id).first unless campaign raise ParamValidation::ValidationError.new("#{campaign_id} is not a valid campaign", key: :campaign_id) end - profile = Profile.where('id = ?', profile_id).first + profile = Profile.where("id = ?", profile_id).first unless profile raise ParamValidation::ValidationError.new("#{profile_id} is not a valid profile", key: :profile_id) end @@ -40,15 +40,15 @@ def self.campaign(campaign_id, profile_id) end def self.event(event_id, profile_id) - ParamValidation.new({ event_id: event_id, profile_id: profile_id }, - event_id: { required: true, is_integer: true }, - profile_id: { required: true, is_integer: true }) - event = Event.where('id = ?', event_id).first + ParamValidation.new({event_id: event_id, profile_id: profile_id}, + event_id: {required: true, is_integer: true}, + profile_id: {required: true, is_integer: true}) + event = Event.where("id = ?", event_id).first unless event raise ParamValidation::ValidationError.new("#{event_id} is not a valid event", key: :event_id) end - profile = Profile.where('id = ?', profile_id).first + profile = Profile.where("id = ?", profile_id).first unless profile raise ParamValidation::ValidationError.new("#{profile_id} is not a valid profile", key: :profile_id) end @@ -76,7 +76,7 @@ def self.event(event_id, profile_id) dupe.main_image.attach(event.main_image.blob) if event.main_image.attached? - dupe.background_image.attach( event.background_image.blob) if event.background_image.attached? + dupe.background_image.attach(event.background_image.blob) if event.background_image.attached? InsertDuplicate.ticket_levels(event_id, dupe.id) InsertDuplicate.event_discounts(event_id, dupe.id) @@ -87,57 +87,57 @@ def self.event(event_id, profile_id) # selects all gift options associated with old campaign # and inserts them and creates associations with a new campaign def self.campaign_gift_options(old_campaign_id, new_campaign_id) - cgos = Qx.select('*') - .from('campaign_gift_options') - .where(campaign_id: old_campaign_id) - .execute - .map { |c| c.except('id', 'created_at', 'updated_at', 'campaign_id') } + cgos = Qx.select("*") + .from("campaign_gift_options") + .where(campaign_id: old_campaign_id) + .execute + .map { |c| c.except("id", "created_at", "updated_at", "campaign_id") } if cgos.any? - return Qx.insert_into('campaign_gift_options') - .values(cgos) - .common_values(campaign_id: new_campaign_id) - .ts - .returning('*') - .execute + Qx.insert_into("campaign_gift_options") + .values(cgos) + .common_values(campaign_id: new_campaign_id) + .ts + .returning("*") + .execute end end # selects all ticket levels associated with old event # and inserts them and creates associations with a new event def self.ticket_levels(old_event_id, new_event_id) - tls = Qx.select('*') - .from('ticket_levels') - .where(event_id: old_event_id) - .execute - .map { |t| t.except('id', 'created_at', 'updated_at', 'event_id') } + tls = Qx.select("*") + .from("ticket_levels") + .where(event_id: old_event_id) + .execute + .map { |t| t.except("id", "created_at", "updated_at", "event_id") } if tls.any? - return Qx.insert_into('ticket_levels') - .values(tls) - .common_values(event_id: new_event_id) - .ts - .returning('*') - .execute + Qx.insert_into("ticket_levels") + .values(tls) + .common_values(event_id: new_event_id) + .ts + .returning("*") + .execute end end # selects all discounts associated with old event # and inserts them and creates associations with a new event def self.event_discounts(old_event_id, new_event_id) - eds = Qx.select('*') - .from('event_discounts') - .where(event_id: old_event_id) - .execute - .map { |t| t.except('id', 'created_at', 'updated_at', 'event_id') } + eds = Qx.select("*") + .from("event_discounts") + .where(event_id: old_event_id) + .execute + .map { |t| t.except("id", "created_at", "updated_at", "event_id") } if eds.any? - return Qx.insert_into('event_discounts') - .values(eds) - .common_values(event_id: new_event_id) - .ts - .returning('*') - .execute + Qx.insert_into("event_discounts") + .values(eds) + .common_values(event_id: new_event_id) + .ts + .returning("*") + .execute end end end diff --git a/app/legacy_lib/insert_email_lists.rb b/app/legacy_lib/insert_email_lists.rb index c029a6b634..4331270105 100644 --- a/app/legacy_lib/insert_email_lists.rb +++ b/app/legacy_lib/insert_email_lists.rb @@ -6,22 +6,22 @@ module InsertEmailLists def self.for_mailchimp(npo_id, tag_definition_ids) # Partial SQL expression for deleting deselected tags - delete_expr = Qx.delete_from(:email_lists).where(nonprofit_id: npo_id).returning('mailchimp_list_id') + delete_expr = Qx.delete_from(:email_lists).where(nonprofit_id: npo_id).returning("mailchimp_list_id") - if tag_definition_ids.empty? # no tags were selected; remove all email lists - deleted = delete_expr.execute + deleted = if tag_definition_ids.empty? # no tags were selected; remove all email lists + delete_expr.execute else # Remove all email lists that exist in the db that are not included in tag_definition_ids - deleted = delete_expr.where('tag_definition_id NOT IN($ids)', ids: tag_definition_ids).execute + delete_expr.where("tag_definition_id NOT IN($ids)", ids: tag_definition_ids).execute end - mailchimp_lists_to_delete = deleted.map { |h| h['mailchimp_list_id'] } + mailchimp_lists_to_delete = deleted.map { |h| h["mailchimp_list_id"] } result = Mailchimp.delete_mailchimp_lists(npo_id, mailchimp_lists_to_delete) - return { deleted: deleted, deleted_result: result } if tag_definition_ids.empty? + return {deleted: deleted, deleted_result: result} if tag_definition_ids.empty? - existing = Qx.select('tag_definition_id').from(:email_lists) - .where(nonprofit_id: npo_id) - .and_where('tag_definition_id IN ($ids)', ids: tag_definition_ids) - .execute + existing = Qx.select("tag_definition_id").from(:email_lists) + .where(nonprofit_id: npo_id) + .and_where("tag_definition_id IN ($ids)", ids: tag_definition_ids) + .execute tag_definition_ids -= existing lists = Mailchimp.create_mailchimp_lists(npo_id, tag_definition_ids) @@ -30,14 +30,14 @@ def self.for_mailchimp(npo_id, tag_definition_ids) end inserted_lists = Qx.insert_into(:email_lists) - .values(lists.map { |ls| { list_name: ls[:name], mailchimp_list_id: ls[:id], tag_definition_id: ls[:tag_definition_id] } }) - .common_values(nonprofit_id: npo_id) - .ts - .returning('*') - .execute + .values(lists.map { |ls| {list_name: ls[:name], mailchimp_list_id: ls[:id], tag_definition_id: ls[:tag_definition_id]} }) + .common_values(nonprofit_id: npo_id) + .ts + .returning("*") + .execute EmailListCreateJob.perform_later(npo_id) - { deleted: deleted, deleted_result: result, inserted_lists: inserted_lists, inserted_result: lists } + {deleted: deleted, deleted_result: result, inserted_lists: inserted_lists, inserted_result: lists} end end diff --git a/app/legacy_lib/insert_nonprofit_keys.rb b/app/legacy_lib/insert_nonprofit_keys.rb index 838a637a7b..2faebee3db 100644 --- a/app/legacy_lib/insert_nonprofit_keys.rb +++ b/app/legacy_lib/insert_nonprofit_keys.rb @@ -2,34 +2,34 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'httparty' +require "httparty" module InsertNonprofitKeys include HTTParty def self.insert_mailchimp_access_token(npo_id, code) - form_data = "grant_type=authorization_code&client_id=#{URI.escape ENV['MAILCHIMP_OAUTH_CLIENT_ID']}&client_secret=#{ENV['MAILCHIMP_OAUTH_CLIENT_SECRET']}&redirect_uri=#{ENV['MAILCHIMP_REDIRECT_URL']}%2Fmailchimp-landing&code=#{URI.escape code}" + form_data = "grant_type=authorization_code&client_id=#{URI.escape ENV["MAILCHIMP_OAUTH_CLIENT_ID"]}&client_secret=#{ENV["MAILCHIMP_OAUTH_CLIENT_SECRET"]}&redirect_uri=#{ENV["MAILCHIMP_REDIRECT_URL"]}%2Fmailchimp-landing&code=#{URI.escape code}" - response = post('https://login.mailchimp.com/oauth2/token', body: form_data) - raise Exception, response['error'] if response['error'] + response = post("https://login.mailchimp.com/oauth2/token", body: form_data) + raise Exception, response["error"] if response["error"] - response['access_token'] = Cypher.encrypt(response['access_token']) + response["access_token"] = Cypher.encrypt(response["access_token"]) - key_row_id = Qx.select('*') - .from(:nonprofit_keys).where(nonprofit_id: npo_id) - .execute.map { |h| h['id'] }.first + key_row_id = Qx.select("*") + .from(:nonprofit_keys).where(nonprofit_id: npo_id) + .execute.map { |h| h["id"] }.first if key_row_id.nil? Qx.insert_into(:nonprofit_keys) - .values(nonprofit_id: npo_id, mailchimp_token: response['access_token'].to_json) + .values(nonprofit_id: npo_id, mailchimp_token: response["access_token"].to_json) .ts.execute else Qx.update(:nonprofit_keys) - .set(mailchimp_token: response['access_token']) - .ts.where('id' => key_row_id) + .set(mailchimp_token: response["access_token"]) + .ts.where("id" => key_row_id) .execute end - response['access_token'] + response["access_token"] end end diff --git a/app/legacy_lib/insert_payout.rb b/app/legacy_lib/insert_payout.rb index c758e36b74..6679434dcc 100644 --- a/app/legacy_lib/insert_payout.rb +++ b/app/legacy_lib/insert_payout.rb @@ -14,24 +14,24 @@ module InsertPayout def self.with_stripe(np_id, data, options = {}) bigger_data = (data || {}).merge(np_id: np_id) ParamValidation.new(bigger_data, - np_id: { required: true, is_integer: true }, - stripe_account_id: { not_blank: true, required: true }, - email: { not_blank: true, required: true }, - user_ip: { not_blank: true, required: true }, - bank_name: { not_blank: true, required: true }) + np_id: {required: true, is_integer: true}, + stripe_account_id: {not_blank: true, required: true}, + email: {not_blank: true, required: true}, + user_ip: {not_blank: true, required: true}, + bank_name: {not_blank: true, required: true}) options ||= {} entities = RetrieveActiveRecordItems.retrieve_from_keys(bigger_data, Nonprofit => :np_id) payment_ids = QueryPayments.ids_for_payout(np_id, options) if payment_ids.count < 1 - raise ArgumentError, 'No payments are available for disbursal on this account.' + raise ArgumentError, "No payments are available for disbursal on this account." end totals = QueryPayments.get_payout_totals(payment_ids) nonprofit_currency = entities[:np_id].currency - now = Time.current + Time.current payout = nil begin - stripe_transfer = StripeUtils.create_transfer(totals['net_amount'], data[:stripe_account_id], nonprofit_currency) + stripe_transfer = StripeUtils.create_transfer(totals["net_amount"], data[:stripe_account_id], nonprofit_currency) Psql.transaction do # Create the Transfer on Stripe @@ -46,45 +46,44 @@ def self.with_stripe(np_id, data, options = {}) # Create the payout record (whether it succeeded on Stripe or not) payout = Psql.execute( Qexpr.new.insert(:payouts, [{ - net_amount: totals['net_amount'], - nonprofit_id: np_id, - failure_message: stripe_transfer['failure_message'], - status: stripe_transfer.status, - fee_total: totals['fee_total'], - gross_amount: totals['gross_amount'], - email: data[:email], - count: totals['count'], - stripe_transfer_id: stripe_transfer.id, - user_ip: data[:user_ip], - ach_fee: 0, - bank_name: data[:bank_name] - }]) - .returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name') + net_amount: totals["net_amount"], + nonprofit_id: np_id, + failure_message: stripe_transfer["failure_message"], + status: stripe_transfer.status, + fee_total: totals["fee_total"], + gross_amount: totals["gross_amount"], + email: data[:email], + count: totals["count"], + stripe_transfer_id: stripe_transfer.id, + user_ip: data[:user_ip], + ach_fee: 0, + bank_name: data[:bank_name] + }]) + .returning("id", "net_amount", "nonprofit_id", "created_at", "updated_at", "status", "fee_total", "gross_amount", "email", "count", "stripe_transfer_id", "user_ip", "ach_fee", "bank_name") ).first # Create PaymentPayout records linking all the payments to the payout - pps = Psql.execute(Qexpr.new.insert('payment_payouts', payment_ids.map { |id| { payment_id: id.to_i } }, common_data: { payout_id: payout['id'].to_i })) - PayoutPendingJob.perform_later(Payout.find(payout['id'].to_i)) + Psql.execute(Qexpr.new.insert("payment_payouts", payment_ids.map { |id| {payment_id: id.to_i} }, common_data: {payout_id: payout["id"].to_i})) + PayoutPendingJob.perform_later(Payout.find(payout["id"].to_i)) end payout rescue Stripe::StripeError => e - payout = Psql.execute( + Psql.execute( Qexpr.new.insert(:payouts, [{ - net_amount: totals['net_amount'], - nonprofit_id: np_id, - failure_message: e.message, - status: 'failed', - fee_total: totals['fee_total'], - gross_amount: totals['gross_amount'], - email: data[:email], - count: totals['count'], - stripe_transfer_id: nil, - user_ip: data[:user_ip], - ach_fee: 0, - bank_name: data[:bank_name] - }]) - .returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name') + net_amount: totals["net_amount"], + nonprofit_id: np_id, + failure_message: e.message, + status: "failed", + fee_total: totals["fee_total"], + gross_amount: totals["gross_amount"], + email: data[:email], + count: totals["count"], + stripe_transfer_id: nil, + user_ip: data[:user_ip], + ach_fee: 0, + bank_name: data[:bank_name] + }]) + .returning("id", "net_amount", "nonprofit_id", "created_at", "updated_at", "status", "fee_total", "gross_amount", "email", "count", "stripe_transfer_id", "user_ip", "ach_fee", "bank_name") ).first - payout end end end diff --git a/app/legacy_lib/insert_recurring_donation.rb b/app/legacy_lib/insert_recurring_donation.rb index de36968c85..11e22706f2 100644 --- a/app/legacy_lib/insert_recurring_donation.rb +++ b/app/legacy_lib/insert_recurring_donation.rb @@ -9,23 +9,23 @@ def self.with_stripe(data) data = data.with_indifferent_access ParamValidation.new(data, InsertDonation.common_param_validations - .merge(token: { required: true, format: UUID::Regex })) + .merge(token: {required: true, format: UUID::Regex})) if data[:recurring_donation].nil? data[:recurring_donation] = {} else ParamValidation.new(data[:recurring_donation], - interval: { is_integer: true }, - start_date: { can_be_date: true }, - time_unit: { included_in: %w[month day week year] }, - paydate: { is_integer: true }) + interval: {is_integer: true}, + start_date: {can_be_date: true}, + time_unit: {included_in: %w[month day week year]}, + paydate: {is_integer: true}) if data[:recurring_donation][:paydate] data[:recurring_donation][:paydate] = data[:recurring_donation][:paydate].to_i end ParamValidation.new(data[:recurring_donation], - paydate: { min: 1, max: 28 }) + paydate: {min: 1, max: 28}) end @@ -35,7 +35,7 @@ def self.with_stripe(data) entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) InsertDonation.validate_entities(entities) @@ -44,43 +44,41 @@ def self.with_stripe(data) raise ParamValidation::ValidationError.new("Supporter #{entities[:supporter_id].id} does not own card #{tokenizable.id}", key: :token) end - data['card_id'] = tokenizable.id + data["card_id"] = tokenizable.id result = {} data[:date] = Time.now data = data.merge(payment_provider: payment_provider(data)) - data = data.except(:old_donation).except('old_donation') + data = data.except(:old_donation).except("old_donation") # if start date is today, make initial charge first test_start_date = get_test_start_date(data) if test_start_date.nil? || Time.current >= test_start_date result = result.merge(InsertDonation.insert_charge(data)) - if result['charge']['status'] == 'failed' - raise ChargeError, result['charge']['failure_message'] + if result["charge"]["status"] == "failed" + raise ChargeError, result["charge"]["failure_message"] end end - - - # Create the donation record - result['donation'] = InsertDonation.insert_donation(data, entities) - entities[:donation_id] = result['donation'] + result["donation"] = InsertDonation.insert_donation(data, entities) + entities[:donation_id] = result["donation"] # Create the recurring_donation record - result['recurring_donation'] = insert_recurring_donation(data, entities) + result["recurring_donation"] = insert_recurring_donation(data, entities) # Update charge foreign keys - if result['payment'] + if result["payment"] InsertDonation.update_donation_keys(result) - trx = entities[:supporter_id].transactions.build(amount: data['amount'], created: data['date']) - don = trx.donations.build(amount: result['donation'].amount, legacy_donation: result['donation']) + trx = entities[:supporter_id].transactions.build(amount: data["amount"], created: data["date"]) + don = trx.donations.build(amount: result["donation"].amount, legacy_donation: result["donation"]) stripe_t = trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: data['amount']), - payments:[ + subtransactable: StripeTransaction.new(amount: data["amount"]), + payments: [ SubtransactionPayment.new( - paymentable: StripeCharge.new(payment: Payment.find(result['payment']['id']))) - ], - created: data['date'] - ); + paymentable: StripeCharge.new(payment: Payment.find(result["payment"]["id"])) + ) + ], + created: data["date"] + ) trx.save! don.save! stripe_t.save! @@ -90,13 +88,13 @@ def self.with_stripe(data) trx.publish_created # Create the activity record - result['activity'] = InsertActivities.for_recurring_donations([result['payment'].id]) + result["activity"] = InsertActivities.for_recurring_donations([result["payment"].id]) end - recurrence = result['recurring_donation'].create_recurrence!(supporter: result['recurring_donation'].supporter, start_date:result['recurring_donation'].start_date, amount: result['recurring_donation'].amount ) + recurrence = result["recurring_donation"].create_recurrence!(supporter: result["recurring_donation"].supporter, start_date: result["recurring_donation"].start_date, amount: result["recurring_donation"].amount) recurrence.publish_created # Send receipts - Houdini.event_publisher.announce(:recurring_donation_create, result['donation'], entities[:supporter_id].locale) + Houdini.event_publisher.announce(:recurring_donation_create, result["donation"], entities[:supporter_id].locale) result end @@ -109,34 +107,34 @@ def self.with_sepa(data) result = result.merge(InsertDonation.insert_charge(data)) end - result['donation'] = Psql.execute(Qexpr.new.insert(:donations, [ - data.except(:recurring_donation) - ]).returning('*')).first + result["donation"] = Psql.execute(Qexpr.new.insert(:donations, [ + data.except(:recurring_donation) + ]).returning("*")).first - result['recurring_donation'] = Psql.execute(Qexpr.new.insert(:recurring_donations, [ - data[:recurring_donation].merge(donation_id: result['donation']['id']) - ]).returning('*')).first + result["recurring_donation"] = Psql.execute(Qexpr.new.insert(:recurring_donations, [ + data[:recurring_donation].merge(donation_id: result["donation"]["id"]) + ]).returning("*")).first - InsertDonation.update_donation_keys(result) if result['payment'] + InsertDonation.update_donation_keys(result) if result["payment"] - Houdini.event_publisher.announce(:recurring_donation_create, result['donation'], entities[:supporter_id].locale) + Houdini.event_publisher.announce(:recurring_donation_create, result["donation"], entities[:supporter_id].locale) - { status: 200, json: result } - end + {status: 200, json: result} + end # the data model here is brutal. This needs to get cleaned up. def self.convert_donation_to_recurring_donation(donation_id) - ParamValidation.new({ donation_id: donation_id }, donation_id: { required: true, is_integer: true }) - don = Donation.where('id = ? ', donation_id).first + ParamValidation.new({donation_id: donation_id}, donation_id: {required: true, is_integer: true}) + don = Donation.where("id = ? ", donation_id).first unless don raise ParamValidation::ValidationError.new("#{donation_id} is not a valid donation", key: :donation_id, val: donation_id) end - rd = insert_recurring_donation({ amount: don.amount, email: don.supporter.email, anonymous: don.anonymous, origin_url: don.origin_url, recurring_donation: { start_date: don.created_at, paydate: convert_date_to_valid_paydate(don.created_at) }, date: don.created_at }, supporter_id: don.supporter, nonprofit_id: don.nonprofit, donation_id: don) + rd = insert_recurring_donation({amount: don.amount, email: don.supporter.email, anonymous: don.anonymous, origin_url: don.origin_url, recurring_donation: {start_date: don.created_at, paydate: convert_date_to_valid_paydate(don.created_at)}, date: don.created_at}, supporter_id: don.supporter, nonprofit_id: don.nonprofit, donation_id: don) don.recurring_donation = rd don.recurring = true - don.payment.kind = 'RecurringDonation' + don.payment.kind = "RecurringDonation" don.payment.save! rd.save! don.save! @@ -154,25 +152,25 @@ def self.insert_recurring_donation(data, entities) rd.edit_token = SecureRandom.uuid rd.n_failures = 0 rd.email = entities[:supporter_id].email - rd.interval = data[:recurring_donation][:interval].blank? ? 1 : data[:recurring_donation][:interval] - rd.time_unit = data[:recurring_donation][:time_unit].blank? ? 'month' : data[:recurring_donation][:time_unit] + rd.interval = (data[:recurring_donation][:interval].presence || 1) + rd.time_unit = (data[:recurring_donation][:time_unit].presence || "month") rd.start_date = if data[:recurring_donation][:start_date].blank? - Time.current.beginning_of_day - elsif data[:recurring_donation][:start_date].is_a? Time - data[:recurring_donation][:start_date] - else - Chronic.parse(data[:recurring_donation][:start_date]) - end - - if rd.time_unit == 'month' && rd.interval == 1 && data[:recurring_donation][:paydate].nil? - rd.paydate = convert_date_to_valid_paydate(rd.start_date) + Time.current.beginning_of_day + elsif data[:recurring_donation][:start_date].is_a? Time + data[:recurring_donation][:start_date] else - rd.paydate = data[:recurring_donation][:paydate] + Chronic.parse(data[:recurring_donation][:start_date]) + end + + rd.paydate = if rd.time_unit == "month" && rd.interval == 1 && data[:recurring_donation][:paydate].nil? + convert_date_to_valid_paydate(rd.start_date) + else + data[:recurring_donation][:paydate] end rd.save! rd - end + end def self.get_test_start_date(data) unless data[:recurring_donation] && data[:recurring_donation][:start_date] @@ -180,7 +178,7 @@ def self.get_test_start_date(data) end Chronic.parse(data[:recurring_donation][:start_date]) - end + end def self.payment_provider(data) if data[:card_id] @@ -192,6 +190,6 @@ def self.payment_provider(data) def self.convert_date_to_valid_paydate(date) day = date.day - day > 28 ? 28 : day + (day > 28) ? 28 : day end end diff --git a/app/legacy_lib/insert_refunds.rb b/app/legacy_lib/insert_refunds.rb index 1912d6031e..d0ad77970a 100644 --- a/app/legacy_lib/insert_refunds.rb +++ b/app/legacy_lib/insert_refunds.rb @@ -8,60 +8,60 @@ module InsertRefunds # params: amount, donation obj def self.with_stripe(charge, h) ParamValidation.new(charge, - payment_id: { required: true, is_integer: true }, - stripe_charge_id: { required: true, format: /^(test_)?ch_.*$/ }, - amount: { required: true, is_integer: true, min: 1 }, - id: { required: true, is_integer: true }, - nonprofit_id: { required: true, is_integer: true }, - supporter_id: { required: true, is_integer: true }) - ParamValidation.new(h, amount: { required: true, is_integer: true, min: 1 }) - - original_payment = Qx.select('*').from('payments').where(id: charge['payment_id']).execute.first - raise ActiveRecord::RecordNotFound, "Cannot find original payment for refund on charge #{charge['id']}" if original_payment.nil? - - if original_payment['refund_total'].to_i + h['amount'].to_i > original_payment['gross_amount'].to_i - raise "Refund amount must be less than the net amount of the payment (for charge #{charge['id']})" + payment_id: {required: true, is_integer: true}, + stripe_charge_id: {required: true, format: /^(test_)?ch_.*$/}, + amount: {required: true, is_integer: true, min: 1}, + id: {required: true, is_integer: true}, + nonprofit_id: {required: true, is_integer: true}, + supporter_id: {required: true, is_integer: true}) + ParamValidation.new(h, amount: {required: true, is_integer: true, min: 1}) + + original_payment = Qx.select("*").from("payments").where(id: charge["payment_id"]).execute.first + raise ActiveRecord::RecordNotFound, "Cannot find original payment for refund on charge #{charge["id"]}" if original_payment.nil? + + if original_payment["refund_total"].to_i + h["amount"].to_i > original_payment["gross_amount"].to_i + raise "Refund amount must be less than the net amount of the payment (for charge #{charge["id"]})" end - stripe_charge = Stripe::Charge.retrieve(charge['stripe_charge_id']) + stripe_charge = Stripe::Charge.retrieve(charge["stripe_charge_id"]) - refund_post_data = { 'amount' => h['amount'], 'refund_application_fee' => true, 'reverse_transfer' => true } - refund_post_data['reason'] = h['reason'] unless h['reason'].blank? # Stripe will error on blank reason field + refund_post_data = {"amount" => h["amount"], "refund_application_fee" => true, "reverse_transfer" => true} + refund_post_data["reason"] = h["reason"] unless h["reason"].blank? # Stripe will error on blank reason field stripe_refund = stripe_charge.refunds.create(refund_post_data) - h['stripe_refund_id'] = stripe_refund.id + h["stripe_refund_id"] = stripe_refund.id - refund_row = Qx.insert_into(:refunds).values(h.merge(charge_id: charge['id'])).timestamps.returning('*').execute.first + refund_row = Qx.insert_into(:refunds).values(h.merge(charge_id: charge["id"])).timestamps.returning("*").execute.first - gross = -(h['amount']) - platform_fee = BillingPlans.get_percentage_fee(charge['nonprofit_id']) - fees = (h['amount'] * - original_payment['fee_total'] / original_payment['gross_amount']).ceil + gross = -h["amount"] + BillingPlans.get_percentage_fee(charge["nonprofit_id"]) + fees = (h["amount"] * - original_payment["fee_total"] / original_payment["gross_amount"]).ceil net = gross + fees # Create a corresponding negative payment record payment_row = Qx.insert_into(:payments).values( gross_amount: gross, fee_total: fees, net_amount: net, - kind: 'Refund', - towards: original_payment['towards'], - date: refund_row['created_at'], - nonprofit_id: charge['nonprofit_id'], - supporter_id: charge['supporter_id'] + kind: "Refund", + towards: original_payment["towards"], + date: refund_row["created_at"], + nonprofit_id: charge["nonprofit_id"], + supporter_id: charge["supporter_id"] ) - .timestamps - .returning('*') - .execute.first + .timestamps + .returning("*") + .execute.first - InsertActivities.for_refunds([payment_row['id']]) + InsertActivities.for_refunds([payment_row["id"]]) # Update the refund to have the above payment_id - refund_row = Qx.update(:refunds).set(payment_id: payment_row['id']).ts.where(id: refund_row['id']).returning('*').execute.first + refund_row = Qx.update(:refunds).set(payment_id: payment_row["id"]).ts.where(id: refund_row["id"]).returning("*").execute.first # Update original payment to increment its refund_total for any future refund attempts - Qx.update(:payments).set("refund_total=refund_total + #{h['amount'].to_i}").ts.where(id: original_payment['id']).execute + Qx.update(:payments).set("refund_total=refund_total + #{h["amount"].to_i}").ts.where(id: original_payment["id"]).execute - refund = Refund.find(refund_row['id']) - refund_payment = Payment.find(payment_row['id']) + Refund.find(refund_row["id"]) + refund_payment = Payment.find(payment_row["id"]) - stripe_transaction_charge = StripeCharge.find_by(payment: original_payment['id']) + stripe_transaction_charge = StripeCharge.find_by(payment: original_payment["id"]) stripe_transaction_refund = StripeRefund.new(payment: refund_payment) transaction_id = stripe_transaction_charge.subtransaction_payment.subtransaction.transaction_id transaction = Transaction.find(transaction_id) @@ -78,7 +78,7 @@ def self.with_stripe(charge, h) refund_subtransaction_payment.publish_created # Send the refund receipts in a delayed job - Houdini.event_publisher.announce(:create_refund, Refund.find(refund_row['id'])) - { 'payment' => payment_row, 'refund' => refund_row } + Houdini.event_publisher.announce(:create_refund, Refund.find(refund_row["id"])) + {"payment" => payment_row, "refund" => refund_row} end end diff --git a/app/legacy_lib/insert_source_token.rb b/app/legacy_lib/insert_source_token.rb index faa28fcc4d..40486ca8c1 100644 --- a/app/legacy_lib/insert_source_token.rb +++ b/app/legacy_lib/insert_source_token.rb @@ -4,11 +4,11 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module InsertSourceToken def self.create_record(tokenizable, params = {}) - ParamValidation.new({ tokenizable: tokenizable }.merge(params), - tokenizable: { required: true }, - event: { is_a: Event }, - expiration_time: { is_integer: true, min: 1 }, - max_uses: { is_integer: true, min: 1 }) + ParamValidation.new({tokenizable: tokenizable}.merge(params), + tokenizable: {required: true}, + event: {is_a: Event}, + expiration_time: {is_integer: true, min: 1}, + max_uses: {is_integer: true, min: 1}) if !params[:event].nil? max_uses = params[:max_uses] || Houdini.source_tokens.event_donation_source.max_uses expiration_diff = params[:expiration_time] || Houdini.source_tokens.event_donation_source.expiration_after_event diff --git a/app/legacy_lib/insert_supporter.rb b/app/legacy_lib/insert_supporter.rb index 80f6635f77..fb644bc170 100644 --- a/app/legacy_lib/insert_supporter.rb +++ b/app/legacy_lib/insert_supporter.rb @@ -6,24 +6,24 @@ module InsertSupporter def self.create_or_update(nonprofit, data, update = false) address_keys = %w[name address city country state_code] - custom_fields = data['customFields'] - data = HashWithIndifferentAccess.new(Format::RemoveDiacritics.from_hash(data, address_keys)) - .except(:customFields) + custom_fields = data["customFields"] + data = ActiveSupport::HashWithIndifferentAccess.new(Format::RemoveDiacritics.from_hash(data, address_keys)) + .except(:customFields) - supporter = Qx.select('*').from(:supporters) - .where('name = $n AND email = $e', n: data[:name], e: data[:email]) - .and_where('nonprofit_id=$id', id: nonprofit.id) - .and_where('coalesce(deleted, FALSE)=FALSE') - .execute.last - if supporter && update - supporter = Qx.update(:supporters) - .set(defaults(data)) - .where('id=$id', id: supporter['id']) - .returning('*') - .timestamps - .execute.last + supporter = Qx.select("*").from(:supporters) + .where("name = $n AND email = $e", n: data[:name], e: data[:email]) + .and_where("nonprofit_id=$id", id: nonprofit.id) + .and_where("coalesce(deleted, FALSE)=FALSE") + .execute.last + supporter = if supporter && update + Qx.update(:supporters) + .set(defaults(data)) + .where("id=$id", id: supporter["id"]) + .returning("*") + .timestamps + .execute.last else - supporter = nonprofit.supporters.create(defaults(data)) + nonprofit.supporters.create(defaults(data)) end if custom_fields @@ -34,23 +34,21 @@ def self.create_or_update(nonprofit, data, update = false) end def self.defaults(h) - h = h.except('profile_id') unless h['profile_id'].present? - if h['first_name'].present? || h['last_name'].present? - h['name'] = h['first_name'] || h['last_name'] - if h['first_name'] && h['last_name'] - h['name'] = "#{h['first_name'].strip} #{h['last_name'].strip}" + h = h.except("profile_id") unless h["profile_id"].present? + if h["first_name"].present? || h["last_name"].present? + h["name"] = h["first_name"] || h["last_name"] + if h["first_name"] && h["last_name"] + h["name"] = "#{h["first_name"].strip} #{h["last_name"].strip}" end end - h['email_unsubscribe_uuid'] = SecureRandom.uuid + h["email_unsubscribe_uuid"] = SecureRandom.uuid - if h['address'].present? && h['address_line2'].present? - h['address'] += ' ' + h['address_line2'] + if h["address"].present? && h["address_line2"].present? + h["address"] += " " + h["address_line2"] end - h = h.except('address_line2') - - h + h.except("address_line2") end # pass in a hash of supporter info, as well as @@ -66,13 +64,13 @@ def self.defaults(h) # The above will create a supporter with name/email, one tag with name 'xy', # and one field with name 'xy' and value 420 def self.with_tags_and_fields(np_id, data) - tags = data.select { |key, _val| key.match(/^tag_/) }.map { |key, _val| key.gsub('tag_', '') } - fields = data.select { |key, _val| key.match(/^field_/) }.map { |key, val| [key.gsub('field_', ''), val] } + tags = data.select { |key, _val| key.match(/^tag_/) }.map { |key, _val| key.gsub("tag_", "") } + fields = data.select { |key, _val| key.match(/^field_/) }.map { |key, val| [key.gsub("field_", ""), val] } supp_cols = data.select { |key, _val| !key.match(/^field_/) && !key.match(/^tag_/) } supporter = create_or_update(np_id, supp_cols) - InsertTagJoins.find_or_create(np_id, [supporter['id']], tags) if tags.any? - InsertCustomFieldJoins.find_or_create(np_id, [supporter['id']], fields) if fields.any? + InsertTagJoins.find_or_create(np_id, [supporter["id"]], tags) if tags.any? + InsertCustomFieldJoins.find_or_create(np_id, [supporter["id"]], fields) if fields.any? supporter end diff --git a/app/legacy_lib/insert_supporter_notes.rb b/app/legacy_lib/insert_supporter_notes.rb index aa9e717838..c599f92bd6 100644 --- a/app/legacy_lib/insert_supporter_notes.rb +++ b/app/legacy_lib/insert_supporter_notes.rb @@ -4,7 +4,7 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module InsertSupporterNotes - #note_supporter_users : array of hashes + # note_supporter_users : array of hashes # each hash: # supporter: Supporter new note should belong to # user: User creating the note diff --git a/app/legacy_lib/insert_tag_joins.rb b/app/legacy_lib/insert_tag_joins.rb index 965d71ad85..49f83dac0a 100644 --- a/app/legacy_lib/insert_tag_joins.rb +++ b/app/legacy_lib/insert_tag_joins.rb @@ -14,35 +14,35 @@ module InsertTagJoins def self.in_bulk(np_id, profile_id, supporter_ids, tag_data) begin ParamValidation.new({ - np_id: np_id, - profile_id: profile_id, - supporter_ids: supporter_ids, - tag_data: tag_data - }, - np_id: { required: true, is_integer: true }, - profile_id: { required: true, is_integer: true }, - supporter_ids: { is_array: true }, - tag_data: { required: true }) + np_id: np_id, + profile_id: profile_id, + supporter_ids: supporter_ids, + tag_data: tag_data + }, + np_id: {required: true, is_integer: true}, + profile_id: {required: true, is_integer: true}, + supporter_ids: {is_array: true}, + tag_data: {required: true}) # array_of_hashes: { # selected: {required: true}, tag_definition_id: {required: true, is_integer: true} # } rescue ParamValidation::ValidationError => e - return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } + return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} end begin - return { json: { error: "Nonprofit #{np_id} is not valid" }, status: :unprocessable_entity } unless Nonprofit.exists?(np_id) - return { json: { error: "Profile #{profile_id} is not valid" }, status: :unprocessable_entity } unless Profile.exists?(profile_id) + return {json: {error: "Nonprofit #{np_id} is not valid"}, status: :unprocessable_entity} unless Nonprofit.exists?(np_id) + return {json: {error: "Profile #{profile_id} is not valid"}, status: :unprocessable_entity} unless Profile.exists?(profile_id) # verify that the supporters belong to the nonprofit - original_supporter_request = supporter_ids.count - supporter_ids = Supporter.where('nonprofit_id = ? and id IN (?)', np_id, supporter_ids).pluck(:id) + supporter_ids.count + supporter_ids = Supporter.where("nonprofit_id = ? and id IN (?)", np_id, supporter_ids).pluck(:id) unless supporter_ids.any? - return { json: { inserted_count: 0, removed_count: 0 }, status: :ok } + return {json: {inserted_count: 0, removed_count: 0}, status: :ok} end # filtering the tag_data to this nonprofit - valid_ids = TagDefinition.where('nonprofit_id = ? and id IN (?)', np_id, tag_data.map { |tg| tg[:tag_definition_id] }).pluck(:id).to_a + valid_ids = TagDefinition.where("nonprofit_id = ? and id IN (?)", np_id, tag_data.map { |tg| tg[:tag_definition_id] }).pluck(:id).to_a filtered_tag_data = tag_data.select { |i| valid_ids.include? i[:tag_definition_id].to_i } # first, delete the items which should be removed @@ -50,28 +50,28 @@ def self.in_bulk(np_id, profile_id, supporter_ids, tag_data) deleted = [] if to_remove.any? deleted = Qx.delete_from(:tag_joins) - .where('supporter_id IN ($ids)', ids: supporter_ids) - .and_where('tag_definition_id in ($tags)', tags: to_remove) - .returning('*') - .execute + .where("supporter_id IN ($ids)", ids: supporter_ids) + .and_where("tag_definition_id in ($tags)", tags: to_remove) + .returning("*") + .execute end # next add only the selected tag_joins to_insert = filtered_tag_data.select { |t| t[:selected] }.map { |t| t[:tag_definition_id] } - insert_data = supporter_ids.map { |id| to_insert.map { |tag_definition_id| { supporter_id: id, tag_definition_id: tag_definition_id } } }.flatten - if insert_data.any? - tags = Qx.insert_into(:tag_joins) - .values(insert_data) - .timestamps - .on_conflict - .conflict_columns(:supporter_id, :tag_definition_id).upsert(:tag_join_supporter_unique_idx) - .returning('*') - .execute + insert_data = supporter_ids.map { |id| to_insert.map { |tag_definition_id| {supporter_id: id, tag_definition_id: tag_definition_id} } }.flatten + tags = if insert_data.any? + Qx.insert_into(:tag_joins) + .values(insert_data) + .timestamps + .on_conflict + .conflict_columns(:supporter_id, :tag_definition_id).upsert(:tag_join_supporter_unique_idx) + .returning("*") + .execute else - tags = [] + [] end rescue ActiveRecord::ActiveRecordError => e - return { json: { error: "A DB error occurred. Please contact support. \n #{e.message}" }, status: :unprocessable_entity } + return {json: {error: "A DB error occurred. Please contact support. \n #{e.message}"}, status: :unprocessable_entity} end # Create an activity for the modified tags for every supporter @@ -82,7 +82,7 @@ def self.in_bulk(np_id, profile_id, supporter_ids, tag_data) # Sync mailchimp lists, if present MailchimpSupporterSyncJob.perform_later(np_id, supporter_ids, tag_data.as_json) - { json: { inserted_count: tags.count, removed_count: deleted.count }, status: :ok } + {json: {inserted_count: tags.count, removed_count: deleted.count}, status: :ok} end # Find or create many tag names for every supporter @@ -91,25 +91,23 @@ def self.find_or_create(np_id, supporter_ids, tag_names) # Pair each tag name with a tag definition id tags = tag_names.map do |name| tm = Qx.select(:id).from(:tag_definitions) - .where(name: name) - .and_where(nonprofit_id: np_id) - .execute.last + .where(name: name) + .and_where(nonprofit_id: np_id) + .execute.last tm ||= Qx.insert_into(:tag_definitions).values( name: name, nonprofit_id: np_id - ).ts.returning('id').execute.last - [name, tm['id']] + ).ts.returning("id").execute.last + [name, tm["id"]] end tag_join_data = supporter_ids.map do |id| - tags.map { |_name, tm_id| { supporter_id: id, tag_definition_id: tm_id } } + tags.map { |_name, tm_id| {supporter_id: id, tag_definition_id: tm_id} } end.flatten - tag_joins = Qx.insert_into(:tag_joins) - .values(tag_join_data) - .ts.returning('id').execute - - tag_joins + Qx.insert_into(:tag_joins) + .values(tag_join_data) + .ts.returning("id").execute end private diff --git a/app/legacy_lib/insert_tickets.rb b/app/legacy_lib/insert_tickets.rb index 61cfbf1364..3d14ef511c 100644 --- a/app/legacy_lib/insert_tickets.rb +++ b/app/legacy_lib/insert_tickets.rb @@ -19,24 +19,24 @@ module InsertTickets def self.create(data) data = data.with_indifferent_access ParamValidation.new(data, - tickets: { required: true, is_array: true }, - nonprofit_id: { required: true, is_reference: true }, - supporter_id: { required: true, is_reference: true }, - event_id: { required: true, is_reference: true }, - event_discount_id: { is_reference: true }, - kind: { included_in: %w[free charge offsite] }, - token: { format: UUID::Regex }, - offsite_payment: { is_hash: true }) + tickets: {required: true, is_array: true}, + nonprofit_id: {required: true, is_reference: true}, + supporter_id: {required: true, is_reference: true}, + event_id: {required: true, is_reference: true}, + event_discount_id: {is_reference: true}, + kind: {included_in: %w[free charge offsite]}, + token: {format: UUID::Regex}, + offsite_payment: {is_hash: true}) data[:tickets].each do |t| - ParamValidation.new(t, quantity: { is_integer: true, required: true, min: 1 }, ticket_level_id: { is_reference: true, required: true }) + ParamValidation.new(t, quantity: {is_integer: true, required: true, min: 1}, ticket_level_id: {is_reference: true, required: true}) end - ParamValidation.new(data[:offsite_payment], kind: { included_in: %w[cash check] }) if data[:offsite_payment] && !data[:offsite_payment][:kind].blank? + ParamValidation.new(data[:offsite_payment], kind: {included_in: %w[cash check]}) if data[:offsite_payment] && !data[:offsite_payment][:kind].blank? entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id, Event => :event_id) - entities.merge!(RetrieveActiveRecordItems.retrieve_from_keys(data, { EventDiscount => :event_discount_id }, true)) + entities.merge!(RetrieveActiveRecordItems.retrieve_from_keys(data, {EventDiscount => :event_discount_id}, true)) tl_entities = get_ticket_level_entities(data) @@ -53,7 +53,7 @@ def self.create(data) subtrx = nil if gross_amount > 0 # Create offsite payment for tickets - if data[:kind] == 'offsite' + if data[:kind] == "offsite" current_user = data[:current_user] # offsite can only come from valid nonprofit users unless current_user && QueryRoles.is_authorized_for_nonprofit?(current_user.id, entities[:nonprofit_id].id) @@ -61,19 +61,20 @@ def self.create(data) end # create payment and offsite payment - result['payment'] = create_payment(entities, gross_amount) - result['offsite_payment'] = create_offsite_payment(entities, gross_amount, data, result['payment']) + result["payment"] = create_payment(entities, gross_amount) + result["offsite_payment"] = create_offsite_payment(entities, gross_amount, data, result["payment"]) subtrx = trx.build_subtransaction( subtransactable: OfflineTransaction.new(amount: gross_amount), - payments:[ + payments: [ SubtransactionPayment.new( - paymentable: OfflineTransactionCharge.new(payment: Payment.find(result['payment']['id']))) - ], - created: data['date'] - ); + paymentable: OfflineTransactionCharge.new(payment: Payment.find(result["payment"]["id"])) + ) + ], + created: data["date"] + ) # Create charge for tickets - elsif data['kind'] == 'charge' || !data['kind'] + elsif data["kind"] == "charge" || !data["kind"] source_token = QuerySourceToken.get_and_increment_source_token(data[:token], nil) QuerySourceToken.validate_source_token_type(source_token) tokenizable = source_token.tokenizable @@ -83,26 +84,27 @@ def self.create(data) end result = result.merge(InsertCharge.with_stripe( - kind: 'Ticket', - towards: entities[:event_id].name, - metadata: { kind: 'Ticket', event_id: entities[:event_id].id, nonprofit_id: entities[:nonprofit_id].id }, - statement: "Tickets #{entities[:event_id].name}", - amount: gross_amount, - nonprofit_id: entities[:nonprofit_id].id, - supporter_id: entities[:supporter_id].id, - card_id: tokenizable.id - )) - if result['charge']['status'] == 'failed' - raise ChargeError, result['charge']['failure_message'] + kind: "Ticket", + towards: entities[:event_id].name, + metadata: {kind: "Ticket", event_id: entities[:event_id].id, nonprofit_id: entities[:nonprofit_id].id}, + statement: "Tickets #{entities[:event_id].name}", + amount: gross_amount, + nonprofit_id: entities[:nonprofit_id].id, + supporter_id: entities[:supporter_id].id, + card_id: tokenizable.id + )) + if result["charge"]["status"] == "failed" + raise ChargeError, result["charge"]["failure_message"] else subtrx = trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: gross_amount), - payments:[ - SubtransactionPayment.new( - paymentable: StripeCharge.new(payment: Payment.find(result['payment']['id']))) + subtransactable: StripeTransaction.new(amount: gross_amount), + payments: [ + SubtransactionPayment.new( + paymentable: StripeCharge.new(payment: Payment.find(result["payment"]["id"])) + ) ], created: Time.current - ); + ) end else raise ParamValidation::ValidationError.new("Ticket costs money but you didn't pay.", key: :kind) @@ -111,24 +113,23 @@ def self.create(data) ticket_purchase = trx.ticket_purchases.build(event: entities[:event_id]) # Generate the bid ids - data['tickets'] = generate_bid_ids(entities[:event_id].id, tl_entities) - - result['tickets'] = generated_ticket_entities(data['tickets'], result, entities) - result['tickets'].each do |legacy_ticket| + data["tickets"] = generate_bid_ids(entities[:event_id].id, tl_entities) + result["tickets"] = generated_ticket_entities(data["tickets"], result, entities) + result["tickets"].each do |legacy_ticket| legacy_ticket.quantity.times do ticket_purchase.ticket_to_legacy_tickets.build(ticket: legacy_ticket) end end # Create the activity rows for the tickets - InsertActivities.for_tickets(result['tickets'].map(&:id)) + InsertActivities.for_tickets(result["tickets"].map(&:id)) - ticket_ids = result['tickets'].map(&:id) - charge_id = result['charge'] ? result['charge'].id : nil + result["tickets"].map(&:id) + result["charge"] ? result["charge"].id : nil trx.save! ticket_purchase.save! - if (subtrx) + if subtrx subtrx.save! subtrx.payments.each(&:publish_created) subtrx.publish_created @@ -144,23 +145,23 @@ def self.create(data) def self.generate_bid_ids(event_id, tickets) # Generate the bid ids last_bid_id = Psql.execute( - Qexpr.new.select('COUNT(*)').from(:tickets) - .where('event_id=$id', id: event_id) - ).first['count'].to_i - tickets.zip(last_bid_id + 1..last_bid_id + tickets.count).map { |h, id| h.merge('bid_id' => id) } + Qexpr.new.select("COUNT(*)").from(:tickets) + .where("event_id=$id", id: event_id) + ).first["count"].to_i + tickets.zip(last_bid_id + 1..last_bid_id + tickets.count).map { |h, id| h.merge("bid_id" => id) } end # not really needed but used for breaking into the unit test and getting the IDs def self.generated_ticket_entities(ticket_data, result, entities) ticket_data.map do |ticket_request| t = Ticket.new - t.quantity = ticket_request['quantity'] - t.ticket_level = ticket_request['ticket_level_id'] + t.quantity = ticket_request["quantity"] + t.ticket_level = ticket_request["ticket_level_id"] t.event = entities[:event_id] t.supporter = entities[:supporter_id] - t.payment = result['payment'] - t.charge = result['charge'] - t.bid_id = ticket_request['bid_id'] + t.payment = result["payment"] + t.charge = result["charge"] + t.bid_id = ticket_request["bid_id"] t.event_discount = entities[:event_discount_id] t.save! t @@ -222,7 +223,7 @@ def self.create_payment(entities, gross_amount) p.towards = entities[:event_id].name p.fee_total = 0 p.net_amount = gross_amount - p.kind = 'OffsitePayment' + p.kind = "OffsitePayment" p.save! p end @@ -234,8 +235,8 @@ def self.create_offsite_payment(entities, gross_amount, data, payment) p.supporter = entities[:supporter_id] p.date = Time.current p.payment = payment - p.kind = data['offsite_payment']['kind'] - p.check_number = data['offsite_payment']['check_number'] + p.kind = data["offsite_payment"]["kind"] + p.check_number = data["offsite_payment"]["check_number"] p.save! p end diff --git a/app/legacy_lib/insert_tracking.rb b/app/legacy_lib/insert_tracking.rb index c040e824d4..863a3f61c5 100644 --- a/app/legacy_lib/insert_tracking.rb +++ b/app/legacy_lib/insert_tracking.rb @@ -6,18 +6,18 @@ module InsertTracking def self.create(params) result = {} - result['tracking'] = Qx.insert_into(:trackings) - .values( - utm_campaign: params[:utm_campaign], - utm_content: params[:utm_content], - utm_medium: params[:utm_medium], - utm_source: params[:utm_source], - donation_id: params[:donation_id] - ) - .timestamps - .returning('*') - .execute.first + result["tracking"] = Qx.insert_into(:trackings) + .values( + utm_campaign: params[:utm_campaign], + utm_content: params[:utm_content], + utm_medium: params[:utm_medium], + utm_source: params[:utm_source], + donation_id: params[:donation_id] + ) + .timestamps + .returning("*") + .execute.first - { status: 200, json: result } + {status: 200, json: result} end end diff --git a/app/legacy_lib/json_resp.rb b/app/legacy_lib/json_resp.rb index 71664926b3..5712b2f969 100644 --- a/app/legacy_lib/json_resp.rb +++ b/app/legacy_lib/json_resp.rb @@ -19,16 +19,15 @@ def initialize(params, &block) validation = JsonResp::Validation.new(params) validation.instance_exec(params, &block) @errors = validation.errors - self end def when_valid - return { status: 422, json: { errors: @errors } } if @errors.any? + return {status: 422, json: {errors: @errors}} if @errors.any? begin @response = yield(@params) rescue Exception => e - @response = { status: 500, json: { error: "We're sorry, but something went wrong. We've been notified about this issue." } } + @response = {status: 500, json: {error: "We're sorry, but something went wrong. We've been notified about this issue."}} puts e puts e.backtrace.first(10) end @@ -42,7 +41,6 @@ class Validation def initialize(params) @params = params @errors = [] - self end def requires(*keys) @@ -97,7 +95,7 @@ def with_format(regex) end def one_of(*vals) - @errors.concat @keys.reject { |k| vals.include?(@params[k]) }.map { |k| "#{k} must be one of: #{vals.join(', ')}" } + @errors.concat @keys.reject { |k| vals.include?(@params[k]) }.map { |k| "#{k} must be one of: #{vals.join(", ")}" } self end @@ -117,10 +115,10 @@ def array_of(&block) end def as_date - with_format /\d\d\d\d-\d\d-\d\d/ - @errors.concat @keys.map { |k| [k].concat @params[k].split('-').map(&:to_i) } - .reject { |_key, year, month, day| year.present? && year > 1000 && year < 3000 && month.present? && month > 0 && month < 13 && day.present? && day > 0 && day < 32 } - .map { |k, _, _, _| "#{k} must be a valid date" } + with_format(/\d\d\d\d-\d\d-\d\d/) + @errors.concat @keys.map { |k| [k].concat @params[k].split("-").map(&:to_i) } + .reject { |_key, year, month, day| year.present? && year > 1000 && year < 3000 && month.present? && month > 0 && month < 13 && day.present? && day > 0 && day < 32 } + .map { |k, _, _, _| "#{k} must be a valid date" } end def min(n) diff --git a/app/legacy_lib/mailchimp.rb b/app/legacy_lib/mailchimp.rb index 1dfe5bf9ea..6660661ce6 100644 --- a/app/legacy_lib/mailchimp.rb +++ b/app/legacy_lib/mailchimp.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'httparty' -require 'digest/md5' +require "httparty" +require "digest/md5" module Mailchimp include HTTParty @@ -19,8 +19,8 @@ def self.base_uri(key) def self.config(hash) @options = { headers: { - 'Content-Type' => 'application/json', - 'Accept' => 'application/json' + "Content-Type" => "application/json", + "Accept" => "application/json" } } @body = { @@ -30,26 +30,26 @@ def self.config(hash) # Given a nonprofit mailchimp oauth2 key, return its current datacenter def self.get_datacenter(key) - metadata = HTTParty.get('https://login.mailchimp.com/oauth2/metadata', - headers: { - 'User-Agent' => 'oauth2-draft-v10', - 'Host' => 'login.mailchimp.com', - 'Accept' => 'application/json', - 'Authorization' => "OAuth #{key}" - }) - metadata['dc'] + metadata = HTTParty.get("https://login.mailchimp.com/oauth2/metadata", + headers: { + "User-Agent" => "oauth2-draft-v10", + "Host" => "login.mailchimp.com", + "Accept" => "application/json", + "Authorization" => "OAuth #{key}" + }) + metadata["dc"] end def self.signup(email, mailchimp_list_id) body_hash = @body.merge( id: mailchimp_list_id, - email: { email: email } + email: {email: email} ) - post('/lists/subscribe', @options.merge(body: body_hash.to_json)).parsed_response + post("/lists/subscribe", @options.merge(body: body_hash.to_json)).parsed_response end def self.get_mailchimp_token(npo_id) - mailchimp_token = QueryNonprofitKeys.get_key(npo_id, 'mailchimp_token') + mailchimp_token = QueryNonprofitKeys.get_key(npo_id, "mailchimp_token") throw RuntimeError.new("No Mailchimp connection for this nonprofit: #{npo_id}") if mailchimp_token.nil? mailchimp_token end @@ -63,41 +63,41 @@ def self.create_mailchimp_lists(npo_id, tag_definition_ids) puts "KEY #{mailchimp_token}" npo = Qx.fetch(:nonprofits, npo_id).first - tags = Qx.select('DISTINCT(tag_definitions.name) AS tag_name, tag_definitions.id') - .from(:tag_definitions) - .where('tag_definitions.nonprofit_id' => npo_id) - .and_where('tag_definitions.id IN ($ids)', ids: tag_definition_ids) - .join(:nonprofits, 'tag_definitions.nonprofit_id = nonprofits.id') - .execute + tags = Qx.select("DISTINCT(tag_definitions.name) AS tag_name, tag_definitions.id") + .from(:tag_definitions) + .where("tag_definitions.nonprofit_id" => npo_id) + .and_where("tag_definitions.id IN ($ids)", ids: tag_definition_ids) + .join(:nonprofits, "tag_definitions.nonprofit_id = nonprofits.id") + .execute tags.map do |h| - list = post(uri + '/lists', - basic_auth: { username: '', password: mailchimp_token }, - headers: { 'Content-Type' => 'application/json' }, - body: { - name: 'CommitChange-' + h['tag_name'], - contact: { - company: npo['name'], - address1: npo['address'] || '', - city: npo['city'] || '', - state: npo['state_code'] || '', - zip: npo['zip_code'] || '', - country: npo['state_code'] || '', - phone: npo['phone'] || '' - }, - permission_reminder: 'You are a registered supporter of our nonprofit.', - campaign_defaults: { - from_name: npo['name'] || '', - from_email: npo['email'].blank? ? 'support@commichange.com' : npo['email'], - subject: 'Enter your subject here...', - language: 'en' - }, - email_type_option: false, - visibility: 'prv' - }.to_json) + list = post(uri + "/lists", + basic_auth: {username: "", password: mailchimp_token}, + headers: {"Content-Type" => "application/json"}, + body: { + name: "CommitChange-" + h["tag_name"], + contact: { + company: npo["name"], + address1: npo["address"] || "", + city: npo["city"] || "", + state: npo["state_code"] || "", + zip: npo["zip_code"] || "", + country: npo["state_code"] || "", + phone: npo["phone"] || "" + }, + permission_reminder: "You are a registered supporter of our nonprofit.", + campaign_defaults: { + from_name: npo["name"] || "", + from_email: npo["email"].presence || "support@commichange.com", + subject: "Enter your subject here...", + language: "en" + }, + email_type_option: false, + visibility: "prv" + }.to_json) raise Exception, "Failed to create list: #{list}" if list.code != 200 - { id: list['id'], name: list['name'], tag_definition_id: h['id'] } + {id: list["id"], name: list["name"], tag_definition_id: h["id"]} end end @@ -109,49 +109,49 @@ def self.perform_batch_operations(npo_id, post_data) mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) - batch_job_id = post(uri + '/batches', - basic_auth: { username: 'CommitChange', password: mailchimp_token }, - headers: { 'Content-Type' => 'application/json' }, - body: { operations: post_data }.to_json)['id'] + batch_job_id = post(uri + "/batches", + basic_auth: {username: "CommitChange", password: mailchimp_token}, + headers: {"Content-Type" => "application/json"}, + body: {operations: post_data}.to_json)["id"] check_batch_status(npo_id, batch_job_id) end def self.check_batch_status(npo_id, batch_job_id) mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) - batch_status = get(uri + '/batches/' + batch_job_id, - basic_auth: { username: 'CommitChange', password: mailchimp_token }, - headers: { 'Content-Type' => 'application/json' }) + get(uri + "/batches/" + batch_job_id, + basic_auth: {username: "CommitChange", password: mailchimp_token}, + headers: {"Content-Type" => "application/json"}) end def self.delete_mailchimp_lists(npo_id, mailchimp_list_ids) mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) mailchimp_list_ids.map do |id| - delete(uri + "/lists/#{id}", basic_auth: { username: 'CommitChange', password: mailchimp_token }) + delete(uri + "/lists/#{id}", basic_auth: {username: "CommitChange", password: mailchimp_token}) end end # `removed` and `added` are arrays of tag join ids that have been added or removed to a supporter def self.sync_supporters_to_list_from_tag_joins(npo_id, supporter_ids, tag_data) - emails = Qx.select(:email).from(:supporters).where('id IN ($ids)', ids: supporter_ids).execute.map { |h| h['email'] } - to_add = get_mailchimp_list_ids(tag_data.select { |h| h['selected'] }.map { |h| h['tag_definition_id'] }) - to_remove = get_mailchimp_list_ids(tag_data.reject { |h| h['selected'] }.map { |h| h['tag_definition_id'] }) + emails = Qx.select(:email).from(:supporters).where("id IN ($ids)", ids: supporter_ids).execute.map { |h| h["email"] } + to_add = get_mailchimp_list_ids(tag_data.select { |h| h["selected"] }.map { |h| h["tag_definition_id"] }) + to_remove = get_mailchimp_list_ids(tag_data.reject { |h| h["selected"] }.map { |h| h["tag_definition_id"] }) return if to_add.empty? && to_remove.empty? - bulk_post = emails.map { |em| to_add.map { |ml_id| { method: 'POST', path: "lists/#{ml_id}/members", body: { email_address: em, status: 'subscribed' }.to_json } } }.flatten - bulk_delete = emails.map { |em| to_remove.map { |ml_id| { method: 'DELETE', path: "lists/#{ml_id}/members/#{Digest::MD5.hexdigest(em.downcase)}" } } }.flatten + bulk_post = emails.map { |em| to_add.map { |ml_id| {method: "POST", path: "lists/#{ml_id}/members", body: {email_address: em, status: "subscribed"}.to_json} } }.flatten + bulk_delete = emails.map { |em| to_remove.map { |ml_id| {method: "DELETE", path: "lists/#{ml_id}/members/#{Digest::MD5.hexdigest(em.downcase)}"} } }.flatten perform_batch_operations(npo_id, bulk_post.concat(bulk_delete)) end def self.get_mailchimp_list_ids(tag_definition_ids) return [] if tag_definition_ids.empty? - to_insert_data = Qx.select('email_lists.mailchimp_list_id') - .from(:tag_definitions) - .where('tag_definitions.id IN ($ids)', ids: tag_definition_ids) - .join('email_lists', 'email_lists.tag_definition_id=tag_definitions.id') - .execute.map { |h| h['mailchimp_list_id'] } + Qx.select("email_lists.mailchimp_list_id") + .from(:tag_definitions) + .where("tag_definitions.id IN ($ids)", ids: tag_definition_ids) + .join("email_lists", "email_lists.tag_definition_id=tag_definitions.id") + .execute.map { |h| h["mailchimp_list_id"] } end # @param [Nonprofit] nonprofit @@ -164,12 +164,12 @@ def self.hard_sync_lists(nonprofit) end # @param [EmailList] email_list - # Notably, if a supporter unsubscribed on Mailchimp, this will not + # Notably, if a supporter unsubscribed on Mailchimp, this will not # resubscribe them. This is the correct behavior. def self.hard_sync_list(email_list) ops = generate_batch_ops_for_hard_sync(email_list) perform_batch_operations(email_list.nonprofit.id, ops) - end + end def self.generate_batch_ops_for_hard_sync(email_list) # get the subscribers from mailchimp @@ -179,7 +179,7 @@ def self.generate_batch_ops_for_hard_sync(email_list) # split them as follows: # on both lists, on our list, on the mailchimp list - in_both, in_mailchimp_only = mailchimp_subscribers.partition do |mc_sub| + _, in_mailchimp_only = mailchimp_subscribers.partition do |mc_sub| our_supporters.any? { |s| s.email.casecmp(mc_sub[:email_address]).zero? } end @@ -189,32 +189,30 @@ def self.generate_batch_ops_for_hard_sync(email_list) # if on our list, add to mailchimp output = in_our_side_only.map do |i| - { method: 'POST', path: "lists/#{email_list.mailchimp_list_id}/members", body: { email_address: i.email, status: 'subscribed' }.to_json } + {method: "POST", path: "lists/#{email_list.mailchimp_list_id}/members", body: {email_address: i.email, status: "subscribed"}.to_json} end # if on mailchimp list, delete from mailchimp - output = output.concat(in_mailchimp_only.map { |i| { method: 'DELETE', path: "lists/#{email_list.mailchimp_list_id}/members/#{i[:id]}" } }) - - output + output.concat(in_mailchimp_only.map { |i| {method: "DELETE", path: "lists/#{email_list.mailchimp_list_id}/members/#{i[:id]}"} }) end def self.get_list_mailchimp_subscribers(email_list) mailchimp_token = get_mailchimp_token(email_list.tag_definition.nonprofit.id) uri = base_uri(mailchimp_token) result = get(uri + "/lists/#{email_list.mailchimp_list_id}/members?count=1000000000", - basic_auth: { username: 'CommitChange', password: mailchimp_token }, - headers: { 'Content-Type' => 'application/json' }) - members = result['members'].map do |i| - { id: i['id'], email_address: i['email_address'] } + basic_auth: {username: "CommitChange", password: mailchimp_token}, + headers: {"Content-Type" => "application/json"}) + result["members"].map do |i| + {id: i["id"], email_address: i["email_address"]} end.to_a end def self.get_email_lists(nonprofit) mailchimp_token = get_mailchimp_token(nonprofit.id) uri = base_uri(mailchimp_token) - result = get(uri + '/lists', - basic_auth: { username: 'CommitChange', password: mailchimp_token }, - headers: { 'Content-Type' => 'application/json' }) - result['lists'] - end + result = get(uri + "/lists", + basic_auth: {username: "CommitChange", password: mailchimp_token}, + headers: {"Content-Type" => "application/json"}) + result["lists"] + end end diff --git a/app/legacy_lib/maintain_dedications.rb b/app/legacy_lib/maintain_dedications.rb index c06f668f32..9f789a0287 100644 --- a/app/legacy_lib/maintain_dedications.rb +++ b/app/legacy_lib/maintain_dedications.rb @@ -4,40 +4,43 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module MaintainDedications def self.retrieve_json_dedications - Qx.select('id', 'dedication').from(:donations) - .where('is_valid_json(dedication)').ex + Qx.select("id", "dedication").from(:donations) + .where("is_valid_json(dedication)").ex end def self.retrieve_non_json_dedications(include_blank = false) - temp = Qx.select('id', 'dedication').from(:donations) + temp = Qx.select("id", "dedication").from(:donations) temp = temp.where("dedication IS NOT NULL AND dedication != ''") unless include_blank - temp = temp.and_where('NOT is_valid_json(dedication)') + temp = temp.and_where("NOT is_valid_json(dedication)") temp.ex end def self.create_json_dedications_from_plain_text(dedications) dedications.map do |i| - output = { id: i['id'] } - if i['dedication'] =~ /(((in (loving )?)?memory of|in memorium)\:? )(.+)/i - output[:dedication] = JSON.generate(type: 'memory', note: $+) - elsif i['dedication'] =~ /((in honor of|honor of)\:? )(.+)/i - output[:dedication] = JSON.generate(type: 'honor', note: $+) + output = {id: i["id"]} + output[:dedication] = if i["dedication"] =~ /(((in (loving )?)?memory of|in memorium):? )(.+)/i + JSON.generate(type: "memory", note: $+) + elsif i["dedication"] =~ /((in honor of|honor of):? )(.+)/i + JSON.generate(type: "honor", note: $+) else - output[:dedication] = JSON.generate(type: 'honor', note: i['dedication']) + JSON.generate(type: "honor", note: i["dedication"]) end output end.each do |i| - Qx.update(:donations).where('id = $id', id: i[:id]).set(dedication: i[:dedication]).ex + Qx.update(:donations).where("id = $id", id: i[:id]).set(dedication: i[:dedication]).ex end end def self.add_honor_to_any_json_dedications_without_type(json_dedications) - json_dedications.map { |i| { 'id' => i['id'], 'dedication' => JSON.parse(i['dedication']) } } - .reject { |i| %w[honor memory].include?(i['dedication']['type']) } - .map { |i| i['dedication']['type'] = 'honor'; i } - .each do |i| - Qx.update(:donations).where('id = $id', id: i['id']) - .set(dedication: JSON.generate(i['dedication'])).ex + json_dedications.map { |i| {"id" => i["id"], "dedication" => JSON.parse(i["dedication"])} } + .reject { |i| %w[honor memory].include?(i["dedication"]["type"]) } + .map { |i| + i["dedication"]["type"] = "honor" + i + } + .each do |i| + Qx.update(:donations).where("id = $id", id: i["id"]) + .set(dedication: JSON.generate(i["dedication"])).ex end end end diff --git a/app/legacy_lib/maintain_payment_records.rb b/app/legacy_lib/maintain_payment_records.rb index a4705cc408..3b0758cf52 100644 --- a/app/legacy_lib/maintain_payment_records.rb +++ b/app/legacy_lib/maintain_payment_records.rb @@ -4,7 +4,7 @@ module MaintainPaymentRecords # For records which have no associated charge, refund, nonprofit, supporter, donation or a gross_amount # The record is basically useless def self.find_records_which_are_really_bad - Payment.includes(:charges).includes(:refund).where('payments.nonprofit_id IS NULL AND payments.supporter_id IS NULL AND payments.donation_id IS NULL AND payments.gross_amount IS NULL AND charges.id IS NULL AND refunds.id IS NULL') + Payment.includes(:charges).includes(:refund).where("payments.nonprofit_id IS NULL AND payments.supporter_id IS NULL AND payments.donation_id IS NULL AND payments.gross_amount IS NULL AND charges.id IS NULL AND refunds.id IS NULL") end def self.set_payment_supporter_and_nonprofit_though_charge_refund(i) diff --git a/app/legacy_lib/maintain_ticket_records.rb b/app/legacy_lib/maintain_ticket_records.rb index e2fdc66592..c2435cfd96 100644 --- a/app/legacy_lib/maintain_ticket_records.rb +++ b/app/legacy_lib/maintain_ticket_records.rb @@ -7,10 +7,10 @@ module MaintainTicketRecords # if the event was in the last two weeks def self.tokenize_cards_already_on_tickets Qx.transaction do - event_ids = Event.where('end_datetime >= ?', Time.current - 2.weeks).pluck(:id) + event_ids = Event.where("end_datetime >= ?", 2.weeks.ago).pluck(:id) - t = Ticket.includes(:card).includes(:event).where('card_id IS NOT NULL and event_id IN (?)', event_ids) - t.each do |i| + t = Ticket.includes(:card).includes(:event).where("card_id IS NOT NULL and event_id IN (?)", event_ids) + t.each do |i| token = InsertSourceToken.create_record(i.card, event: i.event) i.source_token = token i.save! diff --git a/app/legacy_lib/merge_supporters.rb b/app/legacy_lib/merge_supporters.rb index 7b2ed5e63e..f59360c1c7 100644 --- a/app/legacy_lib/merge_supporters.rb +++ b/app/legacy_lib/merge_supporters.rb @@ -9,29 +9,29 @@ def self.update_associations(old_supporter_ids, new_supporter_id, np_id, profile associations = %i[activities donations recurring_donations offsite_payments payments tickets supporter_notes full_contact_infos] associations.each do |table_name| - Qx.update(table_name).set(supporter_id: new_supporter_id).where('supporter_id IN ($ids)', ids: old_supporter_ids).timestamps.execute + Qx.update(table_name).set(supporter_id: new_supporter_id).where("supporter_id IN ($ids)", ids: old_supporter_ids).timestamps.execute end - old_supporters = Supporter.includes(:tag_joins).includes(:custom_field_joins).where('id in (?)', old_supporter_ids) + old_supporters = Supporter.includes(:tag_joins).includes(:custom_field_joins).where("id in (?)", old_supporter_ids) old_tags = old_supporters.map { |i| i.tag_joins.map(&:tag_definition) }.flatten.uniq # delete old tags InsertTagJoins.in_bulk(np_id, profile_id, old_supporter_ids, - old_tags.map { |i| { tag_definition_id: i.id, selected: false } }) + old_tags.map { |i| {tag_definition_id: i.id, selected: false} }) - InsertTagJoins.in_bulk(np_id, profile_id, [new_supporter_id], old_tags.map { |i| { tag_definition_id: i.id, selected: true } }) + InsertTagJoins.in_bulk(np_id, profile_id, [new_supporter_id], old_tags.map { |i| {tag_definition_id: i.id, selected: true} }) all_custom_field_joins = old_supporters.map(&:custom_field_joins).flatten group_joins_by_custom_field_definition = all_custom_field_joins.group_by { |i| i.custom_field_definition.id } one_custom_field_join_per_user = group_joins_by_custom_field_definition.map do |_k, v| - v.sort_by(&:created_at).reverse.first + v.sort_by(&:created_at).last end # delete old supporter custom_field InsertCustomFieldJoins.in_bulk(np_id, old_supporter_ids, one_custom_field_join_per_user.map do |i| { custom_field_definition_id: i.custom_field_definition_id, - value: '' + value: "" } end) @@ -44,7 +44,7 @@ def self.update_associations(old_supporter_ids, new_supporter_id, np_id, profile end) # Update all deleted/merged supporters to record when and where they got merged - Psql.execute(Qexpr.new.update(:supporters, merged_at: Time.current, merged_into: new_supporter_id).where('id IN ($ids)', ids: old_supporter_ids)) + Psql.execute(Qexpr.new.update(:supporters, merged_at: Time.current, merged_into: new_supporter_id).where("id IN ($ids)", ids: old_supporter_ids)) # Removing any duplicate custom fields UpdateCustomFieldJoins.delete_dupes([new_supporter_id]) end @@ -52,10 +52,10 @@ def self.selected(merged_data, supporter_ids, np_id, profile_id) new_supporter = Supporter.new(merged_data) new_supporter.save! # Update merged supporters as deleted - Psql.execute(Qexpr.new.update(:supporters, deleted: true).where('id IN ($ids)', ids: supporter_ids)) + Psql.execute(Qexpr.new.update(:supporters, deleted: true).where("id IN ($ids)", ids: supporter_ids)) # Update all associated tables - update_associations(supporter_ids, new_supporter['id'], np_id, profile_id) - { json: new_supporter, status: :ok } + update_associations(supporter_ids, new_supporter["id"], np_id, profile_id) + {json: new_supporter, status: :ok} end # Merge supporters for a nonprofit based on an array of groups of ids, generated from QuerySupporters.dupes_on_email or dupes_on_names @@ -66,13 +66,13 @@ def self.merge_by_id_groups(np_id, arr_of_ids, profile_id) all_data = Psql.execute( Qexpr.new.from(:supporters) .select(:email, :name, :phone, :address, :city, :state_code, :zip_code, :organization, :country, :created_at) - .where('id IN ($ids)', ids: ids) - .order_by('created_at ASC') + .where("id IN ($ids)", ids: ids) + .order_by("created_at ASC") ) # Use the most recent non null/blank column data for the new supporter data = all_data.each_with_object({}) do |supp, acc| - supp.except('created_at').each { |key, val| acc[key] = val unless val.blank? } - end.merge('nonprofit_id' => np_id) + supp.except("created_at").each { |key, val| acc[key] = val unless val.blank? } + end.merge("nonprofit_id" => np_id) MergeSupporters.selected(data, ids, np_id, profile_id) end diff --git a/app/legacy_lib/name_copy_naming_algorithm.rb b/app/legacy_lib/name_copy_naming_algorithm.rb index d896e38835..1f4df8a9cb 100644 --- a/app/legacy_lib/name_copy_naming_algorithm.rb +++ b/app/legacy_lib/name_copy_naming_algorithm.rb @@ -11,11 +11,11 @@ def initialize(klass, nonprofit_id) end def copy_addition - " (#{Time.now.strftime('%F')} copy)" + " (#{Time.now.strftime("%F")} copy)" end def separator_before_copy_number - ' ' + " " end def max_copies @@ -31,10 +31,10 @@ def get_name_for_entity(name_entity) end def get_already_used_name_entities(base_name) - end_name = "#{copy_addition.gsub('(', '\\(').gsub(')', '\\)')} \\d{2}" + end_name = "#{copy_addition.gsub("(", '\\(').gsub(")", '\\)')} \\d{2}" end_name_length = copy_addition.length + 3 amount_to_strip = end_name_length + base_name.length - max_length amount_to_strip = 0 if amount_to_strip < 0 - @klass.method(:where).call('name SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)', "#{base_name[0..base_name.length - amount_to_strip - 1]}_*" + end_name, nonprofit_id).select('name') + @klass.method(:where).call("name SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)", "#{base_name[0..base_name.length - amount_to_strip - 1]}_*" + end_name, nonprofit_id).select("name") end end diff --git a/app/legacy_lib/nonprofit_creation.rb b/app/legacy_lib/nonprofit_creation.rb index e3356028b5..9472d23874 100644 --- a/app/legacy_lib/nonprofit_creation.rb +++ b/app/legacy_lib/nonprofit_creation.rb @@ -6,57 +6,57 @@ # # NOTE: this should be moved to bess when Nonprofit and wiki is class NonprofitCreation - def initialize(result, options = {}) - result = sanitize_optional_fields(result) - @nonprofit = ::Nonprofit.new(result[:nonprofit].merge({ register_np_only: true })) - @user = User.new(result[:user]) - @options = options - end - - def call - result = {} - ActiveRecord::Base.transaction do - result = if @user.save && @nonprofit.save && roles.each(&:save) - @user.confirm if @options[:confirm_admin] - { success: true, messages: ["Nonprofit #{@nonprofit.id} successfully created."] } - else - retrieve_error_messages - end - end - result - end - - private - - def retrieve_error_messages - result = { success: false, messages: [] } - result = retrieve_user_error_messages(result) - result = retrieve_nonprofit_error_messages(result) - retrieve_roles_error_messages(result) - end - - def retrieve_user_error_messages(result) - @user.errors.full_messages.each { |i| result[:messages] << "Error creating user: #{i}" } - result - end - - def retrieve_nonprofit_error_messages(result) - @nonprofit.errors.full_messages.each { |i| result[:messages] << "Error creating nonprofit: #{i}" } - result - end - - def retrieve_roles_error_messages(result) - roles.each { |role| role.errors.full_messages.each { |i| result[:messages] << "Error creating role: #{i}" } } - result - end - - def roles - roles = [Role.new(host: @nonprofit, name: 'nonprofit_admin', user: @user)] - roles << Role.new(host: @nonprofit, name: 'super_admin', user: @user) if @options[:super_admin] - roles - end - - def sanitize_optional_fields(result) - result.transform_values! { |keys| keys.transform_values! { |value| value&.empty? ? nil : value } } - end + def initialize(result, options = {}) + result = sanitize_optional_fields(result) + @nonprofit = ::Nonprofit.new(result[:nonprofit].merge({register_np_only: true})) + @user = User.new(result[:user]) + @options = options + end + + def call + result = {} + ActiveRecord::Base.transaction do + result = if @user.save && @nonprofit.save && roles.each(&:save) + @user.confirm if @options[:confirm_admin] + {success: true, messages: ["Nonprofit #{@nonprofit.id} successfully created."]} + else + retrieve_error_messages + end + end + result + end + + private + + def retrieve_error_messages + result = {success: false, messages: []} + result = retrieve_user_error_messages(result) + result = retrieve_nonprofit_error_messages(result) + retrieve_roles_error_messages(result) + end + + def retrieve_user_error_messages(result) + @user.errors.full_messages.each { |i| result[:messages] << "Error creating user: #{i}" } + result + end + + def retrieve_nonprofit_error_messages(result) + @nonprofit.errors.full_messages.each { |i| result[:messages] << "Error creating nonprofit: #{i}" } + result + end + + def retrieve_roles_error_messages(result) + roles.each { |role| role.errors.full_messages.each { |i| result[:messages] << "Error creating role: #{i}" } } + result + end + + def roles + roles = [Role.new(host: @nonprofit, name: "nonprofit_admin", user: @user)] + roles << Role.new(host: @nonprofit, name: "super_admin", user: @user) if @options[:super_admin] + roles + end + + def sanitize_optional_fields(result) + result.transform_values! { |keys| keys.transform_values! { |value| value&.empty? ? nil : value } } + end end diff --git a/app/legacy_lib/nonprofit_metrics.rb b/app/legacy_lib/nonprofit_metrics.rb index 0e2251d4f1..8c05fde624 100644 --- a/app/legacy_lib/nonprofit_metrics.rb +++ b/app/legacy_lib/nonprofit_metrics.rb @@ -6,76 +6,76 @@ module NonprofitMetrics def self.payments(np_id) Qx.select( - '(SUM(payments.gross_amount) / 100.0)::money::text AS total', - '(AVG(payments.gross_amount) / 100.0)::money::text AS average', - '(SUM(week.gross_amount) / 100.0)::money::text AS week', - '(SUM(month.gross_amount) / 100.0)::money::text AS month', - '(SUM(year.gross_amount) / 100.0)::money::text AS year' + "(SUM(payments.gross_amount) / 100.0)::money::text AS total", + "(AVG(payments.gross_amount) / 100.0)::money::text AS average", + "(SUM(week.gross_amount) / 100.0)::money::text AS week", + "(SUM(month.gross_amount) / 100.0)::money::text AS month", + "(SUM(year.gross_amount) / 100.0)::money::text AS year" ) .from(:payments) .left_join( - ['payments week', "week.id=payments.id AND week.date > date_trunc('week', NOW())"], - ['payments month', "month.id=payments.id AND month.date > date_trunc('month', NOW())"], - ['payments year', "year.id=payments.id AND year.date > date_trunc('year', NOW())"] + ["payments week", "week.id=payments.id AND week.date > date_trunc('week', NOW())"], + ["payments month", "month.id=payments.id AND month.date > date_trunc('month', NOW())"], + ["payments year", "year.id=payments.id AND year.date > date_trunc('year', NOW())"] ) - .where('payments.nonprofit_id=$id', id: np_id) + .where("payments.nonprofit_id=$id", id: np_id) .execute.last end def self.recurring(np_id) # total, average, this month Qx.select( - '(SUM(recurring_donations.amount) / 100.0)::money::text AS total', - '(AVG(recurring_donations.amount) / 100.0)::money::text AS average', - '(SUM(month.amount) / 100.0)::money::text AS month' + "(SUM(recurring_donations.amount) / 100.0)::money::text AS total", + "(AVG(recurring_donations.amount) / 100.0)::money::text AS average", + "(SUM(month.amount) / 100.0)::money::text AS month" ) .from(:recurring_donations) - .left_join('recurring_donations month', "month.id=recurring_donations.id AND month.created_at > date_trunc('month', NOW())") - .where('recurring_donations.active=TRUE') - .and_where('recurring_donations.n_failures < 3') - .and_where('recurring_donations.nonprofit_id=$id', id: np_id) + .left_join("recurring_donations month", "month.id=recurring_donations.id AND month.created_at > date_trunc('month', NOW())") + .where("recurring_donations.active=TRUE") + .and_where("recurring_donations.n_failures < 3") + .and_where("recurring_donations.nonprofit_id=$id", id: np_id) .execute.last end def self.supporters(np_id) Qx.select( - 'COUNT(supporters) AS total', - 'COUNT(week) AS week', - 'COUNT(month) AS month' + "COUNT(supporters) AS total", + "COUNT(week) AS week", + "COUNT(month) AS month" ) .from(:supporters) - .left_join('supporters week', "week.id=supporters.id AND week.created_at > date_trunc('week', NOW()) AND week.imported_at IS NULL") - .add_left_join('supporters month', "month.id=supporters.id AND month.created_at > date_trunc('month', NOW()) AND month.imported_at IS NULL") - .where('coalesce(supporters.deleted, FALSE) = FALSE') - .and_where('supporters.nonprofit_id=$id', id: np_id) + .left_join("supporters week", "week.id=supporters.id AND week.created_at > date_trunc('week', NOW()) AND week.imported_at IS NULL") + .add_left_join("supporters month", "month.id=supporters.id AND month.created_at > date_trunc('month', NOW()) AND month.imported_at IS NULL") + .where("coalesce(supporters.deleted, FALSE) = FALSE") + .and_where("supporters.nonprofit_id=$id", id: np_id) .execute.last end def self.recent_donations(np_id) Qx.select( - '(payments.gross_amount / 100)::money::text AS amount', - 'payments.date', - 'payments.id AS payment_id', - 'supporters.name AS supporter_name', - 'supporters.email AS supporter_email' + "(payments.gross_amount / 100)::money::text AS amount", + "payments.date", + "payments.id AS payment_id", + "supporters.name AS supporter_name", + "supporters.email AS supporter_email" ) .from(:payments) - .join('supporters', 'payments.supporter_id=supporters.id') - .where('payments.nonprofit_id=$id', id: np_id) + .join("supporters", "payments.supporter_id=supporters.id") + .where("payments.nonprofit_id=$id", id: np_id) .and_where("payments.kind IN ('Donation', 'RecurringDonation', 'Ticket')") .limit(10) - .order_by('payments.date DESC') + .order_by("payments.date DESC") .execute end def self.recent_supporters(np_id) - Qx.select('name', 'email', 'id', 'created_at') + Qx.select("name", "email", "id", "created_at") .from(:supporters) - .where('supporters.nonprofit_id=$id', id: np_id) - .and_where('coalesce(supporters.deleted, FALSE) = FALSE') - .and_where('supporters.import_id IS NULL') + .where("supporters.nonprofit_id=$id", id: np_id) + .and_where("coalesce(supporters.deleted, FALSE) = FALSE") + .and_where("supporters.import_id IS NULL") .limit(10) - .order_by('supporters.created_at DESC') + .order_by("supporters.created_at DESC") .execute end @@ -88,23 +88,23 @@ def self.all_metrics(np_id) def self.published_campaigns(np_id) Qx.select( - 'campaigns.name', - 'campaigns.id', - 'campaigns.created_at', - 'campaigns.end_datetime', - 'COUNT(supporters.id) AS supporter_count', - '(SUM(one_time.amount)/ 100)::money::text AS total_one_time', - '(SUM(recurring_donations.amount)/ 100)::money::text AS total_recurring' + "campaigns.name", + "campaigns.id", + "campaigns.created_at", + "campaigns.end_datetime", + "COUNT(supporters.id) AS supporter_count", + "(SUM(one_time.amount)/ 100)::money::text AS total_one_time", + "(SUM(recurring_donations.amount)/ 100)::money::text AS total_recurring" ) .from(:campaigns) - .left_join('donations', 'donations.campaign_id=campaigns.id') - .add_left_join('donations AS one_time', 'donations.id=one_time.id AND one_time.recurring_donation_id IS NULL') - .add_left_join('recurring_donations', 'recurring_donations.donation_id=donations.id AND recurring_donations.active=TRUE') - .add_left_join('supporters', 'supporters.id=donations.supporter_id') - .group_by('campaigns.id') - .where('campaigns.nonprofit_id=$id', id: np_id) - .and_where('campaigns.published = TRUE') - .order_by('campaigns.end_datetime DESC') + .left_join("donations", "donations.campaign_id=campaigns.id") + .add_left_join("donations AS one_time", "donations.id=one_time.id AND one_time.recurring_donation_id IS NULL") + .add_left_join("recurring_donations", "recurring_donations.donation_id=donations.id AND recurring_donations.active=TRUE") + .add_left_join("supporters", "supporters.id=donations.supporter_id") + .group_by("campaigns.id") + .where("campaigns.nonprofit_id=$id", id: np_id) + .and_where("campaigns.published = TRUE") + .order_by("campaigns.end_datetime DESC") .execute end @@ -114,16 +114,16 @@ def self.published_campaigns(np_id) # each hash is nested in an outer hash, set to a key that is also the date, lol # this is used in the payment_history query to fill in missing dates in the data. def self.payment_history_timespans(params) - raise ArgumentError, 'Invalid timespan' unless %w[year month week day].include? params[:timeSpan] + raise ArgumentError, "Invalid timespan" unless %w[year month week day].include? params[:timeSpan] date_hash = {} - beginning_of = 'beginning_of_' + params[:timeSpan] + beginning_of = "beginning_of_" + params[:timeSpan] current_date = Chronic.parse(params[:startDate]).send(beginning_of) end_date = Chronic.parse(params[:endDate]).send(beginning_of) while current_date <= end_date - date = current_date.strftime('%F') - date_hash[date] = { 'time_span' => date } + date = current_date.strftime("%F") + date_hash[date] = {"time_span" => date} current_date += 1.send(params[:timeSpan]) end date_hash @@ -132,26 +132,26 @@ def self.payment_history_timespans(params) def self.payment_history(params) results = Qx.select( "to_char(date_trunc('#{params[:timeSpan]}', MAX(payments.date)), 'YYYY-MM-DD') AS time_span", - 'coalesce(SUM(payments.gross_amount), 0) AS total_cents', - 'coalesce(SUM(onetime.gross_amount ), 0) AS onetime_cents', - 'coalesce(SUM(recurring.gross_amount ), 0) AS recurring_cents', - 'coalesce(SUM(tickets.gross_amount ), 0) AS tickets_cents' + "coalesce(SUM(payments.gross_amount), 0) AS total_cents", + "coalesce(SUM(onetime.gross_amount ), 0) AS onetime_cents", + "coalesce(SUM(recurring.gross_amount ), 0) AS recurring_cents", + "coalesce(SUM(tickets.gross_amount ), 0) AS tickets_cents" ) - .from(:payments) - .left_join( - ['payments AS onetime', "onetime.id=payments.id AND onetime.kind='Donation'"], - ['payments AS recurring', "recurring.id=payments.id AND recurring.kind='RecurringDonation'"], - ['payments AS tickets', "tickets.id=payments.id AND tickets.kind='Ticket'"] - ) - .where('payments.nonprofit_id' => params[:id]) - .and_where('payments.date >= $d', d: params[:startDate]) - .and_where('payments.date <= $d', d: params[:endDate]) - .group_by("date_trunc('#{params[:timeSpan]}', payments.date)") - .order_by('MAX(payments.date)') - .execute + .from(:payments) + .left_join( + ["payments AS onetime", "onetime.id=payments.id AND onetime.kind='Donation'"], + ["payments AS recurring", "recurring.id=payments.id AND recurring.kind='RecurringDonation'"], + ["payments AS tickets", "tickets.id=payments.id AND tickets.kind='Ticket'"] + ) + .where("payments.nonprofit_id" => params[:id]) + .and_where("payments.date >= $d", d: params[:startDate]) + .and_where("payments.date <= $d", d: params[:endDate]) + .group_by("date_trunc('#{params[:timeSpan]}', payments.date)") + .order_by("MAX(payments.date)") + .execute date_hash = payment_history_timespans(params) - results.each_with_object(date_hash) { |r, acc| acc[r['time_span']] = r; }.values + results.each_with_object(date_hash) { |r, acc| acc[r["time_span"]] = r; }.values end end diff --git a/app/legacy_lib/numeric.rb b/app/legacy_lib/numeric.rb index 6da12598c2..60016645fc 100644 --- a/app/legacy_lib/numeric.rb +++ b/app/legacy_lib/numeric.rb @@ -7,7 +7,7 @@ class Numeric # @param [Integer] delta the integer offsets from zero to round down to # @return [Integer] def floor_for_delta(delta) - raise ArgumentError, 'delta must be a positive integer' unless delta.is_a?(Integer) && delta > 0 + raise ArgumentError, "delta must be a positive integer" unless delta.is_a?(Integer) && delta > 0 (self % delta).zero? ? self : ((to_i / delta)) * delta end @@ -16,7 +16,7 @@ def floor_for_delta(delta) # @param [Integer] delta the integer offsets from zero to round up to # @return [Integer] def ceil_for_delta(delta) - raise ArgumentError, 'delta must be a positive integer' unless delta.is_a?(Integer) && delta > 0 + raise ArgumentError, "delta must be a positive integer" unless delta.is_a?(Integer) && delta > 0 (self % delta).zero? ? self : ((floor.to_i / delta) + 1) * delta end diff --git a/app/legacy_lib/pay_recurring_donation.rb b/app/legacy_lib/pay_recurring_donation.rb index bb1bc84050..b66e55fec4 100644 --- a/app/legacy_lib/pay_recurring_donation.rb +++ b/app/legacy_lib/pay_recurring_donation.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'timespan' +require "timespan" module PayRecurringDonation # Pay ALL recurring donations that are currently due; each payment gets a queued delayed_job @@ -44,13 +44,13 @@ def self.pay_all_due_with_stripe # Charge an existing donation via stripe, only if it is due # Pass in an instance of an existing RecurringDonation def self.with_stripe(rd_id) - ParamValidation.new({ rd_id: rd_id }, - rd_id: { - required: true, - is_integer: true - }) + ParamValidation.new({rd_id: rd_id}, + rd_id: { + required: true, + is_integer: true + }) - rd = RecurringDonation.where('id = ?', rd_id).first + rd = RecurringDonation.where("id = ?", rd_id).first unless rd raise ParamValidation::ValidationError.new("#{rd_id} is not a valid recurring donation", key: :rd_id) @@ -58,38 +58,39 @@ def self.with_stripe(rd_id) return false unless QueryRecurringDonations.is_due?(rd_id) - donation = Donation.where('id = ?', rd['donation_id']).first + donation = Donation.where("id = ?", rd["donation_id"]).first unless donation - raise ParamValidation::ValidationError.new("#{rd['donation_id']} is not a valid donation", {}) + raise ParamValidation::ValidationError.new("#{rd["donation_id"]} is not a valid donation", {}) end - trx = nonprofit.transactions.build(amount: donation['amount']) + trx = nonprofit.transactions.build(amount: donation["amount"]) result = {} result = result.merge(InsertDonation.insert_charge( - 'card_id' => donation['card_id'], - 'recurring_donation' => true, - 'designation' => donation['designation'], - 'amount' => donation['amount'], - 'nonprofit_id' => donation['nonprofit_id'], - 'donation_id' => donation['id'], - 'supporter_id' => donation['supporter_id'], - 'old_donation' => true - )) - if result['charge']['status'] != 'failed' + "card_id" => donation["card_id"], + "recurring_donation" => true, + "designation" => donation["designation"], + "amount" => donation["amount"], + "nonprofit_id" => donation["nonprofit_id"], + "donation_id" => donation["id"], + "supporter_id" => donation["supporter_id"], + "old_donation" => true + )) + if result["charge"]["status"] != "failed" rd.update(n_failures: 0) - result['recurring_donation'] = rd + result["recurring_donation"] = rd - Houdini.event_publisher.announce(:recurring_donation_payment_succeeded, donation, donation&.supporter&.locale || 'en') + Houdini.event_publisher.announce(:recurring_donation_payment_succeeded, donation, donation&.supporter&.locale || "en") - donation = trx.donations.build(amount: donation['amount'], designation: donation['designation'], dedication: donation["dedication"], legacy_donation: donation) + donation = trx.donations.build(amount: donation["amount"], designation: donation["designation"], dedication: donation["dedication"], legacy_donation: donation) stripe_t = trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: data['amount']), - payments:[ + subtransactable: StripeTransaction.new(amount: data["amount"]), + payments: [ SubtransactionPayment.new( - paymentable: StripeCharge.new(payment: Payment.find(result['payment']['id']))) - ], - created: data['date'] - ); + paymentable: StripeCharge.new(payment: Payment.find(result["payment"]["id"])) + ) + ], + created: data["date"] + ) trx.save! donation.save! stripe_t.save! @@ -97,14 +98,14 @@ def self.with_stripe(rd_id) stripe_t.publish_created donation.publish_created trx.publish_created - InsertActivities.for_recurring_donations([result['payment']['id']]) + InsertActivities.for_recurring_donations([result["payment"]["id"]]) else rd.n_failures += 1 rd.save! - result['recurring_donation'] = rd + result["recurring_donation"] = rd Houdini.event_publisher.announce(:recurring_donation_payment_failed, donation) - InsertSupporterNotes.create({supporter:Supporter.find(donation['supporter_id']), user: User.find(540), content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}"}) + InsertSupporterNotes.create({supporter: Supporter.find(donation["supporter_id"]), user: User.find(540), content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}"}) end result end @@ -112,57 +113,57 @@ def self.with_stripe(rd_id) def self.fail_a_recurring_donation(rd, donation, notify_nonprofit = false) recurring_donation = Psql.execute( Qexpr.new.update(:recurring_donations, n_failures: 3) - .where('id=$id', id: rd['id']).returning('*') + .where("id=$id", id: rd["id"]).returning("*") ).first - FailedRecurringDonationPaymentDonorEmailJob.perform_later Donation.find(rd['donation_id']) + FailedRecurringDonationPaymentDonorEmailJob.perform_later Donation.find(rd["donation_id"]) if notify_nonprofit - FailedRecurringDonationPaymentNonprofitEmailJob.perform_later Donation.find(rd['donation_id']) + FailedRecurringDonationPaymentNonprofitEmailJob.perform_later Donation.find(rd["donation_id"]) end - InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd['id']}", supporter_id: donation['supporter_id'], user_id: 540 }]) + InsertSupporterNotes.create([{content: "This supporter had a payment failure for their recurring donation with ID #{rd["id"]}", supporter_id: donation["supporter_id"], user_id: 540}]) recurring_donation end # Charge an existing donation via stripe, NO MATTER WHAT # Pass in an instance of an existing RecurringDonation - def self.with_stripe_BUT_NO_MATTER_WHAT(rd_id, enter_todays_date, run_this = false, set_this_true = false, this_one_needs_to_be_false = true, is_this_run_dangerously = 'no') + def self.with_stripe_BUT_NO_MATTER_WHAT(rd_id, enter_todays_date, run_this = false, set_this_true = false, this_one_needs_to_be_false = true, is_this_run_dangerously = "no") if PayRecurringDonation::ULTIMATE_VERIFICATION(enter_todays_date, run_this, set_this_true, this_one_needs_to_be_false, is_this_run_dangerously) rd = Psql.execute("SELECT * FROM recurring_donations WHERE id=#{rd_id}").first - donation = Psql.execute("SELECT * FROM donations WHERE id=#{rd['donation_id']}").first + donation = Psql.execute("SELECT * FROM donations WHERE id=#{rd["donation_id"]}").first result = {} result = result.merge(InsertDonation.insert_charge( - 'card_id' => donation['card_id'], - 'recurring_donation' => true, - 'designation' => donation['designation'], - 'amount' => donation['amount'], - 'nonprofit_id' => donation['nonprofit_id'], - 'donation_id' => donation['id'], - 'supporter_id' => donation['supporter_id'] - )) - if result['charge']['status'] != 'failed' - result['recurring_donation'] = Psql.execute( + "card_id" => donation["card_id"], + "recurring_donation" => true, + "designation" => donation["designation"], + "amount" => donation["amount"], + "nonprofit_id" => donation["nonprofit_id"], + "donation_id" => donation["id"], + "supporter_id" => donation["supporter_id"] + )) + if result["charge"]["status"] != "failed" + result["recurring_donation"] = Psql.execute( Qexpr.new.update(:recurring_donations, n_failures: 0) - .where('id=$id', id: rd_id).returning('*') + .where("id=$id", id: rd_id).returning("*") ).first ## add PaymentNotificationJobHere - InsertActivities.for_recurring_donations([result['payment']['id']]) + InsertActivities.for_recurring_donations([result["payment"]["id"]]) else - result['recurring_donation'] = Psql.execute( - Qexpr.new.update(:recurring_donations, n_failures: rd['n_failures'] + 1) - .where('id=$id', id: rd_id).returning('*') + result["recurring_donation"] = Psql.execute( + Qexpr.new.update(:recurring_donations, n_failures: rd["n_failures"] + 1) + .where("id=$id", id: rd_id).returning("*") ).first - FailedRecurringDonationPaymentDonorEmailJob.perform_later Donation.find(rd['donation_id']) - if rd['n_failures'] >= 3 - FailedRecurringDonationPaymentNonprofitEmailJob.perform_later Donation.find(rd['donation_id']) + FailedRecurringDonationPaymentDonorEmailJob.perform_later Donation.find(rd["donation_id"]) + if rd["n_failures"] >= 3 + FailedRecurringDonationPaymentNonprofitEmailJob.perform_later Donation.find(rd["donation_id"]) end - InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540 }]) + InsertSupporterNotes.create([{content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation["supporter_id"], user_id: 540}]) end return result end false end - def self.ULTIMATE_VERIFICATION(enter_todays_date, run_this = false, set_this_true = false, this_one_needs_to_be_false = true, is_this_run_dangerously = 'no') - (Date.parse(enter_todays_date) == Date.today && run_this && set_this_true && !this_one_needs_to_be_false && is_this_run_dangerously == 'run dangerously') + def self.ULTIMATE_VERIFICATION(enter_todays_date, run_this = false, set_this_true = false, this_one_needs_to_be_false = true, is_this_run_dangerously = "no") + Date.parse(enter_todays_date) == Date.today && run_this && set_this_true && !this_one_needs_to_be_false && is_this_run_dangerously == "run dangerously" end end diff --git a/app/legacy_lib/psql.rb b/app/legacy_lib/psql.rb index 62ed6e3147..1f6c1c21e9 100644 --- a/app/legacy_lib/psql.rb +++ b/app/legacy_lib/psql.rb @@ -5,23 +5,23 @@ # Some convenience wrappers around the postgresql gem, allowing us to avoid activerecord dependency # combine usage of this library with Qexpr -require 'colorize' +require "colorize" # Initialize the database connection module Psql # Execute a sql statement (string) def self.execute(statement) - puts statement if ENV['RAILS_ENV'] != 'production' && ENV['RAILS_LOG_LEVEL'] == 'debug' # log to STDOUT on dev/staging + puts statement if ENV["RAILS_ENV"] != "production" && ENV["RAILS_LOG_LEVEL"] == "debug" # log to STDOUT on dev/staging Qx.execute_raw(raw_expr_str(statement)) end # A variation of execute that returns a vector of vectors rather than a vector of hashes # Useful and faster for creating CSV's def self.execute_vectors(statement) - puts statement if ENV['RAILS_ENV'] != 'production' && ENV['RAILS_LOG_LEVEL'] == 'debug' # log to STDOUT on dev/staging - raw_str = statement.to_s.uncolorize.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') - Qx.execute_raw(raw_expr_str(statement), format: 'csv') + puts statement if ENV["RAILS_ENV"] != "production" && ENV["RAILS_LOG_LEVEL"] == "debug" # log to STDOUT on dev/staging + statement.to_s.uncolorize.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "") + Qx.execute_raw(raw_expr_str(statement), format: "csv") end def self.transaction(&block) @@ -34,6 +34,6 @@ def self.transaction(&block) # Raw expression string def self.raw_expr_str(statement) - statement.to_s.uncolorize.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') + statement.to_s.uncolorize.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "") end end diff --git a/app/legacy_lib/qexpr.rb b/app/legacy_lib/qexpr.rb index 48edba0934..8c19f4b32a 100644 --- a/app/legacy_lib/qexpr.rb +++ b/app/legacy_lib/qexpr.rb @@ -11,8 +11,8 @@ # - composability and reusability of sql fragments # - pretty printing of sql with formatting and color -require 'hamster' -require 'colorize' +require "hamster" +require "colorize" class Qexpr attr_accessor :tree @@ -27,25 +27,24 @@ def to_s # Parse an qexpr object into a sql string expression def parse - expr = '' if @tree[:insert] expr = "#{@tree[:insert]} #{@tree[:values].blue}" - expr += "\nRETURNING ".bold.light_blue + (@tree[:returning] || ['id']).join(', ').blue + expr += "\nRETURNING ".bold.light_blue + (@tree[:returning] || ["id"]).join(", ").blue return expr end # Query-based expessions expr = @tree[:update] || @tree[:delete_from] || @tree[:select] if expr.nil? || expr.empty? - raise ArgumentError, 'Must have a select, update, or delete clause' + raise ArgumentError, "Must have a select, update, or delete clause" end if @tree[:from] expr += "\nFROM".bold.light_blue + @tree[:from].map do |f| f.is_a?(String) ? f : " (#{f[:sub_expr].parse}\n) AS #{f[:as]}" - end.join(', ').blue + end.join(", ").blue end - expr += @tree[:joins].join(' ') if @tree[:joins] + expr += @tree[:joins].join(" ") if @tree[:joins] expr += @tree[:where] if @tree[:where] expr += @tree[:group_by] if @tree[:group_by] expr += @tree[:having] if @tree[:having] @@ -55,7 +54,7 @@ def parse expr = "(#{expr}) AS #{@tree[:as]}" if @tree[:select] && @tree[:as] if @tree[:update] && @tree[:returning] - expr += "\nRETURNING ".bold.light_blue + @tree[:returning].join(', ').blue + expr += "\nRETURNING ".bold.light_blue + @tree[:returning].join(", ").blue end expr end @@ -70,34 +69,34 @@ def insert(table_name, arr, options = {}) arr = arr.map { |h| h.sort.to_h } # Make sure all key/vals are ordered the same way keys = arr.first.keys keys = keys.concat(options[:common_data].keys) if options[:common_data] - keys = keys.map { |k| "\"#{k}\"" }.join(', ') - ts_columns = options[:no_timestamps] ? '' : 'created_at, updated_at, ' - ts_values = options[:no_timestamps] ? '' : "#{Qexpr.now}, #{Qexpr.now}, " + keys = keys.map { |k| "\"#{k}\"" }.join(", ") + ts_columns = options[:no_timestamps] ? "" : "created_at, updated_at, " + ts_values = options[:no_timestamps] ? "" : "#{Qexpr.now}, #{Qexpr.now}, " common_vals = options[:common_data] ? options[:common_data].values.map { |v| Qexpr.quote(v) } : [] - vals = arr.map { |h| '(' + ts_values + h.values.map { |v| Qexpr.quote(v) }.concat(common_vals).join(',') + ')' }.join(',') + vals = arr.map { |h| "(" + ts_values + h.values.map { |v| Qexpr.quote(v) }.concat(common_vals).join(",") + ")" }.join(",") Qexpr.new @tree - .put(:insert, 'INSERT INTO'.bold.light_blue + " #{table_name} (#{ts_columns} #{keys})".blue) + .put(:insert, "INSERT INTO".bold.light_blue + " #{table_name} (#{ts_columns} #{keys})".blue) .put(:values, "\nVALUES".bold.light_blue + " #{vals}".blue) end def update(table_name, settings, _os = {}) - Qexpr.new @tree.put(:update, 'UPDATE'.bold.light_blue + " #{table_name}".blue + "\nSET".bold.light_blue + " #{settings.map { |key, val| "#{key}=#{Qexpr.quote(val)}" }.join(', ')}".blue) + Qexpr.new @tree.put(:update, "UPDATE".bold.light_blue + " #{table_name}".blue + "\nSET".bold.light_blue + " #{settings.map { |key, val| "#{key}=#{Qexpr.quote(val)}" }.join(", ")}".blue) end def delete_from(table_name) - Qexpr.new @tree.put(:delete_from, 'DELETE FROM'.bold.light_blue + " #{table_name}".blue) + Qexpr.new @tree.put(:delete_from, "DELETE FROM".bold.light_blue + " #{table_name}".blue) end # Create or append select columns def select(*cols) if @tree[:select] - Qexpr.new @tree.put(:select, @tree[:select] + ", #{cols.join(', ')}".blue) + Qexpr.new @tree.put(:select, @tree[:select] + ", #{cols.join(", ")}".blue) else cols = if cols.count < 4 - " #{cols.join(', ')}" - else - "\n #{cols.join("\n, ")}" - end + " #{cols.join(", ")}" + else + "\n #{cols.join("\n, ")}" + end Qexpr.new @tree.put(:select, "\nSELECT".bold.light_blue + cols.to_s.blue) end end @@ -107,7 +106,7 @@ def select_distinct(*cols) end def select_distinct_on(cols_distinct, cols_select) - Qexpr.new @tree.put(:select, 'SELECT DISTINCT ON'.bold.light_blue + " (#{Array(cols_distinct).join(', ')})\n #{Array(cols_select).join("\n, ")}".blue) + Qexpr.new @tree.put(:select, "SELECT DISTINCT ON".bold.light_blue + " (#{Array(cols_distinct).join(", ")})\n #{Array(cols_select).join("\n, ")}".blue) end def from(expr, as = nil) @@ -115,7 +114,7 @@ def from(expr, as = nil) end def group_by(*cols) - Qexpr.new @tree.put(:group_by, "\nGROUP BY".bold.light_blue + " #{cols.join(', ')}".blue) + Qexpr.new @tree.put(:group_by, "\nGROUP BY".bold.light_blue + " #{cols.join(", ")}".blue) end def order_by(expr) @@ -133,25 +132,25 @@ def offset(i) def join(table_name, on_expr, data = {}) on_expr = Qexpr.interpolate_expr(on_expr, data) Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nJOIN".bold.light_blue + " #{table_name}\n ".blue + 'ON'.bold.light_blue + " #{on_expr}".blue)) + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nJOIN".bold.light_blue + " #{table_name}\n ".blue + "ON".bold.light_blue + " #{on_expr}".blue)) end def inner_join(table_name, on_expr, data = {}) on_expr = Qexpr.interpolate_expr(on_expr, data) Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nINNER JOIN".bold.light_blue + " #{table_name}\n ".blue + 'ON'.bold.light_blue + " #{on_expr}".blue)) + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nINNER JOIN".bold.light_blue + " #{table_name}\n ".blue + "ON".bold.light_blue + " #{on_expr}".blue)) end def left_outer_join(table_name, on_expr, data = {}) on_expr = Qexpr.interpolate_expr(on_expr, data) Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nLEFT OUTER JOIN".bold.light_blue + " #{table_name}\n ".blue + 'ON'.bold.light_blue + " #{on_expr}".blue)) + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nLEFT OUTER JOIN".bold.light_blue + " #{table_name}\n ".blue + "ON".bold.light_blue + " #{on_expr}".blue)) end def join_lateral(join_name, select_statement, success_condition = true, data = {}) select_statement = Qexpr.interpolate_expr(select_statement, data) Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\n JOIN LATERAL".bold.light_blue + " (#{select_statement})\n #{join_name} ".blue + 'ON'.bold.light_blue + " #{success_condition}".blue)) + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\n JOIN LATERAL".bold.light_blue + " (#{select_statement})\n #{join_name} ".blue + "ON".bold.light_blue + " #{success_condition}".blue)) end def as(name) @@ -198,18 +197,18 @@ def self.quote(val) if val.is_a?(Integer) || (val.is_a?(String) && val =~ /^\$Q\$.+\$Q\$$/) # is a valid num or already quoted val elsif val.nil? - 'NULL' + "NULL" elsif !!val == val # is a boolean val ? "'t'" : "'f'" else - '$Q$' + val.to_s + '$Q$' + "$Q$" + val.to_s + "$Q$" end end # An alias of PG.quote_ident, for convenience sake # Double-quotes sql identifiers def self.quote_ident(str) - str.split('.').map { |s| "\"#{s}\"" }.join('.') + str.split(".").map { |s| "\"#{s}\"" }.join(".") end # sql-quoted datetime value useful for created_at and updated_at columns @@ -241,9 +240,9 @@ def self.remaining_count(total_count, page_length, current_page = 1) # interpolate the hash data into the expression def self.interpolate_expr(expr, data) expr.gsub(/\$\w+/) do |match| - val = data[match.gsub(/[ \$]*/, '').to_sym] + val = data[match.gsub(/[ \$]*/, "").to_sym] if val.is_a?(Array) || val.is_a?(Hamster::Vector) - val.to_a.map { |x| Qexpr.quote(x) }.join(', ') + val.to_a.map { |x| Qexpr.quote(x) }.join(", ") else Qexpr.quote val end @@ -259,7 +258,7 @@ def self.from_expr(expr, as) if expr.is_a?(Qexpr) Hamster::Hash[sub_expr: expr, as: as] else - " #{expr} #{as ? "AS #{as}" : ''}" + " #{expr} #{as ? "AS #{as}" : ""}" end end end diff --git a/app/legacy_lib/qexpr_query_chunker.rb b/app/legacy_lib/qexpr_query_chunker.rb index 95db0b590d..fa82a1263b 100644 --- a/app/legacy_lib/qexpr_query_chunker.rb +++ b/app/legacy_lib/qexpr_query_chunker.rb @@ -44,7 +44,7 @@ def self.for_export_enumerable(chunk_limit = 35_000, &block) offset = Qexpr.page_offset(limit, page) export_returned = block.call(offset, limit, page > 1).to_a # we got the titles too if on_first, let's skip one row - last_export_length = page == 1 ? export_returned.length - 1 : export_returned.length + last_export_length = (page == 1) ? export_returned.length - 1 : export_returned.length # efficient? no. Do we care? eh. export_returned.each do |i| y << i diff --git a/app/legacy_lib/query_activities.rb b/app/legacy_lib/query_activities.rb index 0372efe469..efe1dbf8c1 100644 --- a/app/legacy_lib/query_activities.rb +++ b/app/legacy_lib/query_activities.rb @@ -5,10 +5,10 @@ module QueryActivities def self.for_timeline(nonprofit_id, supporter_id) - Qx.select('activities.*') + Qx.select("activities.*") .from(:activities) .where("activities.supporter_id = #{supporter_id.to_i} AND activities.nonprofit_id = #{nonprofit_id.to_i}") - .order_by('activities.date DESC') + .order_by("activities.date DESC") .execute end end diff --git a/app/legacy_lib/query_campaign_gifts.rb b/app/legacy_lib/query_campaign_gifts.rb index f2b3ff79d7..f1db4609db 100644 --- a/app/legacy_lib/query_campaign_gifts.rb +++ b/app/legacy_lib/query_campaign_gifts.rb @@ -4,8 +4,6 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # Query code for both campaign_gift_options and campaign_gifts - - module QueryCampaignGifts # Create a mapping of: { # 'total_donations' => Integer, # total donations for gift options @@ -38,10 +36,10 @@ def self.report_metrics(campaign_id) end def self.donations_for_campaign(campaign_id) - Qx.select('donations.id, donations.amount').from(:donations).where('campaign_id IN ($ids)', ids: QueryCampaigns.get_campaign_and_children(campaign_id)) + Qx.select("donations.id, donations.amount").from(:donations).where("campaign_id IN ($ids)", ids: QueryCampaigns.get_campaign_and_children(campaign_id)) end - def self.get_corresponding_payments(campaign_id, recurring_clauses, where_clauses = '') + def self.get_corresponding_payments(campaign_id, recurring_clauses, where_clauses = "") %(SELECT donations.id, payments.gross_amount AS amount FROM (#{donations_for_campaign(campaign_id).parse}) donations #{recurring_clauses} diff --git a/app/legacy_lib/query_campaign_metrics.rb b/app/legacy_lib/query_campaign_metrics.rb index 0304b7be60..0ef5093f64 100644 --- a/app/legacy_lib/query_campaign_metrics.rb +++ b/app/legacy_lib/query_campaign_metrics.rb @@ -7,24 +7,24 @@ def self.on_donations(campaign_id) campaign = Campaign.find(campaign_id) result = Psql.execute( - Qexpr.new.select('COALESCE(COUNT(DISTINCT donations.id), 0) AS supporters_count', - 'COALESCE(SUM(payments.gross_amount), 0) AS total_raised') - .from('campaigns') + Qexpr.new.select("COALESCE(COUNT(DISTINCT donations.id), 0) AS supporters_count", + "COALESCE(SUM(payments.gross_amount), 0) AS total_raised") + .from("campaigns") .join( - 'donations', 'donations.campaign_id=campaigns.id' + "donations", "donations.campaign_id=campaigns.id" ) - .join_lateral('payments', QueryDonations.get_first_payment_for_donation.parse, true) + .join_lateral("payments", QueryDonations.get_first_payment_for_donation.parse, true) .where("campaigns.id IN (#{QueryCampaigns .get_campaign_and_children(campaign_id) .parse})") ).last { - 'supporters_count' => result['supporters_count'], - 'total_raised' => result['total_raised'], - 'goal_amount' => campaign.goal_amount, - 'show_total_count' => campaign.show_total_count, - 'show_total_raised' => campaign.show_total_raised + "supporters_count" => result["supporters_count"], + "total_raised" => result["total_raised"], + "goal_amount" => campaign.goal_amount, + "show_total_count" => campaign.show_total_count, + "show_total_raised" => campaign.show_total_raised } end end diff --git a/app/legacy_lib/query_campaigns.rb b/app/legacy_lib/query_campaigns.rb index d8ebb909b1..190cd7d192 100644 --- a/app/legacy_lib/query_campaigns.rb +++ b/app/legacy_lib/query_campaigns.rb @@ -6,78 +6,77 @@ module QueryCampaigns def self.featured(limit, gross_more_than) expr = Qexpr.new.select( - 'campaigns.name', - 'campaigns.summary', - 'campaigns.gross', - Image._url('campaigns', 'main_image', 'normal') + 'AS main_image_url', + "campaigns.name", + "campaigns.summary", + "campaigns.gross", + Image._url("campaigns", "main_image", "normal") + "AS main_image_url", "concat('/nonprofits/', campaigns.nonprofit_id, '/campaigns/', campaigns.id) AS url" ).from( - Qexpr.new.select('campaigns.*', 'SUM(donations.amount) AS gross') - .from('campaigns') - .join('donations', 'donations.campaign_id=campaigns.id') - .group_by('campaigns.id'), - 'campaigns' + Qexpr.new.select("campaigns.*", "SUM(donations.amount) AS gross") + .from("campaigns") + .join("donations", "donations.campaign_id=campaigns.id") + .group_by("campaigns.id"), + "campaigns" ).where("campaigns.gross > $amount AND campaigns.published='t' AND campaigns.nonprofit_id!=$id", amount: gross_more_than, id: 4182) - .order_by('campaigns.updated_at ASC') - .limit(limit) + .order_by("campaigns.updated_at ASC") + .limit(limit) Psql.execute(expr.parse) end def self.timeline(campaign_id) ex = QueryCampaigns.payments_expression(campaign_id, true) - ex.group_by('DATE(payments.date)') - .order_by('DATE(payments.date)') + ex.group_by("DATE(payments.date)") + .order_by("DATE(payments.date)") .execute end def self.payments_expression(campaign_id, for_timeline) selects = [ - 'coalesce(SUM(payments.gross_amount), 0) AS total_cents', - 'coalesce(SUM(recurring.gross_amount), 0) AS recurring_cents', - 'coalesce(SUM(offsite.gross_amount), 0) AS offsite_cents', - 'coalesce(SUM(onetime.gross_amount), 0) AS onetime_cents' + "coalesce(SUM(payments.gross_amount), 0) AS total_cents", + "coalesce(SUM(recurring.gross_amount), 0) AS recurring_cents", + "coalesce(SUM(offsite.gross_amount), 0) AS offsite_cents", + "coalesce(SUM(onetime.gross_amount), 0) AS onetime_cents" ] for_timeline ? - selects.push('MAX(DATE(payments.date)) AS date') : - selects.push('coalesce(count(supporters.id), 0) AS supporters_count') + selects.push("MAX(DATE(payments.date)) AS date") : + selects.push("coalesce(count(supporters.id), 0) AS supporters_count") Qx.select(*selects) - .from('payments') + .from("payments") .left_join( - ['donations', 'payments.donation_id=donations.id'], - ['payments AS onetime', "onetime.id=payments.id AND onetime.kind='Donation'"], - ['payments AS offsite', "offsite.id=payments.id AND offsite.kind='OffsitePayment'"], - ['payments AS recurring', "recurring.id=payments.id AND recurring.kind='RecurringDonation'"] + ["donations", "payments.donation_id=donations.id"], + ["payments AS onetime", "onetime.id=payments.id AND onetime.kind='Donation'"], + ["payments AS offsite", "offsite.id=payments.id AND offsite.kind='OffsitePayment'"], + ["payments AS recurring", "recurring.id=payments.id AND recurring.kind='RecurringDonation'"] ) .where("donations.campaign_id IN (#{QueryCampaigns.get_campaign_and_children(campaign_id).parse})") end def self.totals(campaign_id) ex = QueryCampaigns.payments_expression(campaign_id, false) - ex.add_left_join(['supporters', 'donations.supporter_id=supporters.id']) + ex.add_left_join(["supporters", "donations.supporter_id=supporters.id"]) .execute.first end def self.name_and_id(npo_id) np = Nonprofit.find(npo_id) - campaigns = np.campaigns.not_deleted.includes(:profile).order('campaigns.name ASC') - output = campaigns.map do |i| + campaigns = np.campaigns.not_deleted.includes(:profile).order("campaigns.name ASC") + campaigns.map do |i| { - 'name' => i.name, - 'id' => i.id, - 'isChildCampaign' => i.child_campaign?, - 'creator' => i.profile&.name || "user ##{i.profile.id}" + "name" => i.name, + "id" => i.id, + "isChildCampaign" => i.child_campaign?, + "creator" => i.profile&.name || "user ##{i.profile.id}" } end - output end def self.get_campaign_and_children(campaign_id) - Qx.select('id') - .from('campaigns') - .where('campaigns.id = $id OR campaigns.parent_campaign_id=$id', - id: campaign_id) + Qx.select("id") + .from("campaigns") + .where("campaigns.id = $id OR campaigns.parent_campaign_id=$id", + id: campaign_id) end end diff --git a/app/legacy_lib/query_custom_fields.rb b/app/legacy_lib/query_custom_fields.rb index 557e0bb2b2..3f8207f7ba 100644 --- a/app/legacy_lib/query_custom_fields.rb +++ b/app/legacy_lib/query_custom_fields.rb @@ -7,12 +7,12 @@ module QueryCustomFields # Find all duplicate custom field joins on supporters # Returns an array of groups of duplicate custom_field_join_ids def self.find_dupes(np_id) - Qx.select('ARRAY_AGG(custom_field_joins.id)') + Qx.select("ARRAY_AGG(custom_field_joins.id)") .from(:custom_field_joins) - .join(:custom_field_definitions, 'custom_field_definitions.id=custom_field_joins.custom_field_definition_id') - .where('custom_field_definitions.nonprofit_id=$id', id: np_id) - .group_by('custom_field_joins.custom_field_definition_id', 'custom_field_joins.value', 'custom_field_joins.supporter_id') - .having('COUNT(custom_field_joins.id) > 1') - .execute(format: 'csv')[1..-1] + .join(:custom_field_definitions, "custom_field_definitions.id=custom_field_joins.custom_field_definition_id") + .where("custom_field_definitions.nonprofit_id=$id", id: np_id) + .group_by("custom_field_joins.custom_field_definition_id", "custom_field_joins.value", "custom_field_joins.supporter_id") + .having("COUNT(custom_field_joins.id) > 1") + .execute(format: "csv")[1..-1] end end diff --git a/app/legacy_lib/query_donations.rb b/app/legacy_lib/query_donations.rb index 1a07313385..393bb2cfdd 100644 --- a/app/legacy_lib/query_donations.rb +++ b/app/legacy_lib/query_donations.rb @@ -10,53 +10,53 @@ def self.campaign_export(campaign_id) result = Psql.execute_vectors( Qexpr.new.select([ - 'donations.created_at', - 'payments.gross_amount AS amount', - 'COUNT(recurring_donations.id) > 0 AS recurring', + "donations.created_at", + "payments.gross_amount AS amount", + "COUNT(recurring_donations.id) > 0 AS recurring", "STRING_AGG(campaign_gift_options.name, ',') AS campaign_gift_names" ].concat(QuerySupporters.supporter_export_selections) .concat([ - 'supporters.id AS "Supporter ID"' - ]).concat([ - "coalesce(donations.designation, 'None') AS designation", - "#{QueryPayments.get_dedication_or_empty('type')}::text AS \"Dedication Type\"", - "#{QueryPayments.get_dedication_or_empty('name')}::text AS \"Dedicated To: Name\"", - "#{QueryPayments.get_dedication_or_empty('supporter_id')}::text AS \"Dedicated To: Supporter ID\"", - "#{QueryPayments.get_dedication_or_empty('contact', 'email')}::text AS \"Dedicated To: Email\"", - "#{QueryPayments.get_dedication_or_empty('contact', 'phone')}::text AS \"Dedicated To: Phone\"", - "#{QueryPayments.get_dedication_or_empty('contact', 'address')}::text AS \"Dedicated To: Address\"", - "#{QueryPayments.get_dedication_or_empty('note')}::text AS \"Dedicated To: Note\"", - 'donations.campaign_id AS "Campaign Id"', - 'users.email AS "Campaign Creator Email"' - ])).from(:donations) - .join(:supporters, 'supporters.id=donations.supporter_id') - .left_outer_join(:campaign_gifts, 'campaign_gifts.donation_id=donations.id') - .left_outer_join(:campaign_gift_options, 'campaign_gift_options.id=campaign_gifts.campaign_gift_option_id') - .left_outer_join(:recurring_donations, 'recurring_donations.donation_id = donations.id') + 'supporters.id AS "Supporter ID"' + ]).concat([ + "coalesce(donations.designation, 'None') AS designation", + "#{QueryPayments.get_dedication_or_empty("type")}::text AS \"Dedication Type\"", + "#{QueryPayments.get_dedication_or_empty("name")}::text AS \"Dedicated To: Name\"", + "#{QueryPayments.get_dedication_or_empty("supporter_id")}::text AS \"Dedicated To: Supporter ID\"", + "#{QueryPayments.get_dedication_or_empty("contact", "email")}::text AS \"Dedicated To: Email\"", + "#{QueryPayments.get_dedication_or_empty("contact", "phone")}::text AS \"Dedicated To: Phone\"", + "#{QueryPayments.get_dedication_or_empty("contact", "address")}::text AS \"Dedicated To: Address\"", + "#{QueryPayments.get_dedication_or_empty("note")}::text AS \"Dedicated To: Note\"", + 'donations.campaign_id AS "Campaign Id"', + 'users.email AS "Campaign Creator Email"' + ])).from(:donations) + .join(:supporters, "supporters.id=donations.supporter_id") + .left_outer_join(:campaign_gifts, "campaign_gifts.donation_id=donations.id") + .left_outer_join(:campaign_gift_options, "campaign_gift_options.id=campaign_gifts.campaign_gift_option_id") + .left_outer_join(:recurring_donations, "recurring_donations.donation_id = donations.id") .join_lateral(:payments, - get_first_payment_for_donation.parse, true) - .join(Qx.select('id, profile_id').from('campaigns') + get_first_payment_for_donation.parse, true) + .join(Qx.select("id, profile_id").from("campaigns") .where("id IN (#{QueryCampaigns .get_campaign_and_children(campaign_id) - .parse})").as('campaigns').parse, - 'donations.campaign_id=campaigns.id') - .join(Qx.select('users.id, profiles.id AS profiles_id, users.email') - .from('users') - .add_join('profiles', 'profiles.user_id = users.id') - .as('users').parse, 'users.profiles_id=campaigns.profile_id') - .group_by('donations.id', 'supporters.id', 'payments.id', 'payments.gross_amount', 'users.email') - .order_by('donations.date') + .parse})").as("campaigns").parse, + "donations.campaign_id=campaigns.id") + .join(Qx.select("users.id, profiles.id AS profiles_id, users.email") + .from("users") + .add_join("profiles", "profiles.user_id = users.id") + .as("users").parse, "users.profiles_id=campaigns.profile_id") + .group_by("donations.id", "supporters.id", "payments.id", "payments.gross_amount", "users.email") + .order_by("donations.date") ) result.map { |r| update_amount_with_currency(r, currency) } end def self.for_campaign_activities(id) - QueryDonations.activities_expression(['donations.recurring']) - .where("donations.campaign_id IN (#{QueryCampaigns + QueryDonations.activities_expression(["donations.recurring"]) + .where("donations.campaign_id IN (#{QueryCampaigns .get_campaign_and_children(id) .parse})") - .execute + .execute end def self.activities_expression(additional_selects) @@ -69,40 +69,40 @@ def self.activities_expression(additional_selects) THEN 'A supporter' ELSE supporters.name END AS supporter_name", - '(donations.amount / 100.0)::money::text as amount', - 'donations.date'] + (additional_selects || []) + "(donations.amount / 100.0)::money::text as amount", + "donations.date"] + (additional_selects || []) - Qx.select(selects.join(',')) + Qx.select(selects.join(",")) .from(:donations) - .left_join(:supporters, 'donations.supporter_id=supporters.id') - .order_by('donations.date desc') + .left_join(:supporters, "donations.supporter_id=supporters.id") + .order_by("donations.date desc") .limit(15) end # Return an array of groups of offsite donation payment_ids that exactly match on nonprofit_id, supporter_id, amount, and date # !!! Note this returns the PAYMENT_IDS for each offsite donation def self.dupe_offsite_donations(np_id) - payment_ids = Psql.execute_vectors( - Qexpr.new.select('ARRAY_AGG(payments.id) AS ids') - .from('donations') - .join(:offsite_payments, 'offsite_payments.donation_id=donations.id') - .join(:payments, 'payments.donation_id=donations.id') - .where('donations.nonprofit_id=$id', id: np_id) - .group_by('donations.supporter_id', 'donations.amount', 'donations.date') - .having('COUNT(donations.id) > 1') + Psql.execute_vectors( + Qexpr.new.select("ARRAY_AGG(payments.id) AS ids") + .from("donations") + .join(:offsite_payments, "offsite_payments.donation_id=donations.id") + .join(:payments, "payments.donation_id=donations.id") + .where("donations.nonprofit_id=$id", id: np_id) + .group_by("donations.supporter_id", "donations.amount", "donations.date") + .having("COUNT(donations.id) > 1") )[1..-1].map(&:flatten) end - def self.get_first_payment_for_donation(table_selector = 'donations') - Qx.select('payments.id, payments.gross_amount').from(:payments) + def self.get_first_payment_for_donation(table_selector = "donations") + Qx.select("payments.id, payments.gross_amount").from(:payments) .where("payments.donation_id = #{table_selector}.id") - .order_by('payments.created_at ASC') + .order_by("payments.created_at ASC") .limit(1) end def self.update_amount_with_currency(query_row, currency) # Skip header row - if query_row[1].to_s.downcase != 'amount' + if query_row[1].to_s.downcase != "amount" query_row[1] = Format::Currency.print_currency(query_row[1], currency, true, true) end query_row diff --git a/app/legacy_lib/query_email_settings.rb b/app/legacy_lib/query_email_settings.rb index ce85092738..d89f79488f 100644 --- a/app/legacy_lib/query_email_settings.rb +++ b/app/legacy_lib/query_email_settings.rb @@ -19,9 +19,9 @@ def self.fetch(np_id, user_id) SELECT column_name FROM information_schema.columns WHERE table_name='email_settings' - )).map { |h| h['column_name'] } - .reject { |name| %w[id nonprofit_id user_id].include?(name) } - .each_with_object({}) { |name, h| h[name] = true; } + )).map { |h| h["column_name"] } + .reject { |name| %w[id nonprofit_id user_id].include?(name) } + .each_with_object({}) { |name, h| h[name] = true } end es end diff --git a/app/legacy_lib/query_event_discounts.rb b/app/legacy_lib/query_event_discounts.rb index dace9606d9..2ab95b48a0 100644 --- a/app/legacy_lib/query_event_discounts.rb +++ b/app/legacy_lib/query_event_discounts.rb @@ -6,11 +6,11 @@ module QueryEventDiscounts def self.with_event_ids(event_ids) return [] if event_ids.empty? - x = Psql.execute( - Qexpr.new.select('name', 'id', 'percent', 'code', 'created_at') - .from('event_discounts') - .where('event_discounts.event_id IN ($ids)', ids: event_ids) - .order_by('created_at DESC') - ).map { |h| HashWithIndifferentAccess.new(h) } - end + Psql.execute( + Qexpr.new.select("name", "id", "percent", "code", "created_at") + .from("event_discounts") + .where("event_discounts.event_id IN ($ids)", ids: event_ids) + .order_by("created_at DESC") + ).map { |h| ActiveSupport::HashWithIndifferentAccess.new(h) } + end end diff --git a/app/legacy_lib/query_event_metrics.rb b/app/legacy_lib/query_event_metrics.rb index ea566e3f0d..5f80a07a02 100644 --- a/app/legacy_lib/query_event_metrics.rb +++ b/app/legacy_lib/query_event_metrics.rb @@ -5,84 +5,84 @@ module QueryEventMetrics def self.expression(additional_selects = []) selects = [ - 'coalesce(tickets.total, 0) AS total_attendees', - 'coalesce(tickets.checked_in_count, 0) AS checked_in_count', - 'coalesce(ticket_payments.total_paid, 0) AS tickets_total_paid', - 'coalesce(donations.payment_total, 0) AS donations_total_paid', - 'coalesce(ticket_payments.total_paid, 0) + coalesce(donations.payment_total, 0) AS total_paid' + "coalesce(tickets.total, 0) AS total_attendees", + "coalesce(tickets.checked_in_count, 0) AS checked_in_count", + "coalesce(ticket_payments.total_paid, 0) AS tickets_total_paid", + "coalesce(donations.payment_total, 0) AS donations_total_paid", + "coalesce(ticket_payments.total_paid, 0) + coalesce(donations.payment_total, 0) AS total_paid" ] - tickets_sub = Qx.select('event_id', 'SUM(quantity) AS total', 'SUM(tickets.checked_in::int) AS checked_in_count') - .from('tickets') - .group_by('event_id') - .as('tickets') + tickets_sub = Qx.select("event_id", "SUM(quantity) AS total", "SUM(tickets.checked_in::int) AS checked_in_count") + .from("tickets") + .group_by("event_id") + .as("tickets") - ticket_payments_subquery = Qx.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') + ticket_payments_subquery = Qx.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") - ticket_payments_sub = Qx.select('SUM(payments.gross_amount) AS total_paid', 'tickets.event_id') - .from(:payments) - .join(ticket_payments_subquery, 'payments.id=tickets.payment_id') - .group_by('tickets.event_id') - .as('ticket_payments') + ticket_payments_sub = Qx.select("SUM(payments.gross_amount) AS total_paid", "tickets.event_id") + .from(:payments) + .join(ticket_payments_subquery, "payments.id=tickets.payment_id") + .group_by("tickets.event_id") + .as("ticket_payments") - donations_sub = Qx.select('event_id', 'SUM(payments.gross_amount) as payment_total') - .from('donations') - .group_by('event_id') - .left_join('payments', 'donations.id=payments.donation_id') - .as('donations') + donations_sub = Qx.select("event_id", "SUM(payments.gross_amount) as payment_total") + .from("donations") + .group_by("event_id") + .left_join("payments", "donations.id=payments.donation_id") + .as("donations") selects = selects.concat(additional_selects) Qx.select(*selects) - .from('events') + .from("events") .left_join( - [tickets_sub, 'tickets.event_id = events.id'], - [donations_sub, 'donations.event_id = events.id'], - [ticket_payments_sub, 'ticket_payments.event_id=events.id'] + [tickets_sub, "tickets.event_id = events.id"], + [donations_sub, "donations.event_id = events.id"], + [ticket_payments_sub, "ticket_payments.event_id=events.id"] ) end def self.with_event_ids(event_ids) return [] if event_ids.empty? - QueryEventMetrics.expression.where('events.id in ($ids)', ids: event_ids).execute + QueryEventMetrics.expression.where("events.id in ($ids)", ids: event_ids).execute end def self.for_listings(id_type, id, params) selects = [ - 'events.id', - 'events.name', - 'events.venue_name', - 'events.address', - 'events.city', - 'events.state_code', - 'events.zip_code', - 'events.start_datetime', - 'events.end_datetime', - 'events.organizer_email' + "events.id", + "events.name", + "events.venue_name", + "events.address", + "events.city", + "events.state_code", + "events.zip_code", + "events.start_datetime", + "events.end_datetime", + "events.organizer_email" ] exp = QueryEventMetrics.expression(selects) - if id_type == 'profile' - exp = exp.and_where(['events.profile_id = $id', id: id]) + if id_type == "profile" + exp = exp.and_where(["events.profile_id = $id", id: id]) end - if id_type == 'nonprofit' - exp = exp.and_where(['events.nonprofit_id = $id', id: id]) + if id_type == "nonprofit" + exp = exp.and_where(["events.nonprofit_id = $id", id: id]) end - if params['active'].present? + if params["active"].present? exp = exp - .and_where(['events.end_datetime >= $date', date: Time.now]) - .and_where(['events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE']) + .and_where(["events.end_datetime >= $date", date: Time.now]) + .and_where(["events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE"]) end - if params['past'].present? + if params["past"].present? exp = exp - .and_where(['events.end_datetime < $date', date: Time.now]) - .and_where(['events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE']) + .and_where(["events.end_datetime < $date", date: Time.now]) + .and_where(["events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE"]) end - if params['unpublished'].present? - exp = exp.and_where(['coalesce(events.published, FALSE) = FALSE AND coalesce(events.deleted, FALSE) = FALSE']) + if params["unpublished"].present? + exp = exp.and_where(["coalesce(events.published, FALSE) = FALSE AND coalesce(events.deleted, FALSE) = FALSE"]) end - exp = exp.and_where(['events.deleted = TRUE']) if params['deleted'].present? + exp = exp.and_where(["events.deleted = TRUE"]) if params["deleted"].present? exp.execute end end diff --git a/app/legacy_lib/query_event_organizer.rb b/app/legacy_lib/query_event_organizer.rb index 9e10658244..85607d1083 100644 --- a/app/legacy_lib/query_event_organizer.rb +++ b/app/legacy_lib/query_event_organizer.rb @@ -5,14 +5,14 @@ module QueryEventOrganizer def self.with_event(event_id) Qx.select( - 'coalesce(profiles.name, nonprofits.name) AS name', - 'coalesce(users.email, nonprofits.email) AS email' + "coalesce(profiles.name, nonprofits.name) AS name", + "coalesce(users.email, nonprofits.email) AS email" ) .from(:events) - .left_join(:profiles, 'profiles.id=events.profile_id') - .add_left_join(:users, 'profiles.user_id=users.id') - .add_join(:nonprofits, 'events.nonprofit_id=nonprofits.id') - .where('events.id=$id', id: event_id) + .left_join(:profiles, "profiles.id=events.profile_id") + .add_left_join(:users, "profiles.user_id=users.id") + .add_join(:nonprofits, "events.nonprofit_id=nonprofits.id") + .where("events.id=$id", id: event_id) .execute.first end end diff --git a/app/legacy_lib/query_full_contact_infos.rb b/app/legacy_lib/query_full_contact_infos.rb index 4385fc85d5..0e80f8786b 100644 --- a/app/legacy_lib/query_full_contact_infos.rb +++ b/app/legacy_lib/query_full_contact_infos.rb @@ -5,10 +5,10 @@ module QueryFullContactInfos def self.fetch_associated_tables(fc_info_id) - photo = Psql.execute(Qexpr.new.from(:full_contact_photos).select('url').where('full_contact_info_id = $id', id: fc_info_id).where('is_primary')) - orgs = Psql.execute(Qexpr.new.from(:full_contact_orgs).select('current', 'name', 'title', 'start_date', 'end_date').where('full_contact_info_id = $id', id: fc_info_id).order_by('start_date DESC NULLS LAST')) - topics = Psql.execute(Qexpr.new.from(:full_contact_topics).select('value').where('full_contact_info_id = $id', id: fc_info_id).order_by('value ASC')) - profiles = Psql.execute(Qexpr.new.from(:full_contact_social_profiles).select('type_id', 'followers', 'url').where('full_contact_info_id = $id', id: fc_info_id).order_by('type_id ASC')) + photo = Psql.execute(Qexpr.new.from(:full_contact_photos).select("url").where("full_contact_info_id = $id", id: fc_info_id).where("is_primary")) + orgs = Psql.execute(Qexpr.new.from(:full_contact_orgs).select("current", "name", "title", "start_date", "end_date").where("full_contact_info_id = $id", id: fc_info_id).order_by("start_date DESC NULLS LAST")) + topics = Psql.execute(Qexpr.new.from(:full_contact_topics).select("value").where("full_contact_info_id = $id", id: fc_info_id).order_by("value ASC")) + profiles = Psql.execute(Qexpr.new.from(:full_contact_social_profiles).select("type_id", "followers", "url").where("full_contact_info_id = $id", id: fc_info_id).order_by("type_id ASC")) { photo: photo, topics: topics, diff --git a/app/legacy_lib/query_nonprofit_keys.rb b/app/legacy_lib/query_nonprofit_keys.rb index a2562016a1..ad51b2d79a 100644 --- a/app/legacy_lib/query_nonprofit_keys.rb +++ b/app/legacy_lib/query_nonprofit_keys.rb @@ -6,9 +6,9 @@ module QueryNonprofitKeys def self.get_key(npo_id, key_name) query = Qx.select(key_name) - .from(:nonprofit_keys) - .where('nonprofit_id' => npo_id) - .execute + .from(:nonprofit_keys) + .where("nonprofit_id" => npo_id) + .execute raise ActiveRecord::RecordNotFound, "Nonprofit key does not exist: #{key_name}" if query.empty? Cypher.decrypt(JSON.parse(query.first[key_name])) diff --git a/app/legacy_lib/query_nonprofits.rb b/app/legacy_lib/query_nonprofits.rb index c66dbaa52b..1af34828ff 100644 --- a/app/legacy_lib/query_nonprofits.rb +++ b/app/legacy_lib/query_nonprofits.rb @@ -7,20 +7,20 @@ module QueryNonprofits def self.all_that_need_payouts Psql.execute_vectors( Qexpr.new.select( - 'nonprofits.id', - 'nonprofits.stripe_account_id', + "nonprofits.id", + "nonprofits.stripe_account_id", "'support@commitchange.com' AS email", "'192.168.0.1' AS user_ip", - 'bank_accounts.name' + "bank_accounts.name" ).from(:nonprofits) .where("nonprofits.verification_status='verified'") - .join(:bank_accounts, 'bank_accounts.nonprofit_id=nonprofits.id') + .join(:bank_accounts, "bank_accounts.nonprofit_id=nonprofits.id") .where("bank_accounts.pending_verification='f'") .join( - Qexpr.new.select('nonprofit_id') - .from(:charges).group_by('nonprofit_id') - .where("status='available'").as('charges'), - 'charges.nonprofit_id=nonprofits.id' + Qexpr.new.select("nonprofit_id") + .from(:charges).group_by("nonprofit_id") + .where("status='available'").as("charges"), + "charges.nonprofit_id=nonprofits.id" ) )[1..-1] end @@ -28,87 +28,87 @@ def self.all_that_need_payouts def self.by_search_string(string) results = Psql.execute_vectors( Qexpr.new.select( - 'nonprofits.id', - 'nonprofits.name' + "nonprofits.id", + "nonprofits.name" ).from(:nonprofits) - .where('lower(nonprofits.name) LIKE lower($search)', search: "%#{string}%") + .where("lower(nonprofits.name) LIKE lower($search)", search: "%#{string}%") .where("nonprofits.published='t'") - .order_by('nonprofits.name ASC') + .order_by("nonprofits.name ASC") .limit(10) )[1..-1] - results = results.map { |id, name| { id: id, name: name } } if results + results = results.map { |id, name| {id: id, name: name} } if results results end def self.for_admin(params) expr = Qx.select( - 'nonprofits.id', - 'nonprofits.name', - 'nonprofits.email', - 'nonprofits.state_code', - 'nonprofits.created_at::date::text AS created_at', - 'nonprofits.verification_status', - 'nonprofits.vetted', - 'nonprofits.stripe_account_id', - 'coalesce(events.count, 0) AS events_count', - 'coalesce(campaigns.count, 0) AS campaigns_count', - 'billing_plans.percentage_fee', - 'charges.total_processed', - 'charges.total_fees' + "nonprofits.id", + "nonprofits.name", + "nonprofits.email", + "nonprofits.state_code", + "nonprofits.created_at::date::text AS created_at", + "nonprofits.verification_status", + "nonprofits.vetted", + "nonprofits.stripe_account_id", + "coalesce(events.count, 0) AS events_count", + "coalesce(campaigns.count, 0) AS campaigns_count", + "billing_plans.percentage_fee", + "charges.total_processed", + "charges.total_fees" ).from(:nonprofits) - .add_left_join(:billing_subscriptions, 'billing_subscriptions.nonprofit_id=nonprofits.id') - .add_left_join(:billing_plans, 'billing_subscriptions.billing_plan_id=billing_plans.id') - .add_left_join( - Qx.select( - '((SUM(coalesce(fee, 0)) * .978) / 100)::money::text AS total_fees', - '(SUM(coalesce(amount, 0)) / 100)::money::text AS total_processed', - 'nonprofit_id' - ) - .from(:charges) - .where("status != 'failed'") - .and_where("created_at::date >= '2017-03-15'") - .group_by('nonprofit_id') - .as('charges'), - 'charges.nonprofit_id=nonprofits.id' - ) - .add_left_join( - Qx.select('COUNT(id)', 'nonprofit_id') - .from(:events) - .group_by('nonprofit_id') - .as('events'), - 'events.nonprofit_id=nonprofits.id' - ) - .add_left_join( - Qx.select('COUNT(id)', 'nonprofit_id') - .from(:campaigns) - .group_by('nonprofit_id') - .as('campaigns'), - 'campaigns.nonprofit_id=nonprofits.id' - ) - .paginate(params[:page].to_i, params[:page_length].to_i) - .order_by('nonprofits.created_at DESC') + .add_left_join(:billing_subscriptions, "billing_subscriptions.nonprofit_id=nonprofits.id") + .add_left_join(:billing_plans, "billing_subscriptions.billing_plan_id=billing_plans.id") + .add_left_join( + Qx.select( + "((SUM(coalesce(fee, 0)) * .978) / 100)::money::text AS total_fees", + "(SUM(coalesce(amount, 0)) / 100)::money::text AS total_processed", + "nonprofit_id" + ) + .from(:charges) + .where("status != 'failed'") + .and_where("created_at::date >= '2017-03-15'") + .group_by("nonprofit_id") + .as("charges"), + "charges.nonprofit_id=nonprofits.id" + ) + .add_left_join( + Qx.select("COUNT(id)", "nonprofit_id") + .from(:events) + .group_by("nonprofit_id") + .as("events"), + "events.nonprofit_id=nonprofits.id" + ) + .add_left_join( + Qx.select("COUNT(id)", "nonprofit_id") + .from(:campaigns) + .group_by("nonprofit_id") + .as("campaigns"), + "campaigns.nonprofit_id=nonprofits.id" + ) + .paginate(params[:page].to_i, params[:page_length].to_i) + .order_by("nonprofits.created_at DESC") if params[:search].present? expr = expr.where(%( nonprofits.name ILIKE $search OR nonprofits.email ILIKE $search OR nonprofits.city ILIKE $search - ), search: '%' + params[:search] + '%') + ), search: "%" + params[:search] + "%") end expr.execute end def self.find_nonprofits_with_no_payments - Nonprofit.includes(:payments).where('payments.nonprofit_id IS NULL') + Nonprofit.includes(:payments).where("payments.nonprofit_id IS NULL") end def self.find_nonprofits_with_payments_in_last_n_days(days) - Payment.where('date >= ?', Time.now - days.days).pluck('nonprofit_id').to_a.uniq + Payment.where("date >= ?", Time.now - days.days).pluck("nonprofit_id").to_a.uniq end def self.find_nonprofits_with_payments_but_not_in_last_n_days(days) recent_nonprofits = find_nonprofits_with_payments_in_last_n_days(days) - Payment.where('date < ?', Time.now - days.days).pluck('nonprofit_id').to_a.uniq.reject { |i| recent_nonprofits.include?(i) } + Payment.where("date < ?", Time.now - days.days).pluck("nonprofit_id").to_a.uniq.reject { |i| recent_nonprofits.include?(i) } end end diff --git a/app/legacy_lib/query_payments.rb b/app/legacy_lib/query_payments.rb index 7ca11c928d..df9fbf8ab5 100644 --- a/app/legacy_lib/query_payments.rb +++ b/app/legacy_lib/query_payments.rb @@ -17,54 +17,54 @@ module QueryPayments # # In effect, we're getting the list of payments which haven't been paid out in a some fashion. This is not a great design but it works mostly. def self.ids_for_payout(npo_id, options = {}) - end_of_day = (Time.current + 1.day).beginning_of_day - Qx.select('DISTINCT payments.id') + end_of_day = 1.day.from_now.beginning_of_day + Qx.select("DISTINCT payments.id") .from(:payments) - .left_join(:charges, 'charges.payment_id=payments.id') - .add_left_join(:refunds, 'refunds.payment_id=payments.id') - .add_left_join(:disputes, 'disputes.payment_id=payments.id') - .where('payments.nonprofit_id=$id', id: npo_id) - .and_where('refunds.payment_id IS NOT NULL OR charges.payment_id IS NOT NULL OR disputes.payment_id IS NOT NULL') + .left_join(:charges, "charges.payment_id=payments.id") + .add_left_join(:refunds, "refunds.payment_id=payments.id") + .add_left_join(:disputes, "disputes.payment_id=payments.id") + .where("payments.nonprofit_id=$id", id: npo_id) + .and_where("refunds.payment_id IS NOT NULL OR charges.payment_id IS NOT NULL OR disputes.payment_id IS NOT NULL") .and_where(%( ((refunds.payment_id IS NOT NULL AND refunds.disbursed IS NULL) OR refunds.disbursed='f') OR (charges.status='available') OR (disputes.status='lost') )) - .and_where('payments.date <= $date', date: options[:date] || end_of_day) - .execute.map { |h| h['id'] } + .and_where("payments.date <= $date", date: options[:date] || end_of_day) + .execute.map { |h| h["id"] } end # the amount to payout calculates the total payout based upon the payments it's provided, likely provided from ids_to_payout def self.get_payout_totals(payment_ids) - return { 'gross_amount' => 0, 'fee_total' => 0, 'net_amount' => 0 } if payment_ids.empty? + return {"gross_amount" => 0, "fee_total" => 0, "net_amount" => 0} if payment_ids.empty? Qx.select( - 'SUM(payments.gross_amount) AS gross_amount', - 'SUM(payments.fee_total) AS fee_total', - 'SUM(payments.net_amount) AS net_amount', - 'COUNT(payments.*) AS count' + "SUM(payments.gross_amount) AS gross_amount", + "SUM(payments.fee_total) AS fee_total", + "SUM(payments.net_amount) AS net_amount", + "COUNT(payments.*) AS count" ) .from(:payments) - .where('payments.id IN ($ids)', ids: payment_ids) + .where("payments.id IN ($ids)", ids: payment_ids) .execute.first end def self.nonprofit_balances(npo_id) Psql.execute( Qexpr.new.select( - 'SUM(coalesce(available.amount, 0)) - SUM(coalesce(refunds.amount, 0)) - SUM(coalesce(disputes.gross_amount, 0)) AS available_gross', - 'SUM(coalesce(pending.amount, 0)) AS pending_gross', - 'COUNT(available) AS count_available', - 'COUNT(pending) AS count_pending', - 'COUNT(refunds) AS count_refunds', - 'COUNT(disputes) AS count_disputes' + "SUM(coalesce(available.amount, 0)) - SUM(coalesce(refunds.amount, 0)) - SUM(coalesce(disputes.gross_amount, 0)) AS available_gross", + "SUM(coalesce(pending.amount, 0)) AS pending_gross", + "COUNT(available) AS count_available", + "COUNT(pending) AS count_pending", + "COUNT(refunds) AS count_refunds", + "COUNT(disputes) AS count_disputes" ) .from(:payments) - .left_outer_join('refunds', "refunds.payment_id=payments.id AND (refunds.disbursed='f' OR refunds.disbursed IS NULL)") - .left_outer_join('charges available', "available.status='available' AND available.payment_id=payments.id") - .left_outer_join('charges pending', "pending.status='pending' AND pending.payment_id=payments.id") - .left_outer_join('disputes', "disputes.status='lost' AND disputes.payment_id=payments.id") - .where('payments.nonprofit_id=$id', id: npo_id) + .left_outer_join("refunds", "refunds.payment_id=payments.id AND (refunds.disbursed='f' OR refunds.disbursed IS NULL)") + .left_outer_join("charges available", "available.status='available' AND available.payment_id=payments.id") + .left_outer_join("charges pending", "pending.status='pending' AND pending.payment_id=payments.id") + .left_outer_join("disputes", "disputes.status='lost' AND disputes.payment_id=payments.id") + .where("payments.nonprofit_id=$id", id: npo_id) ).first end @@ -72,12 +72,12 @@ def self.full_search(npo_id, query) limit = 30 offset = Qexpr.page_offset(limit, query[:page]) expr = full_search_expr(npo_id, query).select( - 'payments.kind', - 'payments.towards', - 'payments.id AS id', - 'supporters.name', - 'supporters.email', - 'payments.gross_amount', + "payments.kind", + "payments.towards", + "payments.id AS id", + "supporters.name", + "supporters.email", + "payments.gross_amount", 'timezone( COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', payments.date) @@ -87,31 +87,31 @@ def self.full_search(npo_id, query) payments = Psql.execute(expr.limit(limit).offset(offset).parse) totals_query = expr - .remove(:select) - .remove(:order_by) - .select( - 'COALESCE(COUNT(payments.id), 0) AS count', - 'COALESCE((SUM(payments.gross_amount) / 100.0), 0)::money::text AS amount' - ) + .remove(:select) + .remove(:order_by) + .select( + "COALESCE(COUNT(payments.id), 0) AS count", + "COALESCE((SUM(payments.gross_amount) / 100.0), 0)::money::text AS amount" + ) totals = Psql.execute(totals_query).first { data: payments, - total_count: totals['count'], - total_amount: totals['amount'], - remaining: Qexpr.remaining_count(totals['count'], limit, query[:page]) + total_count: totals["count"], + total_amount: totals["amount"], + remaining: Qexpr.remaining_count(totals["count"], limit, query[:page]) } end # we must provide payments.*, supporters.*, donations.*, associated event_id, associated campaign_id def self.full_search_expr(npo_id, query) - expr = Qexpr.new.from('payments') - .left_outer_join('supporters', 'supporters.id=payments.supporter_id') - .inner_join('nonprofits', 'nonprofits.id=payments.nonprofit_id') - .left_outer_join('donations', 'donations.id=payments.donation_id') - .join("(#{select_to_filter_search(npo_id, query)}) AS \"filtered_payments\"", 'payments.id = filtered_payments.id') - .order_by('payments.date DESC') + expr = Qexpr.new.from("payments") + .left_outer_join("supporters", "supporters.id=payments.supporter_id") + .inner_join("nonprofits", "nonprofits.id=payments.nonprofit_id") + .left_outer_join("donations", "donations.id=payments.donation_id") + .join("(#{select_to_filter_search(npo_id, query)}) AS \"filtered_payments\"", "payments.id = filtered_payments.id") + .order_by("payments.date DESC") if %w[asc desc].include? query[:sort_amount] expr = expr.order_by("payments.gross_amount #{query[:sort_amount]}") @@ -134,19 +134,19 @@ def self.full_search_expr(npo_id, query) # perform the search but only get the relevant payment_ids def self.select_to_filter_search(npo_id, query) - inner_donation_search = Qexpr.new.select('donations.*').from('donations') + inner_donation_search = Qexpr.new.select("donations.*").from("donations") if query[:event_id].present? - inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id]) + inner_donation_search = inner_donation_search.where("donations.event_id=$id", id: query[:event_id]) end if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string inner_donation_search = inner_donation_search.where("donations.campaign_id IN (#{campaign_search})", id: query[:campaign_id]) end - expr = Qexpr.new.select('payments.id').from('payments') - .left_outer_join('supporters', 'supporters.id=payments.supporter_id') - .inner_join('nonprofits', 'nonprofits.id=payments.nonprofit_id') - .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments.donation_id') - .where('payments.nonprofit_id=$id', id: npo_id.to_i) + expr = Qexpr.new.select("payments.id").from("payments") + .left_outer_join("supporters", "supporters.id=payments.supporter_id") + .inner_join("nonprofits", "nonprofits.id=payments.nonprofit_id") + .left_outer_join(inner_donation_search.as("donations"), "donations.id=payments.donation_id") + .where("payments.nonprofit_id=$id", id: npo_id.to_i) expr = SearchVector.query(query[:search], expr) if query[:search].present? if %w[asc desc].include? query[:sort_amount] @@ -165,47 +165,47 @@ def self.select_to_filter_search(npo_id, query) expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}") end if query[:after_date].present? - expr = expr.where('payments.date >= timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $date))', date: query[:after_date]) + expr = expr.where("payments.date >= timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $date))", date: query[:after_date]) end if query[:before_date].present? - expr = expr.where('payments.date <= timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $date))', date: query[:before_date]) + expr = expr.where("payments.date <= timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $date))", date: query[:before_date]) end if query[:amount_greater_than].present? - expr = expr.where('payments.gross_amount >= $amt', amt: query[:amount_greater_than].to_i * 100) + expr = expr.where("payments.gross_amount >= $amt", amt: query[:amount_greater_than].to_i * 100) end if query[:amount_less_than].present? - expr = expr.where('payments.gross_amount <= $amt', amt: query[:amount_less_than].to_i * 100) + expr = expr.where("payments.gross_amount <= $amt", amt: query[:amount_less_than].to_i * 100) end if query[:year].present? expr = expr - .where( - "to_char(timezone( - COALESCE(nonprofits.timezone, \'UTC\'), - timezone(\'UTC\', payments.date) + .where( + "to_char(timezone( + COALESCE(nonprofits.timezone, 'UTC'), + timezone('UTC', payments.date) ), 'YYYY')=$year", - year: (query[:year]).to_s - ) + year: query[:year].to_s + ) end if query[:designation].present? - expr = expr.where('donations.designation @@ $s', s: (query[:designation]).to_s) + expr = expr.where("donations.designation @@ $s", s: query[:designation].to_s) end if query[:dedication].present? - expr = expr.where('donations.dedication @@ $s', s: (query[:dedication]).to_s) + expr = expr.where("donations.dedication @@ $s", s: query[:dedication].to_s) end if query[:donation_type].present? - expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(',')) + expr = expr.where("payments.kind IN ($kinds)", kinds: query[:donation_type].split(",")) end if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string expr = expr - .left_outer_join('campaigns', 'campaigns.id=donations.campaign_id') - .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) + .left_outer_join("campaigns", "campaigns.id=donations.campaign_id") + .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) end if query[:event_id].present? - tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by('payment_id').as('tix') + tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where("tickets.event_id=$event_id", event_id: query[:event_id]).group_by("payment_id").as("tix") expr = expr - .left_outer_join(tickets_subquery, 'tix.payment_id=payments.id') - .where('tix.event_id=$id OR donations.event_id=$id', id: query[:event_id]) + .left_outer_join(tickets_subquery, "tix.payment_id=payments.id") + .where("tix.event_id=$id OR donations.event_id=$id", id: query[:event_id]) end @@ -215,7 +215,7 @@ def self.select_to_filter_search(npo_id, query) filtered_payment_id_search = expr.parse if query[:event_id].present? || query[:campaign_id].present? - filtered_payment_id_search = filtered_payment_id_search + ' UNION DISTINCT ' + create_reverse_select(npo_id, query).parse + filtered_payment_id_search = filtered_payment_id_search + " UNION DISTINCT " + create_reverse_select(npo_id, query).parse end filtered_payment_id_search @@ -223,21 +223,21 @@ def self.select_to_filter_search(npo_id, query) # we use this when we need to get the refund info def self.create_reverse_select(npo_id, query) - inner_donation_search = Qexpr.new.select('donations.*').from('donations') + inner_donation_search = Qexpr.new.select("donations.*").from("donations") if query[:event_id].present? - inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id]) + inner_donation_search = inner_donation_search.where("donations.event_id=$id", id: query[:event_id]) end if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string inner_donation_search = inner_donation_search.where("donations.campaign_id IN (#{campaign_search})", id: query[:campaign_id]) end - expr = Qexpr.new.select('payments.id').from('payments') - .left_outer_join('supporters', 'supporters.id=payments.supporter_id') - .left_outer_join('refunds', 'payments.id=refunds.payment_id') - .left_outer_join('charges', 'refunds.charge_id=charges.id') - .left_outer_join('payments AS payments_orig', 'payments_orig.id=charges.payment_id') - .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments_orig.donation_id') - .where('payments.nonprofit_id=$id', id: npo_id.to_i) + expr = Qexpr.new.select("payments.id").from("payments") + .left_outer_join("supporters", "supporters.id=payments.supporter_id") + .left_outer_join("refunds", "payments.id=refunds.payment_id") + .left_outer_join("charges", "refunds.charge_id=charges.id") + .left_outer_join("payments AS payments_orig", "payments_orig.id=charges.payment_id") + .left_outer_join(inner_donation_search.as("donations"), "donations.id=payments_orig.donation_id") + .where("payments.nonprofit_id=$id", id: npo_id.to_i) expr = SearchVector.query(query[:search], expr) if query[:search].present? if %w[asc desc].include? query[:sort_amount] @@ -256,40 +256,40 @@ def self.create_reverse_select(npo_id, query) expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}") end if query[:after_date].present? - expr = expr.where('payments.date >= $date', date: query[:after_date]) + expr = expr.where("payments.date >= $date", date: query[:after_date]) end if query[:before_date].present? - expr = expr.where('payments.date <= $date', date: query[:before_date]) + expr = expr.where("payments.date <= $date", date: query[:before_date]) end if query[:amount_greater_than].present? - expr = expr.where('payments.gross_amount >= $amt', amt: query[:amount_greater_than].to_i * 100) + expr = expr.where("payments.gross_amount >= $amt", amt: query[:amount_greater_than].to_i * 100) end if query[:amount_less_than].present? - expr = expr.where('payments.gross_amount <= $amt', amt: query[:amount_less_than].to_i * 100) + expr = expr.where("payments.gross_amount <= $amt", amt: query[:amount_less_than].to_i * 100) end if query[:year].present? expr = expr.where("to_char(payments.date, 'YYYY')=$year", year: query[:year]) end if query[:designation].present? - expr = expr.where('donations.designation @@ $s', s: (query[:designation]).to_s) + expr = expr.where("donations.designation @@ $s", s: query[:designation].to_s) end if query[:dedication].present? - expr = expr.where('donations.dedication @@ $s', s: (query[:dedication]).to_s) + expr = expr.where("donations.dedication @@ $s", s: query[:dedication].to_s) end if query[:donation_type].present? - expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(',')) + expr = expr.where("payments.kind IN ($kinds)", kinds: query[:donation_type].split(",")) end if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string expr = expr - .left_outer_join('campaigns', 'campaigns.id=donations.campaign_id') - .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) + .left_outer_join("campaigns", "campaigns.id=donations.campaign_id") + .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) end if query[:event_id].present? - tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by('payment_id').as('tix') + tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where("tickets.event_id=$event_id", event_id: query[:event_id]).group_by("payment_id").as("tix") expr = expr - .left_outer_join(tickets_subquery, 'tix.payment_id=payments_orig.id') - .where('tix.event_id=$id OR donations.event_id=$id', id: query[:event_id]) + .left_outer_join(tickets_subquery, "tix.payment_id=payments_orig.id") + .where("tix.event_id=$id OR donations.event_id=$id", id: query[:event_id]) end @@ -297,8 +297,8 @@ def self.create_reverse_select(npo_id, query) end def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) - ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, - query: { required: true, is_hash: true }) + ParamValidation.new({npo_id: npo_id, query: query}, npo_id: {required: true, is_int: true}, + query: {required: true, is_hash: true}) QexprQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_export(npo_id, query, offset, limit, skip_header) @@ -306,86 +306,86 @@ def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) end def self.for_export(npo_id, query) - tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') + tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") expr = full_search_expr(npo_id, query) - .select(*export_selects) - .left_outer_join('campaign_gifts', 'campaign_gifts.donation_id=donations.id') - .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') - .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", 'donations.campaign_id=campaigns_for_export.id') - .left_outer_join(tickets_subquery, 'tickets.payment_id=payments.id') - .left_outer_join('events events_for_export', 'events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id') - .left_outer_join('offsite_payments', 'offsite_payments.payment_id=payments.id') - .parse + .select(*export_selects) + .left_outer_join("campaign_gifts", "campaign_gifts.donation_id=donations.id") + .left_outer_join("campaign_gift_options", "campaign_gifts.campaign_gift_option_id=campaign_gift_options.id") + .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", "donations.campaign_id=campaigns_for_export.id") + .left_outer_join(tickets_subquery, "tickets.payment_id=payments.id") + .left_outer_join("events events_for_export", "events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id") + .left_outer_join("offsite_payments", "offsite_payments.payment_id=payments.id") + .parse Psql.execute_vectors(expr) end def self.get_chunk_of_export(npo_id, query, offset = nil, limit = nil, skip_header = false) QexprQueryChunker.get_chunk_of_query(offset, limit, skip_header) do - tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') - expr = full_search_expr(npo_id, query) - .select(*export_selects) - .left_outer_join('campaign_gifts', 'campaign_gifts.donation_id=donations.id') - .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') - .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", 'donations.campaign_id=campaigns_for_export.id') - .left_outer_join(tickets_subquery, 'tickets.payment_id=payments.id') - .left_outer_join('events events_for_export', 'events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id') - .left_outer_join('offsite_payments', 'offsite_payments.payment_id=payments.id') + tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") + full_search_expr(npo_id, query) + .select(*export_selects) + .left_outer_join("campaign_gifts", "campaign_gifts.donation_id=donations.id") + .left_outer_join("campaign_gift_options", "campaign_gifts.campaign_gift_option_id=campaign_gift_options.id") + .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", "donations.campaign_id=campaigns_for_export.id") + .left_outer_join(tickets_subquery, "tickets.payment_id=payments.id") + .left_outer_join("events events_for_export", "events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id") + .left_outer_join("offsite_payments", "offsite_payments.payment_id=payments.id") end end def self.get_dedication_or_empty(*path) - "json_extract_path_text(coalesce(donations.dedication, '{}')::json, #{path.map { |i| "'#{i}'" }.join(',')})" + "json_extract_path_text(coalesce(donations.dedication, '{}')::json, #{path.map { |i| "'#{i}'" }.join(",")})" end def self.export_selects - ["to_char(payments.date::timestamptz at time zone COALESCE(nonprofits.timezone, \'UTC\'), 'YYYY-MM-DD HH24:MI:SS TZ') AS date", - '(payments.gross_amount / 100.0)::money::text AS gross_amount', - '(payments.fee_total / 100.0)::money::text AS fee_total', - '(payments.net_amount / 100.0)::money::text AS net_amount', - 'payments.kind AS type'] + ["to_char(payments.date::timestamptz at time zone COALESCE(nonprofits.timezone, 'UTC'), 'YYYY-MM-DD HH24:MI:SS TZ') AS date", + "(payments.gross_amount / 100.0)::money::text AS gross_amount", + "(payments.fee_total / 100.0)::money::text AS fee_total", + "(payments.net_amount / 100.0)::money::text AS net_amount", + "payments.kind AS type"] .concat(QuerySupporters.supporter_export_selections) .concat([ - "coalesce(donations.designation, 'None') AS designation", - "#{get_dedication_or_empty('type')}::text AS \"Dedication Type\"", - "#{get_dedication_or_empty('name')}::text AS \"Dedicated To: Name\"", - "#{get_dedication_or_empty('supporter_id')}::text AS \"Dedicated To: Supporter ID\"", - "#{get_dedication_or_empty('contact', 'email')}::text AS \"Dedicated To: Email\"", - "#{get_dedication_or_empty('contact', 'phone')}::text AS \"Dedicated To: Phone\"", - "#{get_dedication_or_empty('contact', 'address')}::text AS \"Dedicated To: Address\"", - "#{get_dedication_or_empty('note')}::text AS \"Dedicated To: Note\"", - 'donations.anonymous', - 'donations.comment', - "coalesce(nullif(campaigns_for_export.name, ''), 'None') AS campaign", - 'campaigns_for_export.id AS "Campaign Id"', - "coalesce(nullif(campaigns_for_export.creator_email, ''), '') AS campaign_creator_email", - "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS campaign_gift_level", - 'events_for_export.name AS event_name', - 'payments.id AS payment_id', - 'offsite_payments.check_number AS check_number', - 'donations.comment AS donation_note' - ]) + "coalesce(donations.designation, 'None') AS designation", + "#{get_dedication_or_empty("type")}::text AS \"Dedication Type\"", + "#{get_dedication_or_empty("name")}::text AS \"Dedicated To: Name\"", + "#{get_dedication_or_empty("supporter_id")}::text AS \"Dedicated To: Supporter ID\"", + "#{get_dedication_or_empty("contact", "email")}::text AS \"Dedicated To: Email\"", + "#{get_dedication_or_empty("contact", "phone")}::text AS \"Dedicated To: Phone\"", + "#{get_dedication_or_empty("contact", "address")}::text AS \"Dedicated To: Address\"", + "#{get_dedication_or_empty("note")}::text AS \"Dedicated To: Note\"", + "donations.anonymous", + "donations.comment", + "coalesce(nullif(campaigns_for_export.name, ''), 'None') AS campaign", + 'campaigns_for_export.id AS "Campaign Id"', + "coalesce(nullif(campaigns_for_export.creator_email, ''), '') AS campaign_creator_email", + "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS campaign_gift_level", + "events_for_export.name AS event_name", + "payments.id AS payment_id", + "offsite_payments.check_number AS check_number", + "donations.comment AS donation_note" + ]) end # Create the data structure for the payout export CSVs # Has two sections: two rows for info about the payout, then all the rows after that are for the payments # TODO reuse the standard payment export query for the payment rows for this query def self.for_payout(npo_id, payout_id) - tickets_subquery = Qx.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') - supporters_subq = Qx.select(QuerySupporters.supporter_export_selections) + tickets_subquery = Qx.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") + Qx.select(QuerySupporters.supporter_export_selections) Qx.select( "to_char(payouts.created_at, 'MM/DD/YYYY HH24:MIam') AS date", - '(payouts.gross_amount / 100.0)::money::text AS gross_total', - '(payouts.fee_total / 100.0)::money::text AS fee_total', - '(payouts.net_amount / 100.0)::money::text AS net_total', - 'bank_accounts.name AS bank_name', - 'payouts.status' + "(payouts.gross_amount / 100.0)::money::text AS gross_total", + "(payouts.fee_total / 100.0)::money::text AS fee_total", + "(payouts.net_amount / 100.0)::money::text AS net_total", + "bank_accounts.name AS bank_name", + "payouts.status" ) .from(:payouts) - .join(:bank_accounts, 'bank_accounts.nonprofit_id=payouts.nonprofit_id') - .where('payouts.nonprofit_id=$id', id: npo_id) - .and_where('payouts.id=$id', id: payout_id) - .execute(format: 'csv') + .join(:bank_accounts, "bank_accounts.nonprofit_id=payouts.nonprofit_id") + .where("payouts.nonprofit_id=$id", id: npo_id) + .and_where("payouts.id=$id", id: payout_id) + .execute(format: "csv") .concat([[]]) .concat( Qx.select([ @@ -397,40 +397,40 @@ def self.for_payout(npo_id, payout_id) 'payments.id AS "Payment ID"' ].concat(QuerySupporters.supporter_export_selections) .concat([ - "coalesce(donations.designation, 'None') AS \"Designation\"", - 'donations.dedication AS "Honorarium/Memorium"', - 'donations.anonymous AS "Anonymous?"', - 'donations.comment AS "Comment"', - "coalesce(nullif(campaigns.name, ''), 'None') AS \"Campaign\"", - "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS \"Campaign Gift Level\"", - "coalesce(events.name, 'None') AS \"Event\"" - ])) - .distinct_on('payments.date, payments.id') + "coalesce(donations.designation, 'None') AS \"Designation\"", + 'donations.dedication AS "Honorarium/Memorium"', + 'donations.anonymous AS "Anonymous?"', + 'donations.comment AS "Comment"', + "coalesce(nullif(campaigns.name, ''), 'None') AS \"Campaign\"", + "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS \"Campaign Gift Level\"", + "coalesce(events.name, 'None') AS \"Event\"" + ])) + .distinct_on("payments.date, payments.id") .from(:payments) - .join(:payment_payouts, 'payment_payouts.payment_id=payments.id') - .add_join(:payouts, 'payouts.id=payment_payouts.payout_id') - .left_join(:supporters, 'payments.supporter_id=supporters.id') - .add_left_join(:donations, 'donations.id=payments.donation_id') - .add_left_join(:campaigns, 'donations.campaign_id=campaigns.id') - .add_left_join(:campaign_gifts, 'donations.id=campaign_gifts.donation_id') - .add_left_join(:campaign_gift_options, 'campaign_gift_options.id=campaign_gifts.campaign_gift_option_id') - .add_left_join(tickets_subquery, 'tickets.payment_id=payments.id') - .add_left_join(:events, 'events.id=tickets.event_id OR (events.id = donations.event_id)') - .where('payouts.id=$id', id: payout_id) - .and_where('payments.nonprofit_id=$id', id: npo_id) - .order_by('payments.date DESC, payments.id') - .execute(format: 'csv') + .join(:payment_payouts, "payment_payouts.payment_id=payments.id") + .add_join(:payouts, "payouts.id=payment_payouts.payout_id") + .left_join(:supporters, "payments.supporter_id=supporters.id") + .add_left_join(:donations, "donations.id=payments.donation_id") + .add_left_join(:campaigns, "donations.campaign_id=campaigns.id") + .add_left_join(:campaign_gifts, "donations.id=campaign_gifts.donation_id") + .add_left_join(:campaign_gift_options, "campaign_gift_options.id=campaign_gifts.campaign_gift_option_id") + .add_left_join(tickets_subquery, "tickets.payment_id=payments.id") + .add_left_join(:events, "events.id=tickets.event_id OR (events.id = donations.event_id)") + .where("payouts.id=$id", id: payout_id) + .and_where("payments.nonprofit_id=$id", id: npo_id) + .order_by("payments.date DESC, payments.id") + .execute(format: "csv") ) end def self.find_payments_where_too_far_from_charge_date(id = nil) pay = Payment.includes(:donation).includes(:offsite_payment) - pay = pay.where('id = ?', id) if id - pay = pay.where('date IS NOT NULL').order('id ASC') + pay = pay.where("id = ?", id) if id + pay = pay.where.not(date: nil).order("id ASC") pay.all.each do |p| next unless p.offsite_payment.nil? - lowest_charge_for_payment = Charge.where('payment_id = ?', p.id).order('created_at ASC').limit(1).first + lowest_charge_for_payment = Charge.where("payment_id = ?", p.id).order("created_at ASC").limit(1).first if lowest_charge_for_payment diff = p.date - lowest_charge_for_payment.created_at @@ -443,10 +443,10 @@ def self.find_payments_where_too_far_from_charge_date(id = nil) end def self.campaign_and_child_query_as_raw_string - 'SELECT c_temp.id from campaigns c_temp where c_temp.id=$id OR c_temp.parent_campaign_id=$id' + "SELECT c_temp.id from campaigns c_temp where c_temp.id=$id OR c_temp.parent_campaign_id=$id" end def self.campaigns_with_creator_email - Qexpr.new.select('campaigns.*, users.email AS creator_email').from(:campaigns).left_outer_join(:profiles, 'profiles.id = campaigns.profile_id').left_outer_join(:users, 'users.id = profiles.user_id') + Qexpr.new.select("campaigns.*, users.email AS creator_email").from(:campaigns).left_outer_join(:profiles, "profiles.id = campaigns.profile_id").left_outer_join(:users, "users.id = profiles.user_id") end end diff --git a/app/legacy_lib/query_profiles.rb b/app/legacy_lib/query_profiles.rb index a88ebea559..51a41b47b3 100644 --- a/app/legacy_lib/query_profiles.rb +++ b/app/legacy_lib/query_profiles.rb @@ -6,23 +6,23 @@ module QueryProfiles def self.for_admin(params) expr = Qx.select( - 'profiles.name', - 'profiles.id', - 'profiles.created_at::date::text AS created_at', - 'users.confirmed_at AS is_confirmed', - 'users.email' + "profiles.name", + "profiles.id", + "profiles.created_at::date::text AS created_at", + "users.confirmed_at AS is_confirmed", + "users.email" ) - .from(:profiles) - .add_left_join('users', 'profiles.user_id=users.id') - .order_by('profiles.created_at DESC') - .paginate(params[:page].to_i, params[:page_length].to_i) + .from(:profiles) + .add_left_join("users", "profiles.user_id=users.id") + .order_by("profiles.created_at DESC") + .paginate(params[:page].to_i, params[:page_length].to_i) if params[:search].present? expr = expr.where(%( profiles.name LIKE $search OR users.email LIKE $search OR users.name LIKE $search - ), search: '%' + params[:search].downcase + '%') + ), search: "%" + params[:search].downcase + "%") end expr.execute diff --git a/app/legacy_lib/query_recurring_donations.rb b/app/legacy_lib/query_recurring_donations.rb index 14e45a65d7..8cd20bb856 100644 --- a/app/legacy_lib/query_recurring_donations.rb +++ b/app/legacy_lib/query_recurring_donations.rb @@ -6,80 +6,80 @@ module QueryRecurringDonations # Calculate a nonprofit's total recurring donations def self.calculate_monthly_donation_total(np_id) - Qx.select('coalesce(sum(amount), 0) AS sum') - .from('recurring_donations') + Qx.select("coalesce(sum(amount), 0) AS sum") + .from("recurring_donations") .where(nonprofit_id: np_id) - .and_where(is_external_active_clause('recurring_donations')) - .execute.first['sum'] + .and_where(is_external_active_clause("recurring_donations")) + .execute.first["sum"] end # Fetch a single recurring donation for its edit page def self.fetch_for_edit(id) recurring_donation = Psql.execute( Qexpr.new.select( - 'recurring_donations.*', - 'nonprofits.id AS nonprofit_id', - 'nonprofits.name AS nonprofit_name', - 'cards.name AS card_name' - ).from('recurring_donations') - .left_outer_join('donations', 'donations.id=recurring_donations.donation_id') - .left_outer_join('cards', 'donations.card_id=cards.id') - .left_outer_join('nonprofits', 'nonprofits.id=recurring_donations.nonprofit_id') - .where('recurring_donations.id=$id', id: id) + "recurring_donations.*", + "nonprofits.id AS nonprofit_id", + "nonprofits.name AS nonprofit_name", + "cards.name AS card_name" + ).from("recurring_donations") + .left_outer_join("donations", "donations.id=recurring_donations.donation_id") + .left_outer_join("cards", "donations.card_id=cards.id") + .left_outer_join("nonprofits", "nonprofits.id=recurring_donations.nonprofit_id") + .where("recurring_donations.id=$id", id: id) ).first - return recurring_donation if !recurring_donation || !recurring_donation['id'] + return recurring_donation if !recurring_donation || !recurring_donation["id"] supporter = Psql.execute( - Qexpr.new.select('*') - .from('supporters') - .where('id=$id', id: recurring_donation['supporter_id']) + Qexpr.new.select("*") + .from("supporters") + .where("id=$id", id: recurring_donation["supporter_id"]) ).first - nonprofit = Nonprofit.find(recurring_donation['nonprofit_id']) + nonprofit = Nonprofit.find(recurring_donation["nonprofit_id"]) { - 'recurring_donation' => recurring_donation, - 'supporter' => supporter, - 'nonprofit' => nonprofit + "recurring_donation" => recurring_donation, + "supporter" => supporter, + "nonprofit" => nonprofit } end # Construct a full query for the dashboard/export listings def self.full_search_expr(np_id, query) expr = Qexpr.new - .from('recurring_donations') - .left_outer_join('supporters', 'supporters.id=recurring_donations.supporter_id') - .join('donations', 'donations.id=recurring_donations.donation_id') - .left_outer_join('charges paid_charges', 'paid_charges.donation_id=donations.id') - .where('recurring_donations.nonprofit_id=$id', id: np_id.to_i) + .from("recurring_donations") + .left_outer_join("supporters", "supporters.id=recurring_donations.supporter_id") + .join("donations", "donations.id=recurring_donations.donation_id") + .left_outer_join("charges paid_charges", "paid_charges.donation_id=donations.id") + .where("recurring_donations.nonprofit_id=$id", id: np_id.to_i) failed_or_active_clauses = [] if query.key?(:active_and_not_failed) - clause = query[:active_and_not_failed] ? is_external_active_clause('recurring_donations') : is_external_cancelled_clause('recurring_donations') + clause = query[:active_and_not_failed] ? is_external_active_clause("recurring_donations") : is_external_cancelled_clause("recurring_donations") failed_or_active_clauses.push("(#{clause})") end if query.key?(:active) - clause = query[:active] ? is_active_clause('recurring_donations') : is_cancelled_clause('recurring_donations') + clause = query[:active] ? is_active_clause("recurring_donations") : is_cancelled_clause("recurring_donations") failed_or_active_clauses.push("(#{clause})") end if query.key?(:failed) - clause = query[:failed] ? is_failed_clause('recurring_donations') : is_not_failed_clause('recurring_donations') + clause = query[:failed] ? is_failed_clause("recurring_donations") : is_not_failed_clause("recurring_donations") failed_or_active_clauses.push("(#{clause})") end if failed_or_active_clauses.any? - expr = expr.where(failed_or_active_clauses.join(' OR ').to_s) + expr = expr.where(failed_or_active_clauses.join(" OR ").to_s) end expr = expr.where("paid_charges.id IS NULL OR paid_charges.status != 'failed'") - .group_by('recurring_donations.id') - .order_by('recurring_donations.created_at') + .group_by("recurring_donations.id") + .order_by("recurring_donations.created_at") if query[:search].present? - matcher = "%#{query[:search].downcase.split(' ').join('%')}%" + matcher = "%#{query[:search].downcase.split(" ").join("%")}%" expr = expr.where(%(( lower(supporters.name) LIKE $name OR lower(supporters.email) LIKE $email @@ -95,24 +95,24 @@ def self.full_list(np_id, query = {}) limit = 30 offset = Qexpr.page_offset(limit, query[:page]) expr = full_search_expr(np_id, query).select( - 'recurring_donations.start_date', - 'recurring_donations.interval', - 'recurring_donations.time_unit', - 'recurring_donations.n_failures', - 'recurring_donations.amount', - 'recurring_donations.id AS id', - 'MAX(supporters.email) AS email', - 'MAX(supporters.name) AS name', - 'MAX(supporters.id) AS supporter_id', - 'SUM(paid_charges.amount) AS total_given' + "recurring_donations.start_date", + "recurring_donations.interval", + "recurring_donations.time_unit", + "recurring_donations.n_failures", + "recurring_donations.amount", + "recurring_donations.id AS id", + "MAX(supporters.email) AS email", + "MAX(supporters.name) AS name", + "MAX(supporters.id) AS supporter_id", + "SUM(paid_charges.amount) AS total_given" ) - .limit(limit).offset(offset) + .limit(limit).offset(offset) data = Psql.execute(expr) total_count = Psql.execute( - Qexpr.new.select('COUNT(rds)') - .from(full_search_expr(np_id, query).remove(:order_by).select('recurring_donations.id'), 'rds') - ).first['count'] + Qexpr.new.select("COUNT(rds)") + .from(full_search_expr(np_id, query).remove(:order_by).select("recurring_donations.id"), "rds") + ).first["count"] total_amount = calculate_monthly_donation_total(np_id) { @@ -124,8 +124,8 @@ def self.full_list(np_id, query = {}) end def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) - ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, - query: { required: true, is_hash: true }) + ParamValidation.new({npo_id: npo_id, query: query}, npo_id: {required: true, is_int: true}, + query: {required: true, is_hash: true}) QexprQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_export(npo_id, query, offset, limit, skip_header) @@ -139,34 +139,34 @@ def self.get_chunk_of_export(npo_id, query, offset = nil, limit = nil, skip_head result = QexprQueryChunker.get_chunk_of_query(offset, limit, skip_header) do full_search_expr(npo_id, query).select( - 'recurring_donations.created_at', - 'recurring_donations.amount AS amount', + "recurring_donations.created_at", + "recurring_donations.amount AS amount", "concat('Every ', recurring_donations.interval, ' ', recurring_donations.time_unit, '(s)') AS interval", - '(SUM(paid_charges.amount) / 100.0)::money::text AS total_contributed', - 'MAX(campaigns.name) AS campaign_name', - 'MAX(supporters.name) AS supporter_name', - 'MAX(supporters.email) AS supporter_email', - 'MAX(supporters.phone) AS phone', - 'MAX(supporters.address) AS address', - 'MAX(supporters.city) AS city', - 'MAX(supporters.state_code) AS state', - 'MAX(supporters.zip_code) AS zip_code', - 'MAX(cards.name) AS card_name', + "(SUM(paid_charges.amount) / 100.0)::money::text AS total_contributed", + "MAX(campaigns.name) AS campaign_name", + "MAX(supporters.name) AS supporter_name", + "MAX(supporters.email) AS supporter_email", + "MAX(supporters.phone) AS phone", + "MAX(supporters.address) AS address", + "MAX(supporters.city) AS city", + "MAX(supporters.state_code) AS state", + "MAX(supporters.zip_code) AS zip_code", + "MAX(cards.name) AS card_name", 'recurring_donations.id AS "Recurring Donation ID"', 'MAX(donations.id) AS "Donation ID"', - "CASE WHEN #{is_cancelled_clause('recurring_donations')} THEN 'true' ELSE 'false' END AS Cancelled", - "CASE WHEN #{is_failed_clause('recurring_donations')} THEN 'true' ELSE 'false' END AS Failed", + "CASE WHEN #{is_cancelled_clause("recurring_donations")} THEN 'true' ELSE 'false' END AS Cancelled", + "CASE WHEN #{is_failed_clause("recurring_donations")} THEN 'true' ELSE 'false' END AS Failed", 'recurring_donations.cancelled_at AS "Cancelled At"', - "CASE WHEN #{is_active_clause('recurring_donations')} THEN concat('#{root_url}recurring_donations/', recurring_donations.id, '/edit?t=', recurring_donations.edit_token) ELSE '' END AS \"Donation Management Url\"" + "CASE WHEN #{is_active_clause("recurring_donations")} THEN concat('#{root_url}recurring_donations/', recurring_donations.id, '/edit?t=', recurring_donations.edit_token) ELSE '' END AS \"Donation Management Url\"" ) - .left_outer_join('campaigns', 'campaigns.id=donations.campaign_id') - .left_outer_join('cards', 'cards.id=donations.card_id') + .left_outer_join("campaigns", "campaigns.id=donations.campaign_id") + .left_outer_join("cards", "cards.id=donations.card_id") end result.map { |r| update_amount_with_currency(r, currency) } end def self.recurring_donations_without_cards - RecurringDonation.active.includes(:card).includes(:charges).includes(:donation).includes(:nonprofit).includes(:supporter).where('cards.id IS NULL').order('recurring_donations.created_at DESC') + RecurringDonation.active.includes(:card).includes(:charges).includes(:donation).includes(:nonprofit).includes(:supporter).where("cards.id IS NULL").order("recurring_donations.created_at DESC") end # @param [Supporter] supporter @@ -180,7 +180,7 @@ def self.find_recurring_donation_with_a_card(supporter) def self.is_due?(rd_id) Psql.execute( _all_that_are_due - .where('recurring_donations.id=$id', id: rd_id) + .where("recurring_donations.id=$id", id: rd_id) ).any? end @@ -190,22 +190,22 @@ def self.is_due?(rd_id) # XXX horrendous conditional --what is wrong with me? def self._all_that_are_due now = Time.current - Qexpr.new.select('recurring_donations.id') - .from(:recurring_donations) - .where("recurring_donations.active='t'") - .where('coalesce(recurring_donations.n_failures, 0) < 3') - .where('recurring_donations.start_date IS NULL OR recurring_donations.start_date <= $now', now: now) - .where('recurring_donations.end_date IS NULL OR recurring_donations.end_date > $now', now: now) - .join('donations', 'recurring_donations.donation_id=donations.id and (donations.payment_provider IS NULL OR donations.payment_provider!=\'sepa\')') - .left_outer_join( # Join the most recent paid charge - Qexpr.new.select(:donation_id, 'MAX(created_at) AS created_at') - .from(:charges) - .where("status != 'failed'") - .group_by('donation_id') - .as('last_charge'), - 'last_charge.donation_id=recurring_donations.donation_id' - ) - .where(%( + Qexpr.new.select("recurring_donations.id") + .from(:recurring_donations) + .where("recurring_donations.active='t'") + .where("coalesce(recurring_donations.n_failures, 0) < 3") + .where("recurring_donations.start_date IS NULL OR recurring_donations.start_date <= $now", now: now) + .where("recurring_donations.end_date IS NULL OR recurring_donations.end_date > $now", now: now) + .join("donations", "recurring_donations.donation_id=donations.id and (donations.payment_provider IS NULL OR donations.payment_provider!='sepa')") + .left_outer_join( # Join the most recent paid charge + Qexpr.new.select(:donation_id, "MAX(created_at) AS created_at") + .from(:charges) + .where("status != 'failed'") + .group_by("donation_id") + .as("last_charge"), + "last_charge.donation_id=recurring_donations.donation_id" + ) + .where(%( last_charge.donation_id IS NULL OR ( (recurring_donations.time_unit != 'month' OR recurring_donations.interval != 1) @@ -227,11 +227,11 @@ def self._all_that_are_due ) ) ), - now: now, - beginning_of_month: now.beginning_of_month, - beginning_of_last_month: (now - 1.month).beginning_of_month, - today: now.day) - .order_by('recurring_donations.created_at') + now: now, + beginning_of_month: now.beginning_of_month, + beginning_of_last_month: (now - 1.month).beginning_of_month, + today: now.day) + .order_by("recurring_donations.created_at") end # Some general statistics for a nonprofit @@ -239,21 +239,21 @@ def self.overall_stats(np_id) Psql.execute( Qexpr.new.from(:recurring_donations) .select( - 'money(avg(recurring_donations.amount) / 100.0) AS average', - 'money(coalesce(sum(rds_active.amount), 0) / 100.0) AS active_sum', - 'coalesce(count(rds_active), 0) AS active_count', - 'money(coalesce(sum(rds_inactive.amount), 0) / 100.0) AS inactive_sum', - 'coalesce(count(rds_inactive), 0) AS inactive_count', - 'money(coalesce(sum(rds_failed.amount), 0) / 100.0) AS failed_sum', - 'coalesce(count(rds_failed), 0) AS failed_count', - 'money(coalesce(sum(rds_cancelled.amount), 0) / 100.0) AS cancelled_sum', - 'coalesce(count(rds_cancelled), 0) AS cancelled_count' + "money(avg(recurring_donations.amount) / 100.0) AS average", + "money(coalesce(sum(rds_active.amount), 0) / 100.0) AS active_sum", + "coalesce(count(rds_active), 0) AS active_count", + "money(coalesce(sum(rds_inactive.amount), 0) / 100.0) AS inactive_sum", + "coalesce(count(rds_inactive), 0) AS inactive_count", + "money(coalesce(sum(rds_failed.amount), 0) / 100.0) AS failed_sum", + "coalesce(count(rds_failed), 0) AS failed_count", + "money(coalesce(sum(rds_cancelled.amount), 0) / 100.0) AS cancelled_sum", + "coalesce(count(rds_cancelled), 0) AS cancelled_count" ) - .left_outer_join('recurring_donations rds_active', "rds_active.id=recurring_donations.id AND #{is_external_active_clause('rds_active')}") - .left_outer_join('recurring_donations rds_inactive', "rds_inactive.id=recurring_donations.id AND #{is_external_cancelled_clause('rds_inactive')}") - .left_outer_join('recurring_donations rds_failed', "rds_failed.id=recurring_donations.id AND #{is_failed_clause('rds_failed')}") - .left_outer_join('recurring_donations rds_cancelled', "rds_cancelled.id=recurring_donations.id AND #{is_cancelled_clause('rds_cancelled')}") - .where('recurring_donations.nonprofit_id=$id', id: np_id) + .left_outer_join("recurring_donations rds_active", "rds_active.id=recurring_donations.id AND #{is_external_active_clause("rds_active")}") + .left_outer_join("recurring_donations rds_inactive", "rds_inactive.id=recurring_donations.id AND #{is_external_cancelled_clause("rds_inactive")}") + .left_outer_join("recurring_donations rds_failed", "rds_failed.id=recurring_donations.id AND #{is_failed_clause("rds_failed")}") + .left_outer_join("recurring_donations rds_cancelled", "rds_cancelled.id=recurring_donations.id AND #{is_cancelled_clause("rds_cancelled")}") + .where("recurring_donations.nonprofit_id=$id", id: np_id) ).first end @@ -284,29 +284,29 @@ def self.is_failed_clause(field_for_rd) end def self.last_charge - Qexpr.new.select(:donation_id, 'MAX(created_at) AS created_at') - .from(:charges) - .where("status != 'failed'") - .group_by('donation_id') - .as('last_charge') + Qexpr.new.select(:donation_id, "MAX(created_at) AS created_at") + .from(:charges) + .where("status != 'failed'") + .group_by("donation_id") + .as("last_charge") end def self.export_for_transfer(nonprofit_id) - items = RecurringDonation.where('nonprofit_id = ?', nonprofit_id).active.includes('supporter').includes('card').to_a + items = RecurringDonation.where("nonprofit_id = ?", nonprofit_id).active.includes("supporter").includes("card").to_a output = items.map do |i| - { supporter: i.supporter.id, - supporter_name: i.supporter.name, - supporter_email: i.supporter.email, - amount: i.amount, - paydate: i.paydate, - card: i.card.stripe_card_id } + {supporter: i.supporter.id, + supporter_name: i.supporter.name, + supporter_email: i.supporter.email, + amount: i.amount, + paydate: i.paydate, + card: i.card.stripe_card_id} end output.to_a end def self.update_amount_with_currency(query_row, currency) # Skip header row - if query_row[1] != 'Amount' + if query_row[1] != "Amount" query_row[1] = Format::Currency.print_currency(query_row[1], currency, true, true) end query_row diff --git a/app/legacy_lib/query_roles.rb b/app/legacy_lib/query_roles.rb index b4dbec4709..3966842d8c 100644 --- a/app/legacy_lib/query_roles.rb +++ b/app/legacy_lib/query_roles.rb @@ -4,19 +4,19 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module QueryRoles def self.user_has_role?(user_id, role_names, host_id = nil) - expr = Qx.select('COUNT(roles)').from(:roles) - .where('name IN ($names)', names: Array(role_names)) - .and_where(user_id: user_id) + expr = Qx.select("COUNT(roles)").from(:roles) + .where("name IN ($names)", names: Array(role_names)) + .and_where(user_id: user_id) expr = expr.and_where(host_id: host_id) if host_id - expr.execute.first['count'] > 0 + expr.execute.first["count"] > 0 end # Get host tables -- host can be nonprofit, campaign, event def self.host_ids(user_id, role_names) - Qx.select('host_id').from(:roles) + Qx.select("host_id").from(:roles) .where(user_id: user_id) - .and_where('roles.name IN ($names)', names: role_names) - .execute.map { |h| h['host_id'] } + .and_where("roles.name IN ($names)", names: role_names) + .execute.map { |h| h["host_id"] } end def self.is_nonprofit_user?(user_id, np_id) diff --git a/app/legacy_lib/query_source_token.rb b/app/legacy_lib/query_source_token.rb index a7729e9a48..51367afff5 100644 --- a/app/legacy_lib/query_source_token.rb +++ b/app/legacy_lib/query_source_token.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module QuerySourceToken - EXPIRED_TOKEN_MESSAGE = 'There was an error processing your card and it was not charged. Please try again.' + EXPIRED_TOKEN_MESSAGE = "There was an error processing your card and it was not charged. Please try again." AUTH_ERROR_MESSAGE = "You're not authorized to make this charge" # @param [String] source_token @@ -14,9 +14,9 @@ module QuerySourceToken # @raise [ExpiredTokenError] when the source token has already been used too many times # or we're past the expiration date def self.get_and_increment_source_token(token, user = nil) - ParamValidation.new({ token: token }, - token: { required: true, format: UUID::Regex }) - source_token = SourceToken.where('token = ?', token).first + ParamValidation.new({token: token}, + token: {required: true, format: UUID::Regex}) + source_token = SourceToken.where("token = ?", token).first if source_token source_token.with_lock do unless source_token_unexpired?(source_token) diff --git a/app/legacy_lib/query_supporters.rb b/app/legacy_lib/query_supporters.rb index c2063e8a60..a0c1547b15 100644 --- a/app/legacy_lib/query_supporters.rb +++ b/app/legacy_lib/query_supporters.rb @@ -6,34 +6,34 @@ module QuerySupporters # Query supporters and their donations and gift levels for a campaign def self.campaign_list_expr(np_id, campaign_id, query) - expr = Qexpr.new.from('supporters') - .left_outer_join('donations', 'donations.supporter_id=supporters.id') - .left_outer_join('campaign_gifts', 'donations.id=campaign_gifts.donation_id') - .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') - .join_lateral(:payments, Qx - .select('payments.id, payments.gross_amount').from(:payments) - .where('payments.donation_id = donations.id') - .order_by('payments.created_at ASC') + expr = Qexpr.new.from("supporters") + .left_outer_join("donations", "donations.supporter_id=supporters.id") + .left_outer_join("campaign_gifts", "donations.id=campaign_gifts.donation_id") + .left_outer_join("campaign_gift_options", "campaign_gifts.campaign_gift_option_id=campaign_gift_options.id") + .join_lateral(:payments, Qx + .select("payments.id, payments.gross_amount").from(:payments) + .where("payments.donation_id = donations.id") + .order_by("payments.created_at ASC") .limit(1).parse, true) - .join(Qx.select('id, profile_id').from('campaigns') + .join(Qx.select("id, profile_id").from("campaigns") .where("id IN (#{QueryCampaigns .get_campaign_and_children(campaign_id) - .parse})").as('campaigns').parse, - 'donations.campaign_id=campaigns.id') - .join(Qx.select('users.id, profiles.id AS profiles_id, users.email') - .from('users') - .add_join('profiles', 'profiles.user_id = users.id') - .as('users').parse, 'users.profiles_id=campaigns.profile_id') - .where('supporters.nonprofit_id=$id', id: np_id) - .group_by('supporters.id') - .order_by('MAX(donations.date) DESC') + .parse})").as("campaigns").parse, + "donations.campaign_id=campaigns.id") + .join(Qx.select("users.id, profiles.id AS profiles_id, users.email") + .from("users") + .add_join("profiles", "profiles.user_id = users.id") + .as("users").parse, "users.profiles_id=campaigns.profile_id") + .where("supporters.nonprofit_id=$id", id: np_id) + .group_by("supporters.id") + .order_by("MAX(donations.date) DESC") if query[:search].present? expr = expr.where(%( supporters.name ILIKE $search OR supporters.email ILIKE $search OR campaign_gift_options.name ILIKE $search - ), search: '%' + query[:search] + '%') + ), search: "%" + query[:search] + "%") end expr end @@ -45,20 +45,20 @@ def self.campaign_list(np_id, campaign_id, query) data = Psql.execute( campaign_list_expr(np_id, campaign_id, query).select( - 'supporters.id', - 'supporters.name', - 'supporters.email', - 'SUM(payments.gross_amount) AS total_raised', - 'ARRAY_AGG(DISTINCT campaign_gift_options.name) AS campaign_gift_names', - 'DATE(MAX(donations.created_at)) AS latest_gift', - 'ARRAY_AGG(DISTINCT users.email) AS campaign_creator_emails' + "supporters.id", + "supporters.name", + "supporters.email", + "SUM(payments.gross_amount) AS total_raised", + "ARRAY_AGG(DISTINCT campaign_gift_options.name) AS campaign_gift_names", + "DATE(MAX(donations.created_at)) AS latest_gift", + "ARRAY_AGG(DISTINCT users.email) AS campaign_creator_emails" ).limit(limit).offset(offset) ) total_count = Psql.execute( - Qexpr.new.select('COUNT(s)') - .from(campaign_list_expr(np_id, campaign_id, query).remove(:order_by).select('supporters.id').as('s').parse) - ).first['count'] + Qexpr.new.select("COUNT(s)") + .from(campaign_list_expr(np_id, campaign_id, query).remove(:order_by).select("supporters.id").as("s").parse) + ).first["count"] { data: data, @@ -69,9 +69,9 @@ def self.campaign_list(np_id, campaign_id, query) def self.full_search_metrics(np_id, query) total_count = full_filter_expr(np_id, query) - .select('COUNT(supporters)') - .remove_clause(:order_by) - .execute.first['count'] + .select("COUNT(supporters)") + .remove_clause(:order_by) + .execute.first["count"] { total_count: total_count, @@ -82,11 +82,11 @@ def self.full_search_metrics(np_id, query) # Full supporter search mainly for /nonprofits/id/supporters dashboard def self.full_search(np_id, query) select = [ - 'supporters.name', - 'supporters.email', - 'supporters.is_unsubscribed_from_emails', - 'supporters.id AS id', - 'tags.names AS tags', + "supporters.name", + "supporters.email", + "supporters.is_unsubscribed_from_emails", + "supporters.id AS id", + "tags.names AS tags", 'to_char( timezone( COALESCE(nonprofits.timezone, \'UTC\'), @@ -94,36 +94,36 @@ def self.full_search(np_id, query) ), \'MM/DD/YY\' ) AS last_contribution', - 'payments.sum AS total_raised' + "payments.sum AS total_raised" ] - select += query[:select].split(',') if query[:select] + select += query[:select].split(",") if query[:select] supps = full_filter_expr(np_id, query) - .select(*select) - .paginate(query[:page].to_i, 30) - .execute + .select(*select) + .paginate(query[:page].to_i, 30) + .execute - { data: supps } + {data: supps} end def self._full_search(np_id, query) select = [ - 'supporters.name', - 'supporters.email', - 'supporters.is_unsubscribed_from_emails', - 'supporters.id AS id', - 'tags.names AS tags', + "supporters.name", + "supporters.email", + "supporters.is_unsubscribed_from_emails", + "supporters.id AS id", + "tags.names AS tags", "to_char(payments.max_date, 'MM/DD/YY') AS last_contribution", - 'payments.sum AS total_raised' + "payments.sum AS total_raised" ] - select += query[:select].split(',') if query[:select] + select += query[:select].split(",") if query[:select] supps = full_filter_expr(np_id, query) - .select(*select) - .paginate(query[:page].to_i, query[:page_length].to_i) - .execute + .select(*select) + .paginate(query[:page].to_i, query[:page_length].to_i) + .execute - { data: supps } + {data: supps} end # # Given a list of supporters, you may want to remove duplicates from those supporters. @@ -153,138 +153,138 @@ def self._full_search(np_id, query) # Perform all filters and search for /nonprofits/id/supporters dashboard and export def self.full_filter_expr(np_id, query) payments_subquery = - Qx.select('supporter_id', 'SUM(gross_amount)', 'MAX(date) AS max_date', 'MIN(date) AS min_date', 'COUNT(*) AS count') + Qx.select("supporter_id", "SUM(gross_amount)", "MAX(date) AS max_date", "MIN(date) AS min_date", "COUNT(*) AS count") .from( - Qx.select('supporter_id', 'date', 'gross_amount') + Qx.select("supporter_id", "date", "gross_amount") .from(:payments) - .join(Qx.select('id') + .join(Qx.select("id") .from(:supporters) .where("supporters.nonprofit_id = $id and deleted != 'true'", id: np_id) - .as('payments_to_supporters'), 'payments_to_supporters.id = payments.supporter_id') - .as('outer_from_payment_to_supporter') + .as("payments_to_supporters"), "payments_to_supporters.id = payments.supporter_id") + .as("outer_from_payment_to_supporter") .parse ) .group_by(:supporter_id) .as(:payments) - tags_subquery = Qx.select('tag_joins.supporter_id', 'ARRAY_AGG(tag_definitions.id) AS ids', 'ARRAY_AGG(tag_definitions.name::text) AS names') - .from(:tag_joins) - .join(:tag_definitions, 'tag_definitions.id=tag_joins.tag_definition_id') - .where('tag_definitions.deleted IS NULL') - .group_by('tag_joins.supporter_id') - .as(:tags) + tags_subquery = Qx.select("tag_joins.supporter_id", "ARRAY_AGG(tag_definitions.id) AS ids", "ARRAY_AGG(tag_definitions.name::text) AS names") + .from(:tag_joins) + .join(:tag_definitions, "tag_definitions.id=tag_joins.tag_definition_id") + .where("tag_definitions.deleted IS NULL") + .group_by("tag_joins.supporter_id") + .as(:tags) - expr = Qx.select('supporters.id') + expr = Qx.select("supporters.id") .from(:supporters) - .join('nonprofits', 'nonprofits.id=supporters.nonprofit_id') + .join("nonprofits", "nonprofits.id=supporters.nonprofit_id") .where( - ['supporters.nonprofit_id=$id', id: np_id.to_i], - ['supporters.deleted != true'] + ["supporters.nonprofit_id=$id", id: np_id.to_i], + ["supporters.deleted != true"] ) .left_join( - [tags_subquery, 'tags.supporter_id=supporters.id'], - [payments_subquery, 'payments.supporter_id=supporters.id'] + [tags_subquery, "tags.supporter_id=supporters.id"], + [payments_subquery, "payments.supporter_id=supporters.id"] ) - .order_by('payments.max_date DESC NULLS LAST') + .order_by("payments.max_date DESC NULLS LAST") if query[:last_payment_after].present? - expr = expr.and_where("payments.max_date > timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $d))", d: Chronic.parse(query[:last_payment_after]).beginning_of_day) + expr = expr.and_where("payments.max_date > timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $d))", d: Chronic.parse(query[:last_payment_after]).beginning_of_day) end if query[:last_payment_before].present? - expr = expr.and_where("payments.max_date < timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $d))", d: Chronic.parse(query[:last_payment_before]).beginning_of_day) + expr = expr.and_where("payments.max_date < timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $d))", d: Chronic.parse(query[:last_payment_before]).beginning_of_day) end if query[:first_payment_after].present? - expr = expr.and_where("payments.min_date > timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $d))", d: Chronic.parse(query[:first_payment_after]).beginning_of_day) + expr = expr.and_where("payments.min_date > timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $d))", d: Chronic.parse(query[:first_payment_after]).beginning_of_day) end if query[:first_payment_before].present? - expr = expr.and_where("payments.min_date < timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $d))", d: Chronic.parse(query[:first_payment_before]).beginning_of_day) + expr = expr.and_where("payments.min_date < timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $d))", d: Chronic.parse(query[:first_payment_before]).beginning_of_day) end if query[:total_raised_greater_than].present? - expr = expr.and_where('payments.sum > $amount', amount: query[:total_raised_greater_than].to_i * 100) + expr = expr.and_where("payments.sum > $amount", amount: query[:total_raised_greater_than].to_i * 100) end if query[:total_raised_less_than].present? - expr = expr.and_where('payments.sum < $amount OR payments.supporter_id IS NULL', amount: query[:total_raised_less_than].to_i * 100) + expr = expr.and_where("payments.sum < $amount OR payments.supporter_id IS NULL", amount: query[:total_raised_less_than].to_i * 100) end if %w[week month quarter year].include? query[:has_contributed_during] - d = Time.current.send('beginning_of_' + query[:has_contributed_during]) - expr = expr.and_where("payments.max_date >= timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $d))", d: d) + d = Time.current.send("beginning_of_" + query[:has_contributed_during]) + expr = expr.and_where("payments.max_date >= timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $d))", d: d) end if %w[week month quarter year].include? query[:has_not_contributed_during] - d = Time.current.send('beginning_of_' + query[:has_not_contributed_during]) - expr = expr.and_where("payments.count = 0 OR payments.max_date <= timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $d))", d: d) + d = Time.current.send("beginning_of_" + query[:has_not_contributed_during]) + expr = expr.and_where("payments.count = 0 OR payments.max_date <= timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $d))", d: d) end if query[:MAX_payment_before].present? date_ago = Timespan::TimeUnits[query[:MAX_payment_before]].utc - expr = expr.and_where("payments.max_date < timezone(COALESCE(nonprofits.timezone, \'UTC\'), timezone(\'UTC\', $date)) OR payments.count = 0", date: date_ago) + expr = expr.and_where("payments.max_date < timezone(COALESCE(nonprofits.timezone, 'UTC'), timezone('UTC', $date)) OR payments.count = 0", date: date_ago) end if query[:search].present? expr = expr.and_where(%( supporters.name ILIKE $search OR supporters.email ILIKE $search OR supporters.organization ILIKE $search - ), search: '%' + query[:search] + '%') + ), search: "%" + query[:search] + "%") end if query[:notes].present? notes_subquery = Qx.select("STRING_AGG(content, ' ') as content, supporter_id") - .from(:supporter_notes) - .group_by(:supporter_id) - .as(:notes) - expr = expr.add_left_join(notes_subquery, 'notes.supporter_id=supporters.id') - .and_where("to_tsvector('english', notes.content) @@ plainto_tsquery('english', $notes)", notes: query[:notes]) + .from(:supporter_notes) + .group_by(:supporter_id) + .as(:notes) + expr = expr.add_left_join(notes_subquery, "notes.supporter_id=supporters.id") + .and_where("to_tsvector('english', notes.content) @@ plainto_tsquery('english', $notes)", notes: query[:notes]) end if query[:custom_fields].present? - c_f_subquery = Qx.select("STRING_AGG(value, ' ') as value", 'supporter_id') - .from(:custom_field_joins) - .group_by('custom_field_joins.supporter_id') - .as(:custom_fields) - expr = expr.add_left_join(c_f_subquery, 'custom_fields.supporter_id=supporters.id') - .and_where("to_tsvector('english', custom_fields.value) @@ plainto_tsquery('english', $custom_fields)", custom_fields: query[:custom_fields]) + c_f_subquery = Qx.select("STRING_AGG(value, ' ') as value", "supporter_id") + .from(:custom_field_joins) + .group_by("custom_field_joins.supporter_id") + .as(:custom_fields) + expr = expr.add_left_join(c_f_subquery, "custom_fields.supporter_id=supporters.id") + .and_where("to_tsvector('english', custom_fields.value) @@ plainto_tsquery('english', $custom_fields)", custom_fields: query[:custom_fields]) end if query[:location].present? - expr = expr.and_where('lower(supporters.city) LIKE $city OR lower(supporters.zip_code) LIKE $zip', city: query[:location].downcase, zip: query[:location].downcase) + expr = expr.and_where("lower(supporters.city) LIKE $city OR lower(supporters.zip_code) LIKE $zip", city: query[:location].downcase, zip: query[:location].downcase) end if query[:recurring].present? - rec_ps_subquery = Qx.select('payments.count', 'payments.supporter_id') - .from(:payments) - .where("kind='RecurringDonation'") - .group_by('payments.supporter_id') - .as(:rec_ps) - expr = expr.add_left_join(rec_ps_subquery, 'rec_ps.supporter_id=supporters.id') - .and_where('rec_ps.count > 0') + rec_ps_subquery = Qx.select("payments.count", "payments.supporter_id") + .from(:payments) + .where("kind='RecurringDonation'") + .group_by("payments.supporter_id") + .as(:rec_ps) + expr = expr.add_left_join(rec_ps_subquery, "rec_ps.supporter_id=supporters.id") + .and_where("rec_ps.count > 0") end if query[:ids].present? - expr = expr.and_where('supporters.id IN ($ids)', ids: query[:ids].split(',').map(&:to_i)) + expr = expr.and_where("supporters.id IN ($ids)", ids: query[:ids].split(",").map(&:to_i)) end if query[:select].present? - expr = expr.select(*query[:select].split(',').map { |x| Qx.quote_ident(x) }) + expr = expr.select(*query[:select].split(",").map { |x| Qx.quote_ident(x) }) end # Sort by supporters who have all of the list of tag names if query[:tags].present? - tag_ids = (query[:tags].is_a?(String) ? query[:tags].split(',') : query[:tags]).map(&:to_i) - expr = expr.and_where('tags.ids @> ARRAY[$tag_ids]', tag_ids: tag_ids) + tag_ids = (query[:tags].is_a?(String) ? query[:tags].split(",") : query[:tags]).map(&:to_i) + expr = expr.and_where("tags.ids @> ARRAY[$tag_ids]", tag_ids: tag_ids) end if query[:campaign_id].present? - expr = expr.add_join('donations', "donations.supporter_id=supporters.id AND donations.campaign_id IN (#{QueryCampaigns + expr = expr.add_join("donations", "donations.supporter_id=supporters.id AND donations.campaign_id IN (#{QueryCampaigns .get_campaign_and_children(query[:campaign_id].to_i) .parse})") end if query[:event_id].present? - select_tickets_supporters = Qx.select('event_ticket_supporters.supporter_id') - .from( - Qx.select('MAX(tickets.event_id) AS event_id', 'tickets.supporter_id') - .from(:tickets) - .where('event_id = $event_id', event_id: query[:event_id]) - .group_by(:supporter_id).as('event_ticket_supporters').parse.to_s - ) + select_tickets_supporters = Qx.select("event_ticket_supporters.supporter_id") + .from( + Qx.select("MAX(tickets.event_id) AS event_id", "tickets.supporter_id") + .from(:tickets) + .where("event_id = $event_id", event_id: query[:event_id]) + .group_by(:supporter_id).as("event_ticket_supporters").parse.to_s + ) select_donation_supporters = - Qx.select('event_donation_supporters.supporter_id') + Qx.select("event_donation_supporters.supporter_id") .from( - Qx.select('MAX(donations.event_id) AS event_id', 'donations.supporter_id') + Qx.select("MAX(donations.event_id) AS event_id", "donations.supporter_id") .from(:donations) - .where('event_id = $event_id', event_id: query[:event_id]) - .group_by(:supporter_id).as('event_donation_supporters').parse.to_s + .where("event_id = $event_id", event_id: query[:event_id]) + .group_by(:supporter_id).as("event_donation_supporters").parse.to_s ) union_expr = "( @@ -294,26 +294,26 @@ def self.full_filter_expr(np_id, query) ) AS event_supporters" expr = expr - .add_join( - union_expr, - 'event_supporters.supporter_id=supporters.id' - ) + .add_join( + union_expr, + "event_supporters.supporter_id=supporters.id" + ) end if %w[asc desc].include? query[:sort_name] - expr = expr.order_by(['supporters.name', query[:sort_name]]) + expr = expr.order_by(["supporters.name", query[:sort_name]]) end if %w[asc desc].include? query[:sort_contributed] - expr = expr.and_where('payments.sum > 0').order_by(['payments.sum', query[:sort_contributed]]) + expr = expr.and_where("payments.sum > 0").order_by(["payments.sum", query[:sort_contributed]]) end if %w[asc desc].include? query[:sort_last_payment] - expr = expr.order_by(['payments.max_date', "#{query[:sort_last_payment].upcase} NULLS LAST"]) + expr = expr.order_by(["payments.max_date", "#{query[:sort_last_payment].upcase} NULLS LAST"]) end expr end def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) - ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, - query: { required: true, is_hash: true }) + ParamValidation.new({npo_id: npo_id, query: query}, npo_id: {required: true, is_int: true}, + query: {required: true, is_hash: true}) QxQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_export(npo_id, query, offset, limit, skip_header) @@ -324,9 +324,9 @@ def self.get_chunk_of_export(np_id, query, offset = nil, limit = nil, skip_heade QxQueryChunker.get_chunk_of_query(offset, limit, skip_header) do expr = full_filter_expr(np_id, query) selects = supporter_export_selections.concat([ - '(payments.sum / 100)::money::text AS total_contributed', - 'supporters.id AS id' - ]) + "(payments.sum / 100)::money::text AS total_contributed", + "supporters.id AS id" + ]) if query[:export_custom_fields] # Add a select/csv-column for every custom field definition for this nonprofit # and add a left join for every custom field definition @@ -335,47 +335,47 @@ def self.get_chunk_of_export(np_id, query, offset = nil, limit = nil, skip_heade # FROM supporters # LEFT JOIN custom_field_joins AS export_cfj_Employer ON export_cfj_Employer.supporter_id=supporters.id AND export_cfj_Employer.custom_field_definition_id=99 # ... - ids = query[:export_custom_fields].split(',').map(&:to_i) + ids = query[:export_custom_fields].split(",").map(&:to_i) if ids.any? - cfms = Qx.select('name', 'id').from(:custom_field_definitions).where(nonprofit_id: np_id).and_where('id IN ($ids)', ids: ids).ex + cfms = Qx.select("name", "id").from(:custom_field_definitions).where(nonprofit_id: np_id).and_where("id IN ($ids)", ids: ids).ex cfms.compact.map do |cfm| - table_alias = "cfjs_#{cfm['name'].delete('$')}" + table_alias = "cfjs_#{cfm["name"].delete("$")}" table_alias_quot = "\"#{table_alias}\"" - field_join_subq = Qx.select("STRING_AGG(value, ',') as value", 'supporter_id') - .from('custom_field_joins') - .join('custom_field_definitions', 'custom_field_definitions.id=custom_field_joins.custom_field_definition_id') - .where('custom_field_definitions.id=$id', id: cfm['id']) - .group_by(:supporter_id) - .as(table_alias) + field_join_subq = Qx.select("STRING_AGG(value, ',') as value", "supporter_id") + .from("custom_field_joins") + .join("custom_field_definitions", "custom_field_definitions.id=custom_field_joins.custom_field_definition_id") + .where("custom_field_definitions.id=$id", id: cfm["id"]) + .group_by(:supporter_id) + .as(table_alias) expr.add_left_join(field_join_subq, "#{table_alias_quot}.supporter_id=supporters.id") - selects = selects.concat(["#{table_alias_quot}.value AS \"#{cfm['name']}\""]) + selects = selects.concat(["#{table_alias_quot}.value AS \"#{cfm["name"]}\""]) end end end - get_last_payment_query = Qx.select('supporter_id', 'MAX(date) AS date') - .from(:payments) - .group_by('supporter_id') - .as('last_payment') + get_last_payment_query = Qx.select("supporter_id", "MAX(date) AS date") + .from(:payments) + .group_by("supporter_id") + .as("last_payment") - expr.add_left_join(get_last_payment_query, 'last_payment.supporter_id = supporters.id') + expr.add_left_join(get_last_payment_query, "last_payment.supporter_id = supporters.id") selects = selects.concat(['last_payment.date as "Last Payment Received"']) - supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", 'supporter_notes.supporter_id') - .from(:supporter_notes) - .group_by('supporter_notes.supporter_id') - .as('supporter_note_query') + supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", "supporter_notes.supporter_id") + .from(:supporter_notes) + .group_by("supporter_notes.supporter_id") + .as("supporter_note_query") - expr.add_left_join(supporter_note_query, 'supporter_note_query.supporter_id=supporters.id') - selects = selects.concat(['supporter_note_query.notes AS notes']).concat(["ARRAY_TO_STRING(tags.names, ',') as tags"]) + expr.add_left_join(supporter_note_query, "supporter_note_query.supporter_id=supporters.id") + selects = selects.concat(["supporter_note_query.notes AS notes"]).concat(["ARRAY_TO_STRING(tags.names, ',') as tags"]) expr.select(selects) end end def self.supporter_note_export_enumerable(npo_id, query, chunk_limit = 35_000) - ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, - query: { required: true, is_hash: true }) + ParamValidation.new({npo_id: npo_id, query: query}, npo_id: {required: true, is_int: true}, + query: {required: true, is_hash: true}) QxQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_supporter_note_export(npo_id, query, offset, limit, skip_header) @@ -386,12 +386,12 @@ def self.get_chunk_of_supporter_note_export(np_id, query, offset = nil, limit = QxQueryChunker.get_chunk_of_query(offset, limit, skip_header) do expr = full_filter_expr(np_id, query) supporter_note_select = [ - 'supporters.id', - 'supporters.email', + "supporters.id", + "supporters.email", 'supporter_notes.created_at as "Note Created At"', 'supporter_notes.content "Note Contents"' ] - expr.add_join(:supporter_notes, 'supporter_notes.supporter_id = supporters.id') + expr.add_join(:supporter_notes, "supporter_notes.supporter_id = supporters.id") expr.select(supporter_note_select) end @@ -401,9 +401,9 @@ def self.get_chunk_of_supporter_note_export(np_id, query, offset = nil, limit = def self.for_export(np_id, query) expr = full_filter_expr(np_id, query) selects = supporter_export_selections.concat([ - '(payments.sum / 100)::money::text AS total_contributed', - 'supporters.id AS id' - ]) + "(payments.sum / 100)::money::text AS total_contributed", + "supporters.id AS id" + ]) if query[:export_custom_fields] # Add a select/csv-column for every custom field definition for this nonprofit # and add a left join for every custom field definition @@ -412,32 +412,32 @@ def self.for_export(np_id, query) # FROM supporters # LEFT JOIN custom_field_joins AS export_cfj_Employer ON export_cfj_Employer.supporter_id=supporters.id AND export_cfj_Employer.custom_field_definition_id=99 # ... - ids = query[:export_custom_fields].split(',').map(&:to_i) + ids = query[:export_custom_fields].split(",").map(&:to_i) if ids.any? - cfms = Qx.select('name', 'id').from(:custom_field_definitions).where(nonprofit_id: np_id).and_where('id IN ($ids)', ids: ids).ex + cfms = Qx.select("name", "id").from(:custom_field_definitions).where(nonprofit_id: np_id).and_where("id IN ($ids)", ids: ids).ex cfms.compact.map do |cfm| - table_alias = "cfjs_#{cfm['name'].delete('$')}" + table_alias = "cfjs_#{cfm["name"].delete("$")}" table_alias_quot = "\"#{table_alias}\"" - field_join_subq = Qx.select("STRING_AGG(value, ',') as value", 'supporter_id') - .from('custom_field_joins') - .join('custom_field_definitions', 'custom_field_definitions.id=custom_field_joins.custom_field_definition_id') - .where('custom_field_definitions.id=$id', id: cfm['id']) - .group_by(:supporter_id) - .as(table_alias) + field_join_subq = Qx.select("STRING_AGG(value, ',') as value", "supporter_id") + .from("custom_field_joins") + .join("custom_field_definitions", "custom_field_definitions.id=custom_field_joins.custom_field_definition_id") + .where("custom_field_definitions.id=$id", id: cfm["id"]) + .group_by(:supporter_id) + .as(table_alias) expr.add_left_join(field_join_subq, "#{table_alias_quot}.supporter_id=supporters.id") - selects = selects.concat(["#{table_alias_quot}.value AS \"#{cfm['name']}\""]) + selects = selects.concat(["#{table_alias_quot}.value AS \"#{cfm["name"]}\""]) end end end - supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", 'supporter_notes.supporter_id') - .from(:supporter_notes) - .group_by('supporter_notes.supporter_id') - .as('supporter_note_query') + supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", "supporter_notes.supporter_id") + .from(:supporter_notes) + .group_by("supporter_notes.supporter_id") + .as("supporter_note_query") - expr.add_left_join(supporter_note_query, 'supporter_note_query.supporter_id=supporters.id') - selects = selects.concat(['supporter_note_query.notes AS notes']) + expr.add_left_join(supporter_note_query, "supporter_note_query.supporter_id=supporters.id") + selects = selects.concat(["supporter_note_query.notes AS notes"]) - expr.select(selects).execute(format: 'csv') + expr.select(selects).execute(format: "csv") end def self.supporter_export_selections @@ -462,11 +462,11 @@ def self.supporter_export_selections # Partial sql expression def self.dupes_expr(np_id) - Qx.select('ARRAY_AGG(id) AS ids') + Qx.select("ARRAY_AGG(id) AS ids") .from(:supporters) - .where('nonprofit_id=$id', id: np_id) + .where("nonprofit_id=$id", id: np_id) .and_where("deleted='f' OR deleted IS NULL") - .having('COUNT(id) > 1') + .having("COUNT(id) > 1") end # Merge on exact supporter and email match @@ -476,19 +476,19 @@ def self.dupes_expr(np_id) # (each sub-array is a group of duplicates) def self.dupes_on_email(np_id) dupes_expr(np_id) - .and_where('email IS NOT NULL') + .and_where("email IS NOT NULL") .and_where("email != ''") .group_by(:email) - .execute(format: 'csv')[1..-1] + .execute(format: "csv")[1..-1] .map(&:flatten) end # Find all duplicate supporters by the name column def self.dupes_on_name(np_id) dupes_expr(np_id) - .and_where('name IS NOT NULL') + .and_where("name IS NOT NULL") .group_by(:name) - .execute(format: 'csv')[1..-1] + .execute(format: "csv")[1..-1] .map(&:flatten) end @@ -497,8 +497,8 @@ def self.dupes_on_name(np_id) def self.dupes_on_name_and_email(np_id) dupes_expr(np_id) .and_where("name IS NOT NULL AND email IS NOT NULL AND email != ''") - .group_by('name, email') - .execute(format: 'csv')[1..-1] + .group_by("name, email") + .execute(format: "csv")[1..-1] .map(&:flatten) end @@ -507,31 +507,31 @@ def self.dupes_on_name_and_email(np_id) # Only including payments for the given year def self.end_of_year_donor_report(np_id, year) supporter_expr = Qexpr.new - .select(supporter_export_selections.concat(["(payments.sum / 100.0)::money::text AS \"Total Contributions #{year}\"", 'supporters.id'])) - .from(:supporters) - .join(Qexpr.new - .select('SUM(gross_amount)', 'supporter_id') + .select(supporter_export_selections.concat(["(payments.sum / 100.0)::money::text AS \"Total Contributions #{year}\"", "supporters.id"])) + .from(:supporters) + .join(Qexpr.new + .select("SUM(gross_amount)", "supporter_id") .from(:payments) .group_by(:supporter_id) - .where('date >= $date', date: "#{year}-01-01 00:00:00 UTC") - .where('date < $date', date: "#{year + 1}-01-01 00:00:00 UTC") - .as(:payments), 'payments.supporter_id=supporters.id') - .where('payments.sum > 25000') - .as('supporters') + .where("date >= $date", date: "#{year}-01-01 00:00:00 UTC") + .where("date < $date", date: "#{year + 1}-01-01 00:00:00 UTC") + .as(:payments), "payments.supporter_id=supporters.id") + .where("payments.sum > 25000") + .as("supporters") Psql.execute_vectors( Qexpr.new .select( - 'supporters.*', + "supporters.*", '(payments.gross_amount / 100.0)::money::text AS "Donation Amount"', 'payments.date AS "Donation Date"', 'payments.towards AS "Designation"' ) .from(:payments) - .join(supporter_expr, 'supporters.id = payments.supporter_id') - .where('payments.nonprofit_id = $id', id: np_id) - .where('payments.date >= $date', date: "#{year}-01-01 00:00:00 UTC") - .where('payments.date < $date', date: "#{year + 1}-01-01 00:00:00 UTC") + .join(supporter_expr, "supporters.id = payments.supporter_id") + .where("payments.nonprofit_id = $id", id: np_id) + .where("payments.date >= $date", date: "#{year}-01-01 00:00:00 UTC") + .where("payments.date < $date", date: "#{year + 1}-01-01 00:00:00 UTC") .order_by('supporters."MAX Name", payments.date DESC') ) end @@ -540,72 +540,72 @@ def self.end_of_year_donor_report(np_id, year) # which gets concated with an optional array of additional selects # used for merging supporters, crm profile and info card def self.profile_selects(arr = []) - ['supporters.id', - 'supporters.name', - 'supporters.email', - 'supporters.address', - 'supporters.state_code', - 'supporters.city', - 'supporters.zip_code', - 'supporters.country', - 'supporters.organization', - 'supporters.phone'] + arr + ["supporters.id", + "supporters.name", + "supporters.email", + "supporters.address", + "supporters.state_code", + "supporters.city", + "supporters.zip_code", + "supporters.country", + "supporters.organization", + "supporters.phone"] + arr end # used on crm profile and info card def self.profile_payments_subquery - Qx.select('supporter_id', 'SUM(gross_amount)', 'COUNT(id) AS count') - .from('payments') - .group_by('supporter_id') - .as('payments') + Qx.select("supporter_id", "SUM(gross_amount)", "COUNT(id) AS count") + .from("payments") + .group_by("supporter_id") + .as("payments") end # Get a large set of detailed info for a single supporter, to be displayed in # the side panel details of the supporter listing after clicking a row. def self.for_crm_profile(npo_id, ids) selects = [ - 'supporters.created_at', - 'supporters.imported_at', - 'supporters.anonymous AS anon', - 'supporters.is_unsubscribed_from_emails', - 'COALESCE(MAX(payments.sum), 0) AS raised', - 'COALESCE(MAX(payments.count), 0) AS payments_count', - 'COALESCE(COUNT(recurring_donations.active), 0) AS recurring_donations_count', - 'MAX(full_contact_infos.full_name) AS fc_full_name', - 'MAX(full_contact_infos.age) AS fc_age', - 'MAX(full_contact_infos.location_general) AS fc_location_general', - 'MAX(full_contact_infos.websites) AS fc_websites' + "supporters.created_at", + "supporters.imported_at", + "supporters.anonymous AS anon", + "supporters.is_unsubscribed_from_emails", + "COALESCE(MAX(payments.sum), 0) AS raised", + "COALESCE(MAX(payments.count), 0) AS payments_count", + "COALESCE(COUNT(recurring_donations.active), 0) AS recurring_donations_count", + "MAX(full_contact_infos.full_name) AS fc_full_name", + "MAX(full_contact_infos.age) AS fc_age", + "MAX(full_contact_infos.location_general) AS fc_location_general", + "MAX(full_contact_infos.websites) AS fc_websites" ] Qx.select(*QuerySupporters.profile_selects(selects)) - .from('supporters') + .from("supporters") .left_join( - ['donations', 'donations.supporter_id=supporters.id'], - ['full_contact_infos', 'full_contact_infos.supporter_id=supporters.id'], - ['recurring_donations', 'recurring_donations.donation_id=donations.id'], - [QuerySupporters.profile_payments_subquery, 'payments.supporter_id=supporters.id'] + ["donations", "donations.supporter_id=supporters.id"], + ["full_contact_infos", "full_contact_infos.supporter_id=supporters.id"], + ["recurring_donations", "recurring_donations.donation_id=donations.id"], + [QuerySupporters.profile_payments_subquery, "payments.supporter_id=supporters.id"] ) - .group_by('supporters.id') - .where('supporters.id IN ($ids)', ids: ids) - .and_where('supporters.nonprofit_id = $id', id: npo_id) + .group_by("supporters.id") + .where("supporters.id IN ($ids)", ids: ids) + .and_where("supporters.nonprofit_id = $id", id: npo_id) .execute end def self.for_info_card(id) - selects = ['COALESCE(MAX(payments.sum), 0) AS raised'] + selects = ["COALESCE(MAX(payments.sum), 0) AS raised"] Qx.select(*QuerySupporters.profile_selects(selects)) - .from('supporters') - .left_join([QuerySupporters.profile_payments_subquery, 'payments.supporter_id=supporters.id']) - .group_by('supporters.id') - .where('supporters.id=$id', id: id) + .from("supporters") + .left_join([QuerySupporters.profile_payments_subquery, "payments.supporter_id=supporters.id"]) + .group_by("supporters.id") + .where("supporters.id=$id", id: id) .execute.first end def self.merge_data(ids) Qx.select(*QuerySupporters.profile_selects) - .from('supporters') - .group_by('supporters.id') - .where('supporters.id IN ($ids)', ids: ids.split(',')) + .from("supporters") + .group_by("supporters.id") + .where("supporters.id IN ($ids)", ids: ids.split(",")) .execute end @@ -617,8 +617,8 @@ def self.year_aggregate_report(npo_id, time_range_params) rescue ArgumentError => e raise ParamValidation::ValidationError.new(e.message, {}) end - ParamValidation.new({ npo_id: npo_id }, - npo_id: { required: true, is_integer: true }) + ParamValidation.new({npo_id: npo_id}, + npo_id: {required: true, is_integer: true}) aggregate_dons = %( array_to_string( array_agg( @@ -632,18 +632,18 @@ def self.year_aggregate_report(npo_id, time_range_params) ) AS "Payment History" ) selects = supporter_export_selections.concat([ - 'SUM(payments.gross_amount / 100)::text::money AS "Total Payments"', - 'MAX(payments.date)::date AS "Last Payment Date"', - 'AVG(payments.gross_amount / 100)::text::money AS "Average Payment"', - aggregate_dons - ]) + 'SUM(payments.gross_amount / 100)::text::money AS "Total Payments"', + 'MAX(payments.date)::date AS "Last Payment Date"', + 'AVG(payments.gross_amount / 100)::text::money AS "Average Payment"', + aggregate_dons + ]) Qx.select(selects) .from(:supporters) - .join('payments', 'payments.supporter_id=supporters.id AND payments.date::date >= $min_date AND payments.date::date < $max_date', min_date: min_date.to_date, max_date: max_date.to_date) - .where('supporters.nonprofit_id=$id', id: npo_id) - .group_by('supporters.id') + .join("payments", "payments.supporter_id=supporters.id AND payments.date::date >= $min_date AND payments.date::date < $max_date", min_date: min_date.to_date, max_date: max_date.to_date) + .where("supporters.nonprofit_id=$id", id: npo_id) + .group_by("supporters.id") .order_by("substring(trim(supporters.name) from '^.+ ([^\s]+)$')") - .execute(format: 'csv') + .execute(format: "csv") end def self.get_min_or_max_dates_for_range(time_range_params) @@ -665,38 +665,38 @@ def self.get_min_or_max_dates_for_range(time_range_params) return start, end_datetime || start + 1.year unless start.nil? end - raise ArgumentError, 'no valid time range provided' - rescue StandardError - raise ArgumentError, 'no valid time range provided' + raise ArgumentError, "no valid time range provided" + rescue + raise ArgumentError, "no valid time range provided" end def self.tag_joins(nonprofit_id, supporter_id) - Qx.select('tag_definitions.id', 'tag_definitions.name') - .from('tag_joins') - .left_join('tag_definitions', 'tag_definitions.id = tag_joins.tag_definition_id') + Qx.select("tag_definitions.id", "tag_definitions.name") + .from("tag_joins") + .left_join("tag_definitions", "tag_definitions.id = tag_joins.tag_definition_id") .where( - ['tag_joins.supporter_id = $id', id: supporter_id], - ['coalesce(tag_definitions.deleted, FALSE) = FALSE'], - ['tag_definitions.nonprofit_id = $id', id: nonprofit_id] + ["tag_joins.supporter_id = $id", id: supporter_id], + ["coalesce(tag_definitions.deleted, FALSE) = FALSE"], + ["tag_definitions.nonprofit_id = $id", id: nonprofit_id] ) .execute end # this is inefficient, don't use in live code def self.find_supporters_with_multiple_recurring_donations_evil_way(npo_id) - supporters = Supporter.where('supporters.nonprofit_id = ?', npo_id).includes(:recurring_donations) + supporters = Supporter.where("supporters.nonprofit_id = ?", npo_id).includes(:recurring_donations) supporters.select { |s| s.recurring_donations.length > 1 } end # this is inefficient, don't use in live code def self.find_supporters_with_multiple_active_recurring_donations_evil_way(npo_id) - supporters = Supporter.where('supporters.nonprofit_id = ?', npo_id).includes(:recurring_donations) + supporters = Supporter.where("supporters.nonprofit_id = ?", npo_id).includes(:recurring_donations) supporters.select { |s| s.recurring_donations.select(&:active).length > 1 } end def self.parse_convert_datetime(date) return date if date.is_a?(DateTime) return date.to_datetime if date.is_a?(Date) - return DateTime.parse(date) if date.is_a?(String) + DateTime.parse(date) if date.is_a?(String) end end diff --git a/app/legacy_lib/query_ticket_levels.rb b/app/legacy_lib/query_ticket_levels.rb index 50aecdee34..853db27034 100644 --- a/app/legacy_lib/query_ticket_levels.rb +++ b/app/legacy_lib/query_ticket_levels.rb @@ -10,8 +10,8 @@ module QueryTicketLevels # This could probably be more efficient. I didn't think of a way to calculate it within the query itself. # Although I think it's O(n), and n will always be quite small (the number of tickets someone buys) def self.gross_amount_from_tickets(tickets, discount_id) - amounts = TicketLevel.where('id IN (?)', tickets.map { |h| h['ticket_level_id'] }).map { |i| [i.id, i.amount] }.to_h - total = tickets.map { |t| amounts[t['ticket_level_id'].to_i].to_i * t['quantity'].to_i }.sum + amounts = TicketLevel.where("id IN (?)", tickets.map { |h| h["ticket_level_id"] }).map { |i| [i.id, i.amount] }.to_h + total = tickets.map { |t| amounts[t["ticket_level_id"].to_i].to_i * t["quantity"].to_i }.sum if discount_id perc = EventDiscount.find(discount_id).percent @@ -22,30 +22,30 @@ def self.gross_amount_from_tickets(tickets, discount_id) end def self.with_event_id(event_id, is_admin) - expr = Qx.select('ticket_levels.*', 'SUM(tickets.quantity) AS quantity') - .from(:ticket_levels) - .left_join([:tickets, 'ticket_levels.id=tickets.ticket_level_id']) - .group_by('ticket_levels.id') - .where('ticket_levels.event_id = $id', id: event_id) - .order_by("ticket_levels.order ASC, coalesce(ticket_levels.amount, 'Infinity'::float) ASC, LOWER(ticket_levels.name) ASC") # This puts free ticket levels at the bottom + expr = Qx.select("ticket_levels.*", "SUM(tickets.quantity) AS quantity") + .from(:ticket_levels) + .left_join([:tickets, "ticket_levels.id=tickets.ticket_level_id"]) + .group_by("ticket_levels.id") + .where("ticket_levels.event_id = $id", id: event_id) + .order_by("ticket_levels.order ASC, coalesce(ticket_levels.amount, 'Infinity'::float) ASC, LOWER(ticket_levels.name) ASC") # This puts free ticket levels at the bottom unless is_admin - expr = expr.and_where('coalesce(ticket_levels.admin_only, FALSE) = FALSE') + expr = expr.and_where("coalesce(ticket_levels.admin_only, FALSE) = FALSE") end expr.execute end def self.verify_tickets_available(tickets) - tickets.each do |data| + tickets.each do |data| next unless data[:quantity] != 0 tl = TicketLevel.find(data[:ticket_level_id]) next unless tl.limit && tl.limit > 0 - already_sold = Ticket.where('ticket_level_id = ?', data[:ticket_level_id]).sum('tickets.quantity') + already_sold = Ticket.where("ticket_level_id = ?", data[:ticket_level_id]).sum("tickets.quantity") unless (already_sold + data[:quantity]) <= tl.limit - raise NotEnoughQuantityError.new(TicketLevel, data[:ticket_level_id], data[:quantity], 'Oops! We sold out some of the tickets you wanted before ordering. Please refresh to see what tickets are still available.') + raise NotEnoughQuantityError.new(TicketLevel, data[:ticket_level_id], data[:quantity], "Oops! We sold out some of the tickets you wanted before ordering. Please refresh to see what tickets are still available.") end end end diff --git a/app/legacy_lib/query_tickets.rb b/app/legacy_lib/query_tickets.rb index 581cdd4706..86c37cfc52 100644 --- a/app/legacy_lib/query_tickets.rb +++ b/app/legacy_lib/query_tickets.rb @@ -5,50 +5,50 @@ module QueryTickets def self.attendees_expr(event_id, query) expr = Qexpr.new - .from('tickets') - .where('coalesce(tickets.deleted, FALSE) = FALSE') - .left_outer_join('event_discounts', 'event_discounts.id=tickets.event_discount_id') - .left_outer_join( - Qexpr.new.select('*') - .from(:supporters).group_by('id').as('supporters'), - 'tickets.supporter_id=supporters.id' - ) - .left_outer_join('charges', 'charges.id=tickets.charge_id') - .left_outer_join( - Qexpr.new.select('charge_id', 'SUM(coalesce(amount, 0)) AS amount') - .from(:refunds) - .group_by(:charge_id) - .as(:refunds), - 'refunds.charge_id=charges.id' - ) - .left_outer_join( - Qexpr.new.select('id', 'name', 'amount') - .from(:ticket_levels).group_by('id').as('ticket_levels'), - 'tickets.ticket_level_id=ticket_levels.id' - ) - .left_outer_join( - Qexpr.new.select('token', 'tokenizable_id').from(:source_tokens).group_by('token', 'tokenizable_id').as('source_tokens'), - 'tickets.source_token_id=source_tokens.token' - ) - .left_outer_join( - # TODO: this does not support anything other than cards! - Qexpr.new.select('id', 'name').from(:cards).group_by('id', 'name').as('cards'), - 'source_tokens.tokenizable_id = cards.id' - ) - .left_outer_join( - Qexpr.new.select('supporter_id', 'MAX(event_id) AS event_id', 'SUM(amount) AS total_amount') - .from(:donations).where('event_id=$id', id: event_id).group_by('supporter_id').as(:donations), - 'donations.supporter_id=supporters.id AND donations.event_id=$id', id: event_id - ) - .where('tickets.event_id=$id', id: event_id) - .order_by('tickets.bid_id DESC') + .from("tickets") + .where("coalesce(tickets.deleted, FALSE) = FALSE") + .left_outer_join("event_discounts", "event_discounts.id=tickets.event_discount_id") + .left_outer_join( + Qexpr.new.select("*") + .from(:supporters).group_by("id").as("supporters"), + "tickets.supporter_id=supporters.id" + ) + .left_outer_join("charges", "charges.id=tickets.charge_id") + .left_outer_join( + Qexpr.new.select("charge_id", "SUM(coalesce(amount, 0)) AS amount") + .from(:refunds) + .group_by(:charge_id) + .as(:refunds), + "refunds.charge_id=charges.id" + ) + .left_outer_join( + Qexpr.new.select("id", "name", "amount") + .from(:ticket_levels).group_by("id").as("ticket_levels"), + "tickets.ticket_level_id=ticket_levels.id" + ) + .left_outer_join( + Qexpr.new.select("token", "tokenizable_id").from(:source_tokens).group_by("token", "tokenizable_id").as("source_tokens"), + "tickets.source_token_id=source_tokens.token" + ) + .left_outer_join( + # TODO: this does not support anything other than cards! + Qexpr.new.select("id", "name").from(:cards).group_by("id", "name").as("cards"), + "source_tokens.tokenizable_id = cards.id" + ) + .left_outer_join( + Qexpr.new.select("supporter_id", "MAX(event_id) AS event_id", "SUM(amount) AS total_amount") + .from(:donations).where("event_id=$id", id: event_id).group_by("supporter_id").as(:donations), + "donations.supporter_id=supporters.id AND donations.event_id=$id", id: event_id + ) + .where("tickets.event_id=$id", id: event_id) + .order_by("tickets.bid_id DESC") if query[:search].present? - query[:search] = "%#{query[:search].downcase.split(' ').join('%')}%" + query[:search] = "%#{query[:search].downcase.split(" ").join("%")}%" expr = expr.where(%( lower(supporters.name) LIKE $search OR lower(supporters.email) LIKE $search OR lower(ticket_levels.name) LIKE $search - ), search: '%' + query[:search] + '%') + ), search: "%" + query[:search] + "%") end if %w[asc desc].include? query[:sort_attendee] expr = expr.order_by("lower(supporters.name) #{query[:sort_attendee]} NULLS LAST") @@ -79,15 +79,15 @@ def self.attendees_list(event_id, query) ) total_count = Psql.execute( - Qexpr.new.select('COUNT(ts)') + Qexpr.new.select("COUNT(ts)") .from(attendees_expr(event_id, query) - .remove(:order_by).select('tickets.id'), 'ts') - ).first['count'] + .remove(:order_by).select("tickets.id"), "ts") + ).first["count"] # TODO: this worries me. Seems like a recipe for slow returns... perhaps some caching of the tokens every so often? data.each do |i| - unless i['source_token_id'] && QuerySourceToken.source_token_unexpired?(SourceToken.find(i['source_token_id'])) - i['source_token_id'] = nil + unless i["source_token_id"] && QuerySourceToken.source_token_unexpired?(SourceToken.find(i["source_token_id"])) + i["source_token_id"] = nil end end @@ -102,13 +102,13 @@ def self.for_export(event_id, query) Psql.execute_vectors( attendees_expr(event_id, query) .select([ - 'tickets.bid_id AS id', - 'ticket_levels.name AS ticket_level', - 'MONEY((coalesce(charges.amount, 0) - coalesce(refunds.amount, 0)) / 100.0) AS ticket_cost', - 'MONEY(coalesce(donations.total_amount, 0) / 100.0) AS total_donations', - 'tickets.quantity', + "tickets.bid_id AS id", + "ticket_levels.name AS ticket_level", + "MONEY((coalesce(charges.amount, 0) - coalesce(refunds.amount, 0)) / 100.0) AS ticket_cost", + "MONEY(coalesce(donations.total_amount, 0) / 100.0) AS total_donations", + "tickets.quantity", 'tickets.checked_in AS "Checked In?"', - 'tickets.note', + "tickets.note", "CASE WHEN event_discounts.id IS NULL THEN 'None' ELSE concat(event_discounts.name, ' (', event_discounts.percent, '%)') END AS \"Discount\"", "CASE WHEN tickets.card_id IS NULL OR tickets.card_id = 0 THEN '' ELSE 'YES' END AS \"Card Saved?\"" ].concat(QuerySupporters.supporter_export_selections)) @@ -116,23 +116,23 @@ def self.for_export(event_id, query) end def self.attendees_list_selection - ['tickets.id', - 'tickets.bid_id', - 'tickets.checked_in', - 'tickets.quantity', - 'tickets.note', - 'tickets.source_token_id', - 'ticket_levels.name AS ticket_level_name', - '(coalesce(charges.amount, 0) - coalesce(refunds.amount, 0)) AS total_paid', - 'ticket_levels.id AS ticket_level_id', - 'ticket_levels.amount AS ticket_level_amount', - 'event_discounts.percent AS discount_percent', - 'supporters.id AS supporter_id', - 'supporters.name AS name', - 'supporters.email AS email', - 'coalesce(donations.total_amount, 0) AS total_donations', - 'source_tokens.token AS token', - 'cards.name AS card_name'] + ["tickets.id", + "tickets.bid_id", + "tickets.checked_in", + "tickets.quantity", + "tickets.note", + "tickets.source_token_id", + "ticket_levels.name AS ticket_level_name", + "(coalesce(charges.amount, 0) - coalesce(refunds.amount, 0)) AS total_paid", + "ticket_levels.id AS ticket_level_id", + "ticket_levels.amount AS ticket_level_amount", + "event_discounts.percent AS discount_percent", + "supporters.id AS supporter_id", + "supporters.name AS name", + "supporters.email AS email", + "coalesce(donations.total_amount, 0) AS total_donations", + "source_tokens.token AS token", + "cards.name AS card_name"] end def self.for_event_activities(event_id) @@ -144,12 +144,12 @@ def self.for_event_activities(event_id) THEN 'A supporter' ELSE supporters.name END AS supporter_name", - 'tickets.quantity', 'tickets.created_at'] - Qx.select(selects.join(',')) + "tickets.quantity", "tickets.created_at"] + Qx.select(selects.join(",")) .from(:tickets) - .left_join(:supporters, 'tickets.supporter_id=supporters.id') - .where('tickets.event_id=$id', id: event_id) - .order_by('tickets.created_at desc') + .left_join(:supporters, "tickets.supporter_id=supporters.id") + .where("tickets.event_id=$id", id: event_id) + .order_by("tickets.created_at desc") .limit(15) .execute end diff --git a/app/legacy_lib/query_users.rb b/app/legacy_lib/query_users.rb index f27fa4be9b..5d2d6787cc 100644 --- a/app/legacy_lib/query_users.rb +++ b/app/legacy_lib/query_users.rb @@ -7,33 +7,33 @@ module QueryUsers # Return all the nonprofit user emails for a given email notification setting # for notification_type in ['payments', 'campaigns', 'events', 'payouts', 'recurring_donations'] def self.nonprofit_user_emails(np_id, notification_type) - raise ArgumentError, 'Invalid notification type' unless QueryEmailSettings::Settings.include?(notification_type) + raise ArgumentError, "Invalid notification type" unless QueryEmailSettings::Settings.include?(notification_type) - Qx.select('users.email') - .from('users') - .join('roles', 'roles.user_id=users.id') - .add_join('nonprofits', "roles.host_id=nonprofits.id AND roles.host_type='Nonprofit'") - .add_left_join('email_settings', 'email_settings.user_id=users.id') + Qx.select("users.email") + .from("users") + .join("roles", "roles.user_id=users.id") + .add_join("nonprofits", "roles.host_id=nonprofits.id AND roles.host_type='Nonprofit'") + .add_left_join("email_settings", "email_settings.user_id=users.id") .where("email_settings.user_id IS NULL OR email_settings.#{notification_type}=TRUE") - .and_where('nonprofits.id=$id', id: np_id) - .group_by('users.email') - .execute.map { |h| h['email'] } + .and_where("nonprofits.id=$id", id: np_id) + .group_by("users.email") + .execute.map { |h| h["email"] } end # Return all nonprofit emails regardless of email settings def self.all_nonprofit_user_emails(np_id, roles = %i[nonprofit_admin nonprofit_user]) - Qx.select('users.email').from('users') - .join('roles', 'roles.user_id = users.id') - .add_join('nonprofits', 'nonprofits.id = roles.host_id AND roles.host_type=\'Nonprofit\'') - .where('nonprofits.id=$id', id: np_id) - .and_where('roles.name IN ($names)', names: roles) - .execute.map { |h| h['email'] } + Qx.select("users.email").from("users") + .join("roles", "roles.user_id = users.id") + .add_join("nonprofits", "nonprofits.id = roles.host_id AND roles.host_type='Nonprofit'") + .where("nonprofits.id=$id", id: np_id) + .and_where("roles.name IN ($names)", names: roles) + .execute.map { |h| h["email"] } end # Return an array of email address strings for all users with role of 'super_admin' def self.super_admin_emails - Qx.select('users.email').from('users') - .join('roles', "roles.user_id=users.id AND roles.name='super_admin'") - .ex.map { |h| h['email'] } + Qx.select("users.email").from("users") + .join("roles", "roles.user_id=users.id AND roles.name='super_admin'") + .ex.map { |h| h["email"] } end end diff --git a/app/legacy_lib/retrieve_active_record_items.rb b/app/legacy_lib/retrieve_active_record_items.rb index a360b65edf..49a85dabab 100644 --- a/app/legacy_lib/retrieve_active_record_items.rb +++ b/app/legacy_lib/retrieve_active_record_items.rb @@ -6,10 +6,10 @@ module RetrieveActiveRecordItems def self.retrieve(data, optional = false) data.map do |k, v| our_integer = begin - Integer(v) - rescue StandardError - nil - end + Integer(v) + rescue + nil + end unless (optional && v.nil?) || (our_integer && our_integer > 0) raise ArgumentError, "Value '#{v}' for Key '#{k}' is not valid" end @@ -20,7 +20,7 @@ def self.retrieve(data, optional = false) if optional && v.nil? ret = [k, nil] else - ret = [k, k.where('id = ?', our_integer).first] + ret = [k, k.where("id = ?", our_integer).first] if ret[1].nil? raise ParamValidation::ValidationError.new("ID #{v} is not a valid #{k}", key: k) end @@ -35,13 +35,13 @@ def self.retrieve_from_keys(input, class_to_key_hash, optional = false) ret = nil begin - item = retrieve({ k => input[v] }, optional) + item = retrieve({k => input[v]}, optional) ret = [v, item[k]] rescue ParamValidation::ValidationError raise ParamValidation::ValidationError.new("ID #{input[v]} is not a valid #{k}", key: v) rescue ArgumentError raise ParamValidation::ValidationError.new("#{input[v]} is not a valid ID for Key '#{v}'", key: v) - rescue StandardError + rescue raise ParamValidation::ValidationError.new("#{input[v]} is not a valid ID for Key '#{v}'", key: v) end ret diff --git a/app/legacy_lib/scheduled_jobs.rb b/app/legacy_lib/scheduled_jobs.rb index 1105009ed2..ef6ca58b60 100644 --- a/app/legacy_lib/scheduled_jobs.rb +++ b/app/legacy_lib/scheduled_jobs.rb @@ -15,32 +15,32 @@ module ScheduledJobs def self.delete_junk_data # Delete all custom fields with emptly/nil vals del_cfjs_noval = Qx.delete_from(:custom_field_joins) - .where("value IS NULL OR value=''") + .where("value IS NULL OR value=''") # Delete orphaned custom field joins (those should also all have supporters) - del_cfjs_orphaned = Qx.delete_from(:custom_field_joins).where('id IN ($ids)', - ids: Qx.select('custom_field_joins.id') - .from(:custom_field_joins) - .left_join('supporters', 'custom_field_joins.supporter_id=supporters.id') - .where('supporters.id IS NULL')) + del_cfjs_orphaned = Qx.delete_from(:custom_field_joins).where("id IN ($ids)", + ids: Qx.select("custom_field_joins.id") + .from(:custom_field_joins) + .left_join("supporters", "custom_field_joins.supporter_id=supporters.id") + .where("supporters.id IS NULL")) # Delete orphaned tag joins - del_tags_orphaned = Qx.delete_from(:tag_joins).where('id IN ($ids)', - ids: Qx.select('tag_joins.id') - .from(:tag_joins) - .left_join(:supporters, 'tag_joins.supporter_id=supporters.id') - .where('supporters.id IS NULL')) + del_tags_orphaned = Qx.delete_from(:tag_joins).where("id IN ($ids)", + ids: Qx.select("tag_joins.id") + .from(:tag_joins) + .left_join(:supporters, "tag_joins.supporter_id=supporters.id") + .where("supporters.id IS NULL")) Enumerator.new do |yielder| yielder << lambda do del_cfjs_noval.execute - 'Successfully cleaned up custom field joins with no values' + "Successfully cleaned up custom field joins with no values" end yielder << lambda do del_cfjs_orphaned.execute - 'Successfully cleaned up custom field joins that have been orphaned from supporters' + "Successfully cleaned up custom field joins that have been orphaned from supporters" end yielder << lambda do del_tags_orphaned.execute - 'Successfully cleaned up tags that have been orphaned from supporters' + "Successfully cleaned up tags that have been orphaned from supporters" end end end @@ -56,13 +56,13 @@ def self.pay_recurring_donations def self.update_verification_statuses Enumerator.new do |yielder| - Nonprofit.where(verification_status: 'pending').each do |np| + Nonprofit.where(verification_status: "pending").each do |np| yielder << lambda do acct = Stripe::Account.retrieve(np.stripe_account_id) verified = acct.transfers_enabled && acct.verification.fields_needed.count == 0 - np.verification_status = verified ? 'verified' : np.verification_status - VerificationFailedJob.perform_later(np) if np.verification_status != 'verified' - VerificationCompletedJob.perform_later(np) if np.verification_status == 'verified' + np.verification_status = verified ? "verified" : np.verification_status + VerificationFailedJob.perform_later(np) if np.verification_status != "verified" + VerificationCompletedJob.perform_later(np) if np.verification_status == "verified" np.save "Status updated for NP #{np.id} as '#{np.verification_status}'" end @@ -72,7 +72,7 @@ def self.update_verification_statuses def self.update_np_balances Enumerator.new do |yielder| - nps = Nonprofit.where('id IN (?)', Charge.pending.uniq.pluck(:nonprofit_id)) + nps = Nonprofit.where("id IN (?)", Charge.pending.uniq.pluck(:nonprofit_id)) nps.each do |np| yielder << lambda do UpdateNonprofit.mark_available_charges(np.id) @@ -86,9 +86,8 @@ def self.update_pending_payouts Enumerator.new do |yielder| Payout.pending.includes(:nonprofit).each do |p| yielder << lambda do - err = false p.status = Stripe::Transfer.retrieve(p.stripe_transfer_id, - stripe_account: p.nonprofit.stripe_account_id).status + stripe_account: p.nonprofit.stripe_account_id).status p.save "Updated status for NP #{p.nonprofit.id}, payout # #{p.id}" end @@ -99,7 +98,7 @@ def self.update_pending_payouts def self.delete_expired_source_tokens Enumerator.new do |yielder| yielder << lambda do - tokens_deleted = SourceToken.where('expiration > ?', DateTime.now - 1.day).delete_all + tokens_deleted = SourceToken.where("expiration > ?", DateTime.now - 1.day).delete_all "Deleted #{tokens_deleted} source tokens" end end diff --git a/app/legacy_lib/search_vector.rb b/app/legacy_lib/search_vector.rb index 23aab50336..efd4ad861b 100644 --- a/app/legacy_lib/search_vector.rb +++ b/app/legacy_lib/search_vector.rb @@ -15,7 +15,7 @@ def self.query(query_string, expr = nil) def self._payments_blob_query Qexpr.new.select( - 'payments.id', + "payments.id", "concat_ws(' ' , payments.gross_amount , payments.kind @@ -29,20 +29,20 @@ def self._payments_blob_query , donations.dedication ) AS search_blob" ) - .from(:payments) - .left_outer_join('supporters', 'payments.supporter_id=supporters.id') - .left_outer_join('donations', 'payments.donation_id=donations.id') + .from(:payments) + .left_outer_join("supporters", "payments.supporter_id=supporters.id") + .left_outer_join("donations", "payments.donation_id=donations.id") end # Construct of query of ids and search blobs for all supporters # for use in a sub-query def self._supporters_blob_query - fields_subquery = Qexpr.new.select("string_agg(value::text, ' ') AS value", 'supporter_id') - .from(:custom_field_joins) - .group_by(:supporter_id) - .as(:custom_field_joins) + fields_subquery = Qexpr.new.select("string_agg(value::text, ' ') AS value", "supporter_id") + .from(:custom_field_joins) + .group_by(:supporter_id) + .as(:custom_field_joins) Qexpr.new.select( - 'supporters.id', + "supporters.id", "concat_ws(' ' , custom_field_joins.value , supporters.name @@ -57,9 +57,9 @@ def self._supporters_blob_query , payments.towards ) AS search_blob" ) - .from(:supporters) - .left_outer_join(:payments, 'payments.supporter_id=supporters.id') - .left_outer_join(:donations, 'donations.supporter_id=supporters.id') - .left_outer_join(fields_subquery, 'custom_field_joins.supporter_id=supporters.id') + .from(:supporters) + .left_outer_join(:payments, "payments.supporter_id=supporters.id") + .left_outer_join(:donations, "donations.supporter_id=supporters.id") + .left_outer_join(fields_subquery, "custom_field_joins.supporter_id=supporters.id") end end diff --git a/app/legacy_lib/slug_copy_naming_algorithm.rb b/app/legacy_lib/slug_copy_naming_algorithm.rb index 14fee51612..9fc38d6b27 100644 --- a/app/legacy_lib/slug_copy_naming_algorithm.rb +++ b/app/legacy_lib/slug_copy_naming_algorithm.rb @@ -11,7 +11,7 @@ def initialize(klass, nonprofit_id) end def copy_addition - '_copy' + "_copy" end def max_copies @@ -24,6 +24,6 @@ def get_name_for_entity(name_entity) def get_already_used_name_entities(base_name) end_name = '\\_copy\\_\\d{2}' - @klass.method(:where).call('slug SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)', base_name + end_name, nonprofit_id).select('slug') + @klass.method(:where).call("slug SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)", base_name + end_name, nonprofit_id).select("slug") end end diff --git a/app/legacy_lib/slug_nonprofit_naming_algorithm.rb b/app/legacy_lib/slug_nonprofit_naming_algorithm.rb index 6223498530..d966578290 100644 --- a/app/legacy_lib/slug_nonprofit_naming_algorithm.rb +++ b/app/legacy_lib/slug_nonprofit_naming_algorithm.rb @@ -11,7 +11,7 @@ def initialize(state_slug, city_slug) end def copy_addition - '' + "" end def max_copies @@ -19,7 +19,7 @@ def max_copies end def separator_before_copy_number - '-' + "-" end def get_name_for_entity(name_entity) @@ -28,6 +28,6 @@ def get_name_for_entity(name_entity) def get_already_used_name_entities(base_name) end_name = '\\-\\d{2}' - Nonprofit.method(:where).call('slug SIMILAR TO ? AND state_code_slug = ? AND city_slug = ?', base_name + end_name, @state_slug, @city_slug).select('slug') + Nonprofit.method(:where).call("slug SIMILAR TO ? AND state_code_slug = ? AND city_slug = ?", base_name + end_name, @state_slug, @city_slug).select("slug") end end diff --git a/app/legacy_lib/slug_p2p_campaign_naming_algorithm.rb b/app/legacy_lib/slug_p2p_campaign_naming_algorithm.rb index cb773da8e4..a7e0048275 100644 --- a/app/legacy_lib/slug_p2p_campaign_naming_algorithm.rb +++ b/app/legacy_lib/slug_p2p_campaign_naming_algorithm.rb @@ -10,7 +10,7 @@ def initialize(nonprofit_id) end def copy_addition - '' + "" end def max_copies @@ -23,6 +23,6 @@ def get_name_for_entity(name_entity) def get_already_used_name_entities(base_name) end_name = '\\_\\d{3}' - Campaign.where('slug SIMILAR TO ? AND nonprofit_id = ?', base_name + end_name, nonprofit_id).select('slug') + Campaign.where("slug SIMILAR TO ? AND nonprofit_id = ?", base_name + end_name, nonprofit_id).select("slug") end end diff --git a/app/legacy_lib/stripe_account.rb b/app/legacy_lib/stripe_account.rb index ab7860718b..ddea149471 100644 --- a/app/legacy_lib/stripe_account.rb +++ b/app/legacy_lib/stripe_account.rb @@ -6,48 +6,48 @@ module StripeAccount # Returns the stripe account ID string def self.find_or_create(nonprofit_id) - ParamValidation.new({ nonprofit_id: nonprofit_id }, nonprofit_id: { required: true, is_integer: true }) + ParamValidation.new({nonprofit_id: nonprofit_id}, nonprofit_id: {required: true, is_integer: true}) begin np = Nonprofit.find(nonprofit_id) - rescue StandardError => e + rescue raise ParamValidation::ValidationError.new("#{nonprofit_id} is not a valid nonprofit", key: :nonprofit_id) end - if !np['stripe_account_id'] - return create(np) + if !np["stripe_account_id"] + create(np) else - return np['stripe_account_id'] + np["stripe_account_id"] end end # np should be a hash with string keys def self.create(np) - ParamValidation.new({ np: np }, np: { required: true, is_a: Nonprofit }) + ParamValidation.new({np: np}, np: {required: true, is_a: Nonprofit}) params = { managed: true, - email: np['email'].present? ? np['email'] : np.roles.nonprofit_admins.order('created_at ASC').first.user.email, - business_name: np['name'], + email: np["email"].presence || np.roles.nonprofit_admins.order("created_at ASC").first.user.email, + business_name: np["name"], legal_entity: { - type: 'company', + type: "company", address: { - city: np['city'], - state: np['state_code'], - postal_code: np['zip_code'], - country: 'US' + city: np["city"], + state: np["state_code"], + postal_code: np["zip_code"], + country: "US" }, - business_name: np['name'] + business_name: np["name"] }, - product_description: 'Nonprofit donations', - transfer_schedule: { interval: 'manual' } + product_description: "Nonprofit donations", + transfer_schedule: {interval: "manual"} } - if np['website'] && np['website'] =~ URI::DEFAULT_PARSER.make_regexp - params[:business_url] = np['website'] + if np["website"] && np["website"] =~ URI::DEFAULT_PARSER.make_regexp + params[:business_url] = np["website"] end acct = Stripe::Account.create(params) - Qx.update(:nonprofits).set(stripe_account_id: acct.id).where(id: np['id']).execute - StripeAccountCreateJob.perform_later(Nonprofit.find(np['id'])) + Qx.update(:nonprofits).set(stripe_account_id: acct.id).where(id: np["id"]).execute + StripeAccountCreateJob.perform_later(Nonprofit.find(np["id"])) acct.id end end diff --git a/app/legacy_lib/stripe_utils.rb b/app/legacy_lib/stripe_utils.rb index 09bb057b84..06a4ab865e 100644 --- a/app/legacy_lib/stripe_utils.rb +++ b/app/legacy_lib/stripe_utils.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'stripe' +require "stripe" module StripeUtils # Get the verification status from a stripe object @@ -10,18 +10,18 @@ module StripeUtils # fields_needed set and have transfers_enabled set to true. So for our system, # that practically means they are verified. def self.get_verification_status(stripe_acct) - return 'verified' if stripe_acct.transfers_enabled + return "verified" if stripe_acct.transfers_enabled stripe_acct.legal_entity.verification.status end def self.create_transfer(net_amount, stripe_account_id, currency) Stripe::Transfer.create({ - amount: net_amount, - currency: currency || Houdini.intl.currencies[0], - recipient: 'self' - }, - stripe_account: stripe_account_id) + amount: net_amount, + currency: currency || Houdini.intl.currencies[0], + recipient: "self" + }, + stripe_account: stripe_account_id) end def self.create_refund(stripe_charge, amount, reason) diff --git a/app/legacy_lib/timespan.rb b/app/legacy_lib/timespan.rb index 683aaf5418..894170ccb3 100644 --- a/app/legacy_lib/timespan.rb +++ b/app/legacy_lib/timespan.rb @@ -4,18 +4,18 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # For tracking and calculating timespans/time intervals # Relies on activesupport -require 'active_support/time' +require "active_support/time" Timespan = Struct.new(:interval, :time_unit) do self::Units = %w[week day month year].freeze self::TimeUnits = { - '1_week' => 1.week.ago, - '2_weeks' => 2.weeks.ago, - '1_month' => 1.month.ago, - '3_months' => 3.months.ago, - '6_months' => 6.months.ago, - '1_year' => 1.year.ago, - '2_years' => 2.years.ago + "1_week" => 1.week.ago, + "2_weeks" => 2.weeks.ago, + "1_month" => 1.month.ago, + "3_months" => 3.months.ago, + "6_months" => 6.months.ago, + "1_year" => 1.year.ago, + "2_years" => 2.years.ago }.freeze # Test if end_date is past start_date by timespan diff --git a/app/legacy_lib/update_activities.rb b/app/legacy_lib/update_activities.rb index de61dd75a5..dcc94d7c83 100644 --- a/app/legacy_lib/update_activities.rb +++ b/app/legacy_lib/update_activities.rb @@ -6,7 +6,7 @@ module UpdateActivities def self.for_supporter_notes(supporter_note) user_email = supporter_note.user.email - supporter_note.activities.update_all(json_data: { content: supporter_note.content, user_email: user_email }.to_json, + supporter_note.activities.update_all(json_data: {content: supporter_note.content, user_email: user_email}.to_json, updated_at: DateTime.now) end end diff --git a/app/legacy_lib/update_charges.rb b/app/legacy_lib/update_charges.rb index 47f91f9115..94d0380400 100644 --- a/app/legacy_lib/update_charges.rb +++ b/app/legacy_lib/update_charges.rb @@ -4,10 +4,10 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module UpdateCharges def self.disburse_all_with_payments(payment_ids) - Psql.execute(Qexpr.new.update(:charges, status: 'disbursed').where('payment_id IN ($ids)', ids: payment_ids).returning('id', 'status')) + Psql.execute(Qexpr.new.update(:charges, status: "disbursed").where("payment_id IN ($ids)", ids: payment_ids).returning("id", "status")) end def self.reverse_disburse_all_with_payments(payment_ids) - Charge.where('payment_id IN (?)', payment_ids).update_all(status: 'available') + Charge.where("payment_id IN (?)", payment_ids).update_all(status: "available") end end diff --git a/app/legacy_lib/update_custom_field_joins.rb b/app/legacy_lib/update_custom_field_joins.rb index 48bad526a6..32ff8ee201 100644 --- a/app/legacy_lib/update_custom_field_joins.rb +++ b/app/legacy_lib/update_custom_field_joins.rb @@ -8,17 +8,17 @@ module UpdateCustomFieldJoins # Favor the most recent custom field join def self.delete_dupes(supporter_ids) # Bulk remove duplicate custom field joins, favoring the most recent one - ids = Qx.select('ARRAY_AGG(custom_field_joins.id ORDER BY custom_field_joins.created_at DESC) AS ids') - .from(:custom_field_joins) - .where('custom_field_joins.supporter_id IN ($ids)', ids: supporter_ids) - .join('custom_field_definitions cfms', 'cfms.id = custom_field_joins.custom_field_definition_id') - .group_by('cfms.name') - .having('COUNT(custom_field_joins) > 1') - .execute.map { |h| h['ids'][1..-1] }.flatten + ids = Qx.select("ARRAY_AGG(custom_field_joins.id ORDER BY custom_field_joins.created_at DESC) AS ids") + .from(:custom_field_joins) + .where("custom_field_joins.supporter_id IN ($ids)", ids: supporter_ids) + .join("custom_field_definitions cfms", "cfms.id = custom_field_joins.custom_field_definition_id") + .group_by("cfms.name") + .having("COUNT(custom_field_joins) > 1") + .execute.map { |h| h["ids"][1..-1] }.flatten return unless ids.any? Qx.delete_from(:custom_field_joins) - .where('id IN ($ids)', ids: ids) + .where("id IN ($ids)", ids: ids) .execute end end diff --git a/app/legacy_lib/update_disputes.rb b/app/legacy_lib/update_disputes.rb index d2ba328668..9187ef42b6 100644 --- a/app/legacy_lib/update_disputes.rb +++ b/app/legacy_lib/update_disputes.rb @@ -6,7 +6,7 @@ module UpdateDisputes def self.disburse_all_with_payments(payment_ids) Psql.execute( - Qexpr.new.update(:disputes, status: 'lost_and_paid').where('payment_id IN ($ids)', ids: payment_ids) + Qexpr.new.update(:disputes, status: "lost_and_paid").where("payment_id IN ($ids)", ids: payment_ids) ) end end diff --git a/app/legacy_lib/update_donation.rb b/app/legacy_lib/update_donation.rb index 349e387956..7b6ced56b4 100644 --- a/app/legacy_lib/update_donation.rb +++ b/app/legacy_lib/update_donation.rb @@ -13,43 +13,43 @@ def self.from_followup(donation, params) # @param [Integer] donation_id the donation for the payment you wish to modify def self.update_payment(donation_id, data) - ParamValidation.new({ id: donation_id, data: data }, - id: { required: true, is_reference: true }, - data: { required: true, is_hash: true }) - existing_payment = Payment.where('donation_id = ?', donation_id).last + ParamValidation.new({id: donation_id, data: data}, + id: {required: true, is_reference: true}, + data: {required: true, is_hash: true}) + existing_payment = Payment.where("donation_id = ?", donation_id).last unless existing_payment raise ParamValidation::ValidationError.new("#{donation_id} is does not correspond to a valid donation", - key: :id) + key: :id) end is_offsite = !existing_payment.offsite_payment.nil? validations = { - designation: { is_a: String }, - dedication: { is_a: String }, - comment: { is_a: String }, - campaign_id: { is_reference: true, required: true }, - event_id: { is_reference: true, required: true } + designation: {is_a: String}, + dedication: {is_a: String}, + comment: {is_a: String}, + campaign_id: {is_reference: true, required: true}, + event_id: {is_reference: true, required: true} } if is_offsite # if offline test the other values (fee_total, gross_amount, check_number, date) # - validations.merge!(gross_amount: { is_integer: true, min: 1 }, - fee_total: { is_integer: true }, - check_number: { is_a: String }, - date: { can_be_date: true }) + validations.merge!(gross_amount: {is_integer: true, min: 1}, + fee_total: {is_integer: true}, + check_number: {is_a: String}, + date: {can_be_date: true}) end ParamValidation.new(data, validations) - set_to_nil = { campaign: data[:campaign_id] == '', event: data[:event_id] == '' } + set_to_nil = {campaign: data[:campaign_id] == "", event: data[:event_id] == ""} # validate campaign and event ids if there and if they belong to nonprofit if set_to_nil[:campaign] campaign = nil else - campaign = Campaign.where('id = ?', data[:campaign_id]).first + campaign = Campaign.where("id = ?", data[:campaign_id]).first unless campaign raise ParamValidation::ValidationError.new("#{data[:campaign_id]} is not a valid campaign", key: :campaign_id) end @@ -61,7 +61,7 @@ def self.update_payment(donation_id, data) if set_to_nil[:event] event = nil else - event = Event.where('id = ?', data[:event_id]).first + event = Event.where("id = ?", data[:event_id]).first unless event raise ParamValidation::ValidationError.new("#{data[:event_id]} is not a valid event", key: :event_id) end @@ -77,9 +77,9 @@ def self.update_payment(donation_id, data) donation.comment = data[:comment] if data[:comment] donation.dedication = data[:dedication] if data[:dedication] donation.event = event if event - donation.event = nil if data[:event_id] == '' + donation.event = nil if data[:event_id] == "" donation.campaign = campaign if campaign - donation.campaign = nil if data[:campaign_id] == '' + donation.campaign = nil if data[:campaign_id] == "" if is_offsite donation.amount = data[:gross_amount] if data[:gross_amount] @@ -99,15 +99,13 @@ def self.update_payment(donation_id, data) if existing_payment.changed? existing_payment.save! - if existing_payment.previous_changes.has_key? 'gross_amount' - modern_donation.amount = existing_payment.gross_amount + if existing_payment.previous_changes.has_key? "gross_amount" + modern_donation.amount = existing_payment.gross_amount trx.amount = existing_payment.gross_amount end end - else - if donation.designation - Payment.where('donation_id = ?', donation.id).update_all(towards: donation.designation, updated_at: Time.now) - end + elsif donation.designation + Payment.where("donation_id = ?", donation.id).update_all(towards: donation.designation, updated_at: Time.now) end # if offsite, set check_number, date, gross_amount @@ -123,10 +121,9 @@ def self.update_payment(donation_id, data) donation.save! if donation.changed? md_changed = modern_donation.changed? modern_donation.save! if modern_donation.changed? - if (['dedication', 'designation'].any? {|i| donation.previous_changes.has_key? i} || md_changed) + if ["dedication", "designation"].any? { |i| donation.previous_changes.has_key? i } || md_changed modern_donation.publish_updated end - existing_payment.reload diff --git a/app/legacy_lib/update_email_lists.rb b/app/legacy_lib/update_email_lists.rb index 6fc0279ff0..e206eb2f82 100644 --- a/app/legacy_lib/update_email_lists.rb +++ b/app/legacy_lib/update_email_lists.rb @@ -5,18 +5,18 @@ module UpdateEmailLists def self.populate_lists_on_mailchimp(npo_id) - lists = Qx.select('tag_definition_id', 'list_name', 'mailchimp_list_id') - .from(:email_lists) - .where(nonprofit_id: npo_id) - .execute - post_data = Qx.select('supporters.email', 'email_lists.mailchimp_list_id') - .from('email_lists') - .add_join('tag_definitions', 'tag_definitions.id=email_lists.tag_definition_id') - .add_join('tag_joins', 'tag_joins.tag_definition_id=tag_definitions.id') - .add_join('supporters', 'supporters.id=tag_joins.supporter_id') - .where('email_lists.nonprofit_id=$id', id: npo_id) - .execute - .map { |h| { method: 'POST', path: "lists/#{h['mailchimp_list_id']}/members", body: { email_address: h['email'], status: 'subscribed' }.to_json } } + Qx.select("tag_definition_id", "list_name", "mailchimp_list_id") + .from(:email_lists) + .where(nonprofit_id: npo_id) + .execute + post_data = Qx.select("supporters.email", "email_lists.mailchimp_list_id") + .from("email_lists") + .add_join("tag_definitions", "tag_definitions.id=email_lists.tag_definition_id") + .add_join("tag_joins", "tag_joins.tag_definition_id=tag_definitions.id") + .add_join("supporters", "supporters.id=tag_joins.supporter_id") + .where("email_lists.nonprofit_id=$id", id: npo_id) + .execute + .map { |h| {method: "POST", path: "lists/#{h["mailchimp_list_id"]}/members", body: {email_address: h["email"], status: "subscribed"}.to_json} } Mailchimp.perform_batch_operations(npo_id, post_data) end end diff --git a/app/legacy_lib/update_email_settings.rb b/app/legacy_lib/update_email_settings.rb index 741863f843..71977e1963 100644 --- a/app/legacy_lib/update_email_settings.rb +++ b/app/legacy_lib/update_email_settings.rb @@ -6,16 +6,16 @@ module UpdateEmailSettings def self.save(np_id, user_id, params) es = Psql.execute( Qexpr.new.select(:id).from(:email_settings) - .where('nonprofit_id=$id', id: np_id.to_i) - .where('user_id=$id', id: user_id) + .where("nonprofit_id=$id", id: np_id.to_i) + .where("user_id=$id", id: user_id) ).first if es.nil? - es = Psql.execute(Qexpr.new.insert('email_settings', [{ nonprofit_id: np_id, user_id: user_id }], no_timestamps: true)).first + es = Psql.execute(Qexpr.new.insert("email_settings", [{nonprofit_id: np_id, user_id: user_id}], no_timestamps: true)).first end Psql.execute( Qexpr.new.update(:email_settings, params) - .where('id=$id', id: es['id']) - .returning('*') + .where("id=$id", id: es["id"]) + .returning("*") ).first end end diff --git a/app/legacy_lib/update_miscellaneous_np_info.rb b/app/legacy_lib/update_miscellaneous_np_info.rb index 15c6a3c9c4..88bc793849 100644 --- a/app/legacy_lib/update_miscellaneous_np_info.rb +++ b/app/legacy_lib/update_miscellaneous_np_info.rb @@ -4,13 +4,13 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module UpdateMiscellaneousNpInfo def self.update(np_id, misc_settings) - ParamValidation.new({ np_id: np_id, misc_settings: misc_settings }, - np_id: { required: true, is_integer: true }, - misc_settings: { required: true, is_hash: true }) - np = Nonprofit.where('id = ?', np_id).first + ParamValidation.new({np_id: np_id, misc_settings: misc_settings}, + np_id: {required: true, is_integer: true}, + misc_settings: {required: true, is_hash: true}) + np = Nonprofit.where("id = ?", np_id).first raise ParamValidation::ValidationError.new("Nonprofit #{np_id} does not exist", key: :np_id) unless np - misc = MiscellaneousNpInfo.where('nonprofit_id = ?', np_id).first + misc = MiscellaneousNpInfo.where("nonprofit_id = ?", np_id).first unless misc misc = MiscellaneousNpInfo.new misc.nonprofit = np @@ -20,10 +20,10 @@ def self.update(np_id, misc_settings) end if misc_settings[:change_amount_message].present? - if Format::HTML.has_only_empty_tags(misc_settings[:change_amount_message]) - misc.change_amount_message = nil + misc.change_amount_message = if Format::HTML.has_only_empty_tags(misc_settings[:change_amount_message]) + nil else - misc.change_amount_message = misc_settings[:change_amount_message] + misc_settings[:change_amount_message] end end diff --git a/app/legacy_lib/update_nonprofit.rb b/app/legacy_lib/update_nonprofit.rb index 4be85976c7..83213296ff 100644 --- a/app/legacy_lib/update_nonprofit.rb +++ b/app/legacy_lib/update_nonprofit.rb @@ -5,9 +5,9 @@ module UpdateNonprofit # See the stripe docs for reference: => https://stripe.com/docs/connect/identity-verification def self.verify_identity(np_id, legal_entity, tos = nil) - np = Qx.select('*').from(:nonprofits).where(id: np_id).execute.first - legal_entity[:address][:country] = 'US' if legal_entity[:address] - acct = FetchStripeAccount.with_account_id(np['stripe_account_id']) + np = Qx.select("*").from(:nonprofits).where(id: np_id).execute.first + legal_entity[:address][:country] = "US" if legal_entity[:address] + acct = FetchStripeAccount.with_account_id(np["stripe_account_id"]) acct.legal_entity.phone_number = acct.support_phone = legal_entity[:phone_number] if legal_entity[:phone_number] acct.legal_entity.business_tax_id = legal_entity[:business_tax_id] if legal_entity[:business_tax_id] acct.legal_entity.address = legal_entity[:address] if legal_entity[:address] @@ -16,58 +16,56 @@ def self.verify_identity(np_id, legal_entity, tos = nil) acct.legal_entity.dob = legal_entity[:dob] if legal_entity[:dob] acct.legal_entity.ssn_last_4 = legal_entity[:ssn_last_4] if legal_entity[:ssn_last_4] acct.legal_entity.personal_id_number = legal_entity[:personal_id_number] if legal_entity[:personal_id_number] - acct.legal_entity.type = 'company' - acct.legal_entity.business_name = np['name'] + acct.legal_entity.type = "company" + acct.legal_entity.business_name = np["name"] acct.tos_acceptance = tos if tos acct.save # Might as well update the nonprofit info if legal_entity[:address] && legal_entity[:business_tax_id] - np = Qx.update(:nonprofits).set( + Qx.update(:nonprofits).set( address: legal_entity[:address][:line1], city: legal_entity[:address][:city], state_code: legal_entity[:address][:state], zip_code: legal_entity[:address][:postal_code], ein: legal_entity[:business_tax_id], - verification_status: 'pending', + verification_status: "pending", phone: legal_entity[:phone_number] ) - .where(id: np_id) - .returning('*') - .execute.first + .where(id: np_id) + .returning("*") + .execute.first else - np = Qx.update(:nonprofits).set(verification_status: 'pending').where(id: np_id).returning('*').first + Qx.update(:nonprofits).set(verification_status: "pending").where(id: np_id).returning("*").first end - - np end # Update charges from pending to available if the nonprofit's balance on stripe can accommodate them # First, get net balance on Stripe, then get net balance on CC # Take the difference of those two, and mark as many oldest pending charges as 'available' as are less than or equal to that difference def self.mark_available_charges(npo_id) - stripe_account_id = Qx.select('stripe_account_id').from(:nonprofits).where(id: npo_id).ex.first['stripe_account_id'] + stripe_account_id = Qx.select("stripe_account_id").from(:nonprofits).where(id: npo_id).ex.first["stripe_account_id"] stripe_net_balance = Stripe::Balance.retrieve(stripe_account: stripe_account_id).available.first.amount - cc_net_balance = QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(npo_id))['net_amount'] + cc_net_balance = QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(npo_id))["net_amount"] - pending_payments = Qx.select('payments.net_amount', 'charges.id AS charge_id') - .from(:payments) - .where("charges.status='pending'") - .and_where('payments.nonprofit_id=$id', id: npo_id) - .join('charges', 'charges.payment_id=payments.id') - .order_by('payments.date ASC') - .execute + pending_payments = Qx.select("payments.net_amount", "charges.id AS charge_id") + .from(:payments) + .where("charges.status='pending'") + .and_where("payments.nonprofit_id=$id", id: npo_id) + .join("charges", "charges.payment_id=payments.id") + .order_by("payments.date ASC") + .execute return if pending_payments.empty? remaining_balance = stripe_net_balance - cc_net_balance charge_ids = pending_payments.take_while do |payment| - if payment['net_amount'] <= remaining_balance - remaining_balance -= payment['net_amount'] + if payment["net_amount"] <= remaining_balance + remaining_balance -= payment["net_amount"] true end - end.map { |h| h['charge_id'] } + end.map { |h| h["charge_id"] } - Qx.update(:charges).set(status: 'available').where('id IN ($ids)', ids: charge_ids).execute if charge_ids.any? + Qx.update(:charges).set(status: "available").where("id IN ($ids)", ids: charge_ids).execute if charge_ids.any? end end diff --git a/app/legacy_lib/update_order.rb b/app/legacy_lib/update_order.rb index 13fb05235e..4f51b2e27e 100644 --- a/app/legacy_lib/update_order.rb +++ b/app/legacy_lib/update_order.rb @@ -8,7 +8,7 @@ module UpdateOrder # - id : id of row to update # - order: new order of row to update def self.with_data(table_name, data) - vals = data.map { |h| "(#{h[:id].to_i}, #{h[:order].to_i})" }.join(', ') + vals = data.map { |h| "(#{h[:id].to_i}, #{h[:order].to_i})" }.join(", ") from_str = "(VALUES #{vals}) AS data(id, \"order\")" Qx.update(table_name.to_s) .set('"order"="data"."order"') diff --git a/app/legacy_lib/update_payouts.rb b/app/legacy_lib/update_payouts.rb index 99f801d0e1..2dd079dd6f 100644 --- a/app/legacy_lib/update_payouts.rb +++ b/app/legacy_lib/update_payouts.rb @@ -4,21 +4,21 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module UpdatePayouts def self.reverse_with_stripe(payout_id, status, failure_message) - ParamValidation.new({ payout_id: payout_id, status: status, failure_message: failure_message }, - payout_id: { required: true, is_integer: true }, - status: { included_in: %w[pending paid canceled failed], required: true }, - failure_message: { not_blank: true, required: true }) - payout = Payout.where('id = ?', payout_id).first + ParamValidation.new({payout_id: payout_id, status: status, failure_message: failure_message}, + payout_id: {required: true, is_integer: true}, + status: {included_in: %w[pending paid canceled failed], required: true}, + failure_message: {not_blank: true, required: true}) + payout = Payout.where("id = ?", payout_id).first unless payout - raise ParamValidation::ValidationError.new("No payout with id number: #{payout_id} ", [{ key: :payout_id }]) + raise ParamValidation::ValidationError.new("No payout with id number: #{payout_id} ", [{key: :payout_id}]) end - payment_ids = payout.payments.select('payments.id').map(&:id).to_a + payment_ids = payout.payments.select("payments.id").map(&:id).to_a if payment_ids.count < 1 - raise ArgumentError, 'No payments are available to reverse.' + raise ArgumentError, "No payments are available to reverse." end - now = Time.current + Time.current Psql.transaction do # Retrieve all payments with available charges and undisbursed refunds diff --git a/app/legacy_lib/update_recurring_donations.rb b/app/legacy_lib/update_recurring_donations.rb index b4a46ef9e5..0a0becbcdb 100644 --- a/app/legacy_lib/update_recurring_donations.rb +++ b/app/legacy_lib/update_recurring_donations.rb @@ -7,12 +7,12 @@ module UpdateRecurringDonations # Update the card id and name for a given recurring donation (provide rd['donation_id']) def self.update_card_id(rd, token) rd = rd&.with_indifferent_access - ParamValidation.new({ rd: rd, token: token }, - rd: { is_hash: true, required: true }, - token: { format: UUID::Regex, required: true }) + ParamValidation.new({rd: rd, token: token}, + rd: {is_hash: true, required: true}, + token: {format: UUID::Regex, required: true}) ParamValidation.new(rd, - id: { is_reference: true, required: true }) + id: {is_reference: true, required: true}) source_token = QuerySourceToken.get_and_increment_source_token(token, nil) tokenizable = source_token.tokenizable @@ -31,19 +31,19 @@ def self.update_card_id(rd, token) rec_don.n_failures = 0 rec_don.save! donation.save! - InsertSupporterNotes.create([{ content: "This supporter updated their card for their recurring donation with ID #{rec_don.id}", supporter_id: rec_don.supporter.id, user_id: 540 }]) + InsertSupporterNotes.create([{content: "This supporter updated their card for their recurring donation with ID #{rec_don.id}", supporter_id: rec_don.supporter.id, user_id: 540}]) end - QueryRecurringDonations.fetch_for_edit(rd[:id])['recurring_donation'] + QueryRecurringDonations.fetch_for_edit(rd[:id])["recurring_donation"] end # Update the paydate for a given recurring donation (provide rd['id']) def self.update_paydate(rd, paydate) - return ValidationError.new(['Invalid paydate']) unless (1..28).cover?(paydate.to_i) + return ValidationError.new(["Invalid paydate"]) unless (1..28).cover?(paydate.to_i) - Psql.execute(Qexpr.new.update(:recurring_donations, paydate: paydate).where('id=$id', id: rd['id'])) - recurring_donation = RecurringDonation.find(rd['id']) + Psql.execute(Qexpr.new.update(:recurring_donations, paydate: paydate).where("id=$id", id: rd["id"])) + recurring_donation = RecurringDonation.find(rd["id"]) recurring_donation.recurrence.publish_updated - rd['paydate'] = paydate + rd["paydate"] = paydate rd end @@ -51,10 +51,10 @@ def self.update_paydate(rd, paydate) # @param [String] token # @param [Integer] amount def self.update_amount(rd, token, amount) - ParamValidation.new({ amount: amount, rd: rd, token: token }, - amount: { is_integer: true, min: 50, required: true }, - rd: { required: true, is_a: RecurringDonation }, - token: { required: true, format: UUID::Regex }) + ParamValidation.new({amount: amount, rd: rd, token: token}, + amount: {is_integer: true, min: 50, required: true}, + rd: {required: true, is_a: RecurringDonation}, + token: {required: true, format: UUID::Regex}) source_token = QuerySourceToken.get_and_increment_source_token(token, nil) tokenizable = source_token.tokenizable @@ -80,26 +80,26 @@ def self.update_amount(rd, token, amount) end def self.update_from_start_dates - RecurringDonation.inactive.where('start_date >= ?', Date.today).update_all(active: true) + RecurringDonation.inactive.where("start_date >= ?", Date.today).update_all(active: true) end def self.update_from_end_dates - RecurringDonation.active.where('end_date < ?', Date.today).update_all(active: false) + RecurringDonation.active.where("end_date < ?", Date.today).update_all(active: false) end # Cancel a recurring donation (set active='f') and record the supporter/user email who did it def self.cancel(rd_id, email, dont_notify_nonprofit = false) Psql.execute( Qexpr.new.update(:recurring_donations, - active: false, - cancelled_by: email, - cancelled_at: Time.current) - .where('id=$id', id: rd_id.to_i) + active: false, + cancelled_by: email, + cancelled_at: Time.current) + .where("id=$id", id: rd_id.to_i) ) - rd = QueryRecurringDonations.fetch_for_edit(rd_id)['recurring_donation'] - InsertSupporterNotes.create({ supporter: Supporter.find(rd['supporter_id']), user: nil, content: "This supporter's recurring donation for $#{Format::Currency.cents_to_dollars(rd['amount'])} was cancelled by #{rd['cancelled_by']} on #{Format::Date.simple(rd['cancelled_at'])}"}) + rd = QueryRecurringDonations.fetch_for_edit(rd_id)["recurring_donation"] + InsertSupporterNotes.create({supporter: Supporter.find(rd["supporter_id"]), user: nil, content: "This supporter's recurring donation for $#{Format::Currency.cents_to_dollars(rd["amount"])} was cancelled by #{rd["cancelled_by"]} on #{Format::Date.simple(rd["cancelled_at"])}"}) unless dont_notify_nonprofit - RecurringDonationCancelledJob.perform_later(Donation.find(rd['donation_id'])) + RecurringDonationCancelledJob.perform_later(Donation.find(rd["donation_id"])) end rd end @@ -125,10 +125,10 @@ def self.set_defaults(params) end if params[:end_date_str] - if params[:end_date_str].blank? || params[:end_date_str] == 'None' - params[:end_date] = nil + params[:end_date] = if params[:end_date_str].blank? || params[:end_date_str] == "None" + nil else - params[:end_date] = Chronic.parse(params[:end_date_str]) + Chronic.parse(params[:end_date_str]) end params = params.except(:end_date_str) end diff --git a/app/legacy_lib/update_refunds.rb b/app/legacy_lib/update_refunds.rb index 2904bffb82..a7524ad0d3 100644 --- a/app/legacy_lib/update_refunds.rb +++ b/app/legacy_lib/update_refunds.rb @@ -4,15 +4,15 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module UpdateRefunds def self.disburse_all_with_payments(payment_ids) - expr = Qx.update(:refunds) - .set(disbursed: true) - .timestamps - .where('payment_id IN ($ids)', ids: payment_ids) - .returning('*') - .execute + Qx.update(:refunds) + .set(disbursed: true) + .timestamps + .where("payment_id IN ($ids)", ids: payment_ids) + .returning("*") + .execute end def self.reverse_disburse_all_with_payments(payment_ids) - Refund.where('payment_id IN (?)', payment_ids).update_all(disbursed: false) + Refund.where("payment_id IN (?)", payment_ids).update_all(disbursed: false) end end diff --git a/app/legacy_lib/update_supporter.rb b/app/legacy_lib/update_supporter.rb index 0a6067e2b9..5d51792bed 100644 --- a/app/legacy_lib/update_supporter.rb +++ b/app/legacy_lib/update_supporter.rb @@ -12,13 +12,13 @@ def self.from_info(supporter, params) def self.bulk_delete(np_id, supporter_ids) Qx.update(:supporters) .set(deleted: true) - .where('id IN ($ids)', ids: supporter_ids) - .and_where('nonprofit_id=$id', id: np_id) - .returning('id') + .where("id IN ($ids)", ids: supporter_ids) + .and_where("nonprofit_id=$id", id: np_id) + .returning("id") .execute end def self.general_info(supporter_id, data) - Qx.update(:supporters).set(data).where(id: supporter_id).returning('*').ex.last + Qx.update(:supporters).set(data).where(id: supporter_id).returning("*").ex.last end end diff --git a/app/legacy_lib/update_supporter_notes.rb b/app/legacy_lib/update_supporter_notes.rb index e0ca41a758..06e3cce1fb 100644 --- a/app/legacy_lib/update_supporter_notes.rb +++ b/app/legacy_lib/update_supporter_notes.rb @@ -3,10 +3,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module UpdateSupporterNotes - # should this get put into a callback on SupporterNote? Probably but + # should this get put into a callback on SupporterNote? Probably but # not sure how right now. def self.update(supporter_note, params) - ActiveRecord::Base.transaction do + ActiveRecord::Base.transaction do supporter_note.update params supporter_note.save! UpdateActivities.for_supporter_notes(note) @@ -16,10 +16,10 @@ def self.update(supporter_note, params) # sets the deleted column to true on supporter_notes (soft delete) # and then does a hard delete on the associated activity # - # should this get put into a callback on SupporterNote? Probably but + # should this get put into a callback on SupporterNote? Probably but # not sure how right now. def self.delete(supporter_note) - ActiveRecord::Base.transaction do + ActiveRecord::Base.transaction do supporter_note.discard! supporter_note.activities.destroy_all end diff --git a/app/legacy_lib/update_tickets.rb b/app/legacy_lib/update_tickets.rb index d98cf8ff47..b2f7dc7a00 100644 --- a/app/legacy_lib/update_tickets.rb +++ b/app/legacy_lib/update_tickets.rb @@ -5,13 +5,13 @@ module UpdateTickets def self.update(data, current_user = nil) ParamValidation.new(data, - event_id: { required: true, is_reference: true }, - ticket_id: { required: true, is_reference: true }, - token: { format: UUID::Regex }, - bid_id: { is_integer: true }, - # note: nothing to check? + event_id: {required: true, is_reference: true}, + ticket_id: {required: true, is_reference: true}, + token: {format: UUID::Regex}, + bid_id: {is_integer: true}, + # note: nothing to check? - checked_in: { included_in: ['true', 'false', true, false] }) + checked_in: {included_in: ["true", "false", true, false]}) entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Event => :event_id, Ticket => :ticket_id) validate_entities(entities) @@ -55,8 +55,7 @@ def self.update(data, current_user = nil) end def self.delete(event_id, ticket_id) - - Ticket.transaction do + Ticket.transaction do ticket = Event.find(event_id).tickets.find(ticket_id) ticket.deleted = true ticket.save! @@ -66,26 +65,26 @@ def self.delete(event_id, ticket_id) def self.delete_card_for_ticket(event_id, ticket_id) begin - ParamValidation.new({ event_id: event_id, ticket_id: ticket_id }, - event_id: { required: true, is_integer: true }, - ticket_id: { required: true, is_integer: true }) + ParamValidation.new({event_id: event_id, ticket_id: ticket_id}, + event_id: {required: true, is_integer: true}, + ticket_id: {required: true, is_integer: true}) rescue ParamValidation::ValidationError => e - return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } + return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} end begin - ticket = Ticket.where('id = ? and event_id = ?', ticket_id, event_id).limit(1).first! + ticket = Ticket.where("id = ? and event_id = ?", ticket_id, event_id).limit(1).first! ticket.card = nil ticket.source_token = nil ticket.save! - return { json: {}, status: :ok } + {json: {}, status: :ok} rescue ActiveRecord::RecordNotFound => e # there's no stinking ticket by that event and ticket - return { json: { error: "No ticket with id #{ticket_id} at event with id #{event_id}\n #{e.message}" }, - status: :unprocessable_entity } + {json: {error: "No ticket with id #{ticket_id} at event with id #{event_id}\n #{e.message}"}, + status: :unprocessable_entity} rescue ActiveRecord::ActiveRecordError - return { json: { error: 'There was a DB error. Please contact support' }, - status: :unprocessable_entity } + {json: {error: "There was a DB error. Please contact support"}, + status: :unprocessable_entity} end end diff --git a/app/legacy_lib/uuid.rb b/app/legacy_lib/uuid.rb index 305aad8bab..d4fc8daceb 100644 --- a/app/legacy_lib/uuid.rb +++ b/app/legacy_lib/uuid.rb @@ -3,5 +3,5 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module UUID - Regex = /\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?/.freeze + Regex = /\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?/ end diff --git a/app/listeners/campaign_listener.rb b/app/listeners/campaign_listener.rb index f5f53726ea..741009b4d1 100644 --- a/app/listeners/campaign_listener.rb +++ b/app/listeners/campaign_listener.rb @@ -3,13 +3,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class CampaignListener < ApplicationListener - def self.campaign_create(campaign) - if campaign.child_campaign? - CampaignCreationFederatedEmailJob.perform_later(campaign) - else - CampaignCreationEmailFollowupJob.perform_later(campaign) - end - - SupporterFundraiserCreateJob.perform_later(campaign) + def self.campaign_create(campaign) + if campaign.child_campaign? + CampaignCreationFederatedEmailJob.perform_later(campaign) + else + CampaignCreationEmailFollowupJob.perform_later(campaign) end + + SupporterFundraiserCreateJob.perform_later(campaign) + end end diff --git a/app/listeners/credit_card_payment_listener.rb b/app/listeners/credit_card_payment_listener.rb index 98ed950b3b..2ebc1d79d5 100644 --- a/app/listeners/credit_card_payment_listener.rb +++ b/app/listeners/credit_card_payment_listener.rb @@ -3,35 +3,35 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class CreditCardPaymentListener < ApplicationListener - def self.donation_create(donation, locale, user=nil) - if donation.payment_provider.to_sym == :credit_card - PaymentNotificationEmailDonorJob.perform_later donation, locale - PaymentNotificationEmailNonprofitJob.perform_later donation, user - end + def self.donation_create(donation, locale, user = nil) + if donation.payment_provider.to_sym == :credit_card + PaymentNotificationEmailDonorJob.perform_later donation, locale + PaymentNotificationEmailNonprofitJob.perform_later donation, user end + end - def self.recurring_donation_create(donation, locale, user=nil) - if donation.payment_provider.to_sym == :credit_card - PaymentNotificationEmailDonorJob.perform_later donation, locale - PaymentNotificationEmailNonprofitJob.perform_later donation, user - end + def self.recurring_donation_create(donation, locale, user = nil) + if donation.payment_provider.to_sym == :credit_card + PaymentNotificationEmailDonorJob.perform_later donation, locale + PaymentNotificationEmailNonprofitJob.perform_later donation, user end + end - def self.refund_create(refund) - RefundNotificationJob.perform_later refund - end + def self.refund_create(refund) + RefundNotificationJob.perform_later refund + end - def self.recurring_donation_payment_succeeded(donation, locale, user=nil) - if donation.payment_provider.to_sym == :credit_card - PaymentNotificationEmailDonorJob.perform_later donation, locale - PaymentNotificationEmailNonprofitJob.perform_later donation, user - end + def self.recurring_donation_payment_succeeded(donation, locale, user = nil) + if donation.payment_provider.to_sym == :credit_card + PaymentNotificationEmailDonorJob.perform_later donation, locale + PaymentNotificationEmailNonprofitJob.perform_later donation, user end + end - def self.recurring_donation_payment_failed(donation, locale) - FailedRecurringDonationPaymentDonorEmailJob.perform_later(donation) - if (donation.recurring_donation.n_failures >= 3) - FailedRecurringDonationPaymentNonprofitEmailJob.perform_later(donation) - end + def self.recurring_donation_payment_failed(donation, locale) + FailedRecurringDonationPaymentDonorEmailJob.perform_later(donation) + if donation.recurring_donation.n_failures >= 3 + FailedRecurringDonationPaymentNonprofitEmailJob.perform_later(donation) end + end end diff --git a/app/listeners/nonprofit_mailer_listener.rb b/app/listeners/nonprofit_mailer_listener.rb index 341c7fc90e..13c43964e2 100644 --- a/app/listeners/nonprofit_mailer_listener.rb +++ b/app/listeners/nonprofit_mailer_listener.rb @@ -3,7 +3,6 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class NonprofitMailerListener < ApplicationListener - def nonprofit_create(nonprofit) - - end -end \ No newline at end of file + def nonprofit_create(nonprofit) + end +end diff --git a/app/listeners/sepa_payment_listener.rb b/app/listeners/sepa_payment_listener.rb index 894db547de..0398398402 100644 --- a/app/listeners/sepa_payment_listener.rb +++ b/app/listeners/sepa_payment_listener.rb @@ -3,10 +3,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class SepaPaymentListener < ApplicationListener - def self.donation_create(donation, locale, user=nil) - if donation.payment_provider.to_sym == :sepa - DirectDebitCreateNotifyNonprofitJob.perform_later(donation.id) - DirectDebitCreateNotifyDonorJob.perform_later donation.id, locale - end + def self.donation_create(donation, locale, user = nil) + if donation.payment_provider.to_sym == :sepa + DirectDebitCreateNotifyNonprofitJob.perform_later(donation.id) + DirectDebitCreateNotifyDonorJob.perform_later donation.id, locale end + end end diff --git a/app/listeners/ticket_mailing_listener.rb b/app/listeners/ticket_mailing_listener.rb index 0bfb148995..a5c0ad3bc9 100644 --- a/app/listeners/ticket_mailing_listener.rb +++ b/app/listeners/ticket_mailing_listener.rb @@ -3,10 +3,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class TicketMailingListener < ApplicationListener - def self.ticket_purchase_created(ticket_purchase) - tickets_ids = ticket_purchase.ticket_to_legacy_tickets.joins(:ticket).map {|i| i.ticket.id} - charge = ticket_purchase.ticket_to_legacy_tickets.joins(:ticket).first.charge - TicketMailer.followup(tickets_ids, charge && charge.id).deliver_later - TicketMailer.receipt_admin(tickets_ids, nil).deliver_later - end -end \ No newline at end of file + def self.ticket_purchase_created(ticket_purchase) + tickets_ids = ticket_purchase.ticket_to_legacy_tickets.joins(:ticket).map { |i| i.ticket.id } + charge = ticket_purchase.ticket_to_legacy_tickets.joins(:ticket).first.charge + TicketMailer.followup(tickets_ids, charge && charge.id).deliver_later + TicketMailer.receipt_admin(tickets_ids, nil).deliver_later + end +end diff --git a/app/listeners/wemove_listener.rb b/app/listeners/wemove_listener.rb index 468913b2d2..b2a7443697 100644 --- a/app/listeners/wemove_listener.rb +++ b/app/listeners/wemove_listener.rb @@ -3,15 +3,15 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class WemoveListener < ApplicationListener - def self.donation_create(donation) - WeMoveExecuteForDonationsJob.perform_later(donation) - end + def self.donation_create(donation) + WeMoveExecuteForDonationsJob.perform_later(donation) + end - def self.offsite_donation_create(donation) - WeMoveExecuteForDonationsJob.perform_later(donation) - end + def self.offsite_donation_create(donation) + WeMoveExecuteForDonationsJob.perform_later(donation) + end - def self.recurring_donation_create(donation) - WeMoveExecuteForDonationsJob.perform_later(donation) - end + def self.recurring_donation_create(donation) + WeMoveExecuteForDonationsJob.perform_later(donation) + end end diff --git a/app/mailers/base_mailer.rb b/app/mailers/base_mailer.rb index 82c852d2e0..352c874f2d 100644 --- a/app/mailers/base_mailer.rb +++ b/app/mailers/base_mailer.rb @@ -7,5 +7,5 @@ class BaseMailer < ActionMailer::Base include ApplicationHelper helper ApplicationHelper default from: Houdini.hoster.support_email - layout 'email' + layout "email" end diff --git a/app/mailers/donation_mailer.rb b/app/mailers/donation_mailer.rb index 4d9c2a28fa..ada8a18b1a 100644 --- a/app/mailers/donation_mailer.rb +++ b/app/mailers/donation_mailer.rb @@ -8,20 +8,20 @@ class DonationMailer < BaseMailer 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 + @thank_you_note = if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? + @donation.campaign.receipt_message else - @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, 'NAME' => @donation.supporter.name) + 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.presence || @nonprofit.users.first.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) + subject: I18n.t("mailer.donations.donor_direct_debit_notification.subject", nonprofit_name: @nonprofit.name) ) end end @@ -30,20 +30,20 @@ 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? - @thank_you_note = @donation.campaign.receipt_message + @thank_you_note = if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? + @donation.campaign.receipt_message else - @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, 'NAME' => @donation.supporter.name) + Format::Interpolate.with_hash(@nonprofit.thank_you_note, "NAME" => @donation.supporter.name) end - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + reply_to = @nonprofit.email.presence || @nonprofit.users.first.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) + subject: I18n.t("mailer.donations.donor_direct_debit_notification.subject", nonprofit_name: @nonprofit.name) ) end end @@ -53,7 +53,7 @@ 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') + @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) @@ -66,7 +66,7 @@ def nonprofit_failed_recurring_donation(donation_id) @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') + @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}") end @@ -74,7 +74,7 @@ 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 + reply_to = @nonprofit.email.presence || @nonprofit.users.first.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}") end @@ -83,14 +83,14 @@ def nonprofit_recurring_donation_cancellation(donation_id) @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') + @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 + 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') + @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 @@ -98,11 +98,9 @@ def nonprofit_recurring_donation_change_amount(donation_id, previous_amount = ni 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 + reply_to = @nonprofit.email.presence || @nonprofit.users.first.email + @thank_you_note = if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? + @nonprofit.miscellaneous_np_info.change_amount_message end from = Format::Name.email_from_np(@nonprofit.name) @previous_amount = previous_amount @@ -112,7 +110,7 @@ def donor_recurring_donation_change_amount(donation_id, previous_amount = nil) 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') + @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 @@ -120,11 +118,9 @@ def nonprofit_recurring_donation_change_amount(donation_id, previous_amount = ni 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 + reply_to = @nonprofit.email.presence || @nonprofit.users.first.email + @thank_you_note = if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? + @nonprofit.miscellaneous_np_info.change_amount_message end from = Format::Name.email_from_np(@nonprofit.name) @previous_amount = previous_amount diff --git a/app/mailers/export_mailer.rb b/app/mailers/export_mailer.rb index c7e5556204..70252abcbb 100644 --- a/app/mailers/export_mailer.rb +++ b/app/mailers/export_mailer.rb @@ -11,46 +11,46 @@ class ExportMailer < BaseMailer def export_payments_completed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your payment export is available!') + mail(to: @export.user.email, subject: "Your payment export is available!") end def export_payments_failed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your payment export has failed') + mail(to: @export.user.email, subject: "Your payment export has failed") end def export_recurring_donations_completed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your recurring donations export is available!') + mail(to: @export.user.email, subject: "Your recurring donations export is available!") end def export_recurring_donations_failed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your recurring donations export has failed') + mail(to: @export.user.email, subject: "Your recurring donations export has failed") end def export_supporters_completed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your supporters export is available!') + mail(to: @export.user.email, subject: "Your supporters export is available!") end def export_supporters_failed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your supporters export has failed') + mail(to: @export.user.email, subject: "Your supporters export has failed") end def export_supporter_notes_completed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your supporter notes export is available!') + mail(to: @export.user.email, subject: "Your supporter notes export is available!") end def export_supporter_notes_failed_notification(export) @export = export - mail(to: @export.user.email, subject: 'Your supporter notes export has failed.') + mail(to: @export.user.email, subject: "Your supporter notes export has failed.") end end diff --git a/app/mailers/generic_mailer.rb b/app/mailers/generic_mailer.rb index 5e2de166f5..9ffca1ed11 100644 --- a/app/mailers/generic_mailer.rb +++ b/app/mailers/generic_mailer.rb @@ -13,9 +13,9 @@ def generic_mail(from_email, from_name, message, subject, to_email, _to_name) # For sending a system notice to super admins def admin_notice(options) @from_email = Houdini.hoster.support_email - @from_name = 'CC Bot' + @from_name = "CC Bot" @message = options[:body] emails = QueryUsers.super_admin_emails - mail(to: emails, from: "#{@from_name} <#{@from_email}>", reply_to: @from_email, subject: options[:subject], template_name: 'generic_mail') + mail(to: emails, from: "#{@from_name} <#{@from_email}>", reply_to: @from_email, subject: options[:subject], template_name: "generic_mail") end end diff --git a/app/mailers/import_mailer.rb b/app/mailers/import_mailer.rb index cc832db492..81e2104255 100644 --- a/app/mailers/import_mailer.rb +++ b/app/mailers/import_mailer.rb @@ -6,6 +6,6 @@ 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!') + mail(to: @import.user.email, subject: "Your import is complete!") end end diff --git a/app/mailers/nonprofit_admin_mailer.rb b/app/mailers/nonprofit_admin_mailer.rb index 004d9c5ce5..a91551bbf2 100644 --- a/app/mailers/nonprofit_admin_mailer.rb +++ b/app/mailers/nonprofit_admin_mailer.rb @@ -20,7 +20,7 @@ def existing_invite(role) def supporter_fundraiser(event_or_campaign) @fundraiser = event_or_campaign - @kind = event_or_campaign.class.name.downcase || 'event' + @kind = event_or_campaign.class.name.downcase || "event" @nonprofit = event_or_campaign.nonprofit @profile = event_or_campaign.profile recipients = @nonprofit.nonprofit_personnel_emails diff --git a/app/mailers/nonprofit_mailer.rb b/app/mailers/nonprofit_mailer.rb index ffbcdfd63e..53f34fe75d 100644 --- a/app/mailers/nonprofit_mailer.rb +++ b/app/mailers/nonprofit_mailer.rb @@ -5,13 +5,13 @@ class NonprofitMailer < BaseMailer def failed_verification_notice(np) @nonprofit = np - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, "notify_payouts") mail(to: @emails, subject: "We need some further account verification on #{Houdini.general.name}") end def successful_verification_notice(np) @nonprofit = np - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, "notify_payouts") mail(to: @emails, subject: "Verification successful on #{Houdini.general.name}!") end @@ -20,7 +20,7 @@ def refund_notification(refund_id) @charge = @refund.charge @nonprofit = @refund.payment.nonprofit @supporter = @refund.payment.supporter - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payments') + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, "notify_payments") return if @emails.blank? mail(to: @emails, subject: "A new refund has been made for $#{Format::Currency.cents_to_dollars(@refund.amount)}") end @@ -29,48 +29,48 @@ 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') + 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') + @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') + @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') + @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.') + @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.') + @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!') + mail(to: @emails, subject: "Your nonprofit has been verified!") end def button_code(nonprofit, to_email, to_name, from_email, message, code) @@ -81,7 +81,7 @@ def button_code(nonprofit, to_email, to_name, from_email, message, code) @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') + mail(to: to_email, from: from, reply_to: from_email, subject: "Please include this donate button code on the website") end # pass in all of: @@ -99,7 +99,7 @@ def supporter_message(args) def setup_verification(np_id) @nonprofit = Nonprofit.find(np_id) @emails = QueryUsers.all_nonprofit_user_emails(np_id, [:nonprofit_admin]) - mail(to: @emails, reply_to: 'support@commitchange.com', from: "#{Houdini.general.name} Support", subject: "Set up automatic payouts on #{Houdini.general.name}") + mail(to: @emails, reply_to: "support@commitchange.com", from: "#{Houdini.general.name} Support", subject: "Set up automatic payouts on #{Houdini.general.name}") end def welcome(np_id) @@ -107,6 +107,6 @@ def welcome(np_id) @user = @nonprofit.users.first @token = @user.make_confirmation_token! @emails = QueryUsers.all_nonprofit_user_emails(np_id, [:nonprofit_admin]) - mail(to: @emails, reply_to: 'support@commitchange.com', from: "#{Houdini.general.name} Support", subject: "A hearty welcome from the #{Houdini.general.name} team") + mail(to: @emails, reply_to: "support@commitchange.com", from: "#{Houdini.general.name} Support", subject: "A hearty welcome from the #{Houdini.general.name} team") end end diff --git a/app/mailers/payment_mailer.rb b/app/mailers/payment_mailer.rb index 035a5db7f4..503fa456f2 100644 --- a/app/mailers/payment_mailer.rb +++ b/app/mailers/payment_mailer.rb @@ -7,10 +7,10 @@ class PaymentMailer < BaseMailer # or a ticket receipt def resend_admin_receipt(payment_id, user_id) payment = Payment.find(payment_id) - if payment.kind == 'Donation' || payment.kind == 'RecurringDonation' + if payment.kind == "Donation" || payment.kind == "RecurringDonation" PaymentNotificationEmailNonprofitJob.perform_later(payment.donation, User.find(user_id)) - elsif payment.kind == 'Ticket' - return TicketMailer.receipt_admin(payment.donation.id, user_id).deliver_later + elsif payment.kind == "Ticket" + TicketMailer.receipt_admin(payment.donation.id, user_id).deliver_later end end @@ -18,10 +18,10 @@ def resend_admin_receipt(payment_id, user_id) # or a ticket followup email to the supporter def resend_donor_receipt(payment_id) payment = Payment.find(payment_id) - if payment.kind == 'Donation' || payment.kind == 'RecurringDonation' - PaymentNotificationEmailDonorJob.perform_later payment.donation, (payment&.supporter&.locale || 'en') - elsif payment.kind == 'Ticket' - return TicketMailer.followup(payment.tickets.pluck(:id), payment.charge).deliver_later + if payment.kind == "Donation" || payment.kind == "RecurringDonation" + PaymentNotificationEmailDonorJob.perform_later payment.donation, (payment&.supporter&.locale || "en") + elsif payment.kind == "Ticket" + TicketMailer.followup(payment.tickets.pluck(:id), payment.charge).deliver_later end end end diff --git a/app/mailers/testing.rb b/app/mailers/testing.rb index 90e387236c..12accd365b 100644 --- a/app/mailers/testing.rb +++ b/app/mailers/testing.rb @@ -3,5 +3,5 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Testing < ActionMailer::Base - default from: 'from@example.com' + default from: "from@example.com" end diff --git a/app/mailers/ticket_mailer.rb b/app/mailers/ticket_mailer.rb index 9294466f43..8e18c7115b 100644 --- a/app/mailers/ticket_mailer.rb +++ b/app/mailers/ticket_mailer.rb @@ -8,22 +8,22 @@ class TicketMailer < BaseMailer # Pass in ticket_ids, event_id, and supporter 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}") + reply_to = @nonprofit.email.presence || @nonprofit.users.first.email + 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) + @tickets = Ticket.where("id IN (?)", ticket_ids) @charge = @tickets.last.charge @supporter = @tickets.last.supporter @event = @tickets.last.event @nonprofit = @event.nonprofit - recipients = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_events') + recipients = QueryUsers.nonprofit_user_emails(@nonprofit.id, "notify_events") if user_id em = User.find(user_id).email return unless recipients.include?(em) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index c017212cb9..cf5c02cbd1 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -8,7 +8,7 @@ def refund_receipt(refund_id) @nonprofit = @refund.payment.nonprofit @charge = @refund.charge @supporter = @refund.payment.supporter - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + reply_to = @nonprofit.email.presence || @nonprofit.users.first.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 @@ -16,12 +16,12 @@ def refund_receipt(refund_id) 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}.") + 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.") + subject: "Your recurring donation towards #{@recurring_donation.nonprofit.name} was successfully cancelled.") end end diff --git a/app/models/activity.rb b/app/models/activity.rb index ac7bb369fb..aded7c7ecc 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -3,16 +3,16 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Activity < ApplicationRecord - belongs_to :attachment, :polymorphic => true + belongs_to :attachment, polymorphic: true belongs_to :supporter - belongs_to :nonprofit - belongs_to :user - + belongs_to :nonprofit + belongs_to :user + def json_data=(data) - write_attribute :json_data, JSON::generate(data) + write_attribute :json_data, JSON.generate(data) end def json_data - JSON::parse(read_attribute :json_data) + JSON.parse(read_attribute(:json_data)) end end diff --git a/app/models/bank_account.rb b/app/models/bank_account.rb index 16236be440..3a38ab88de 100644 --- a/app/models/bank_account.rb +++ b/app/models/bank_account.rb @@ -18,18 +18,18 @@ class BankAccount < ApplicationRecord 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 + validate :nonprofit_must_be_vetted, on: :create + validate :nonprofit_has_stripe_account has_many :payouts belongs_to :nonprofit def nonprofit_must_be_vetted - errors.add(:nonprofit, 'must be vetted') unless nonprofit&.vetted + errors.add(:nonprofit, "must be vetted") unless nonprofit&.vetted end def nonprofit_has_stripe_account - errors.add(:nonprofit, 'must have a Stripe account id') if !nonprofit || nonprofit.stripe_account_id.blank? + errors.add(:nonprofit, "must have a Stripe account id") if !nonprofit || nonprofit.stripe_account_id.blank? end # Manually cause an instance to become invalid diff --git a/app/models/billing_plan.rb b/app/models/billing_plan.rb index 486b883be2..9f21a0dcc5 100644 --- a/app/models/billing_plan.rb +++ b/app/models/billing_plan.rb @@ -10,7 +10,7 @@ class BillingPlan < ApplicationRecord # :interval, #str ('monthly', 'annual') # :percentage_fee # 0.038 - Names = ['Starter', 'Fundraising', 'Supporter Management'].freeze + Names = ["Starter", "Fundraising", "Supporter Management"].freeze DefaultAmounts = [0, 9900, 29_900].freeze # in pennies has_many :billing_subscriptions diff --git a/app/models/billing_subscription.rb b/app/models/billing_subscription.rb index 8152f909f0..e8e9aa0058 100644 --- a/app/models/billing_subscription.rb +++ b/app/models/billing_subscription.rb @@ -16,7 +16,7 @@ class BillingSubscription < ApplicationRecord validates :billing_plan, presence: true def as_json(options = {}) - h = super(options) + h = super h[:plan_name] = billing_plan.name h[:plan_amount] = billing_plan.amount / 100 h diff --git a/app/models/campaign.rb b/app/models/campaign.rb index b333a5f6f3..c59937259d 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -39,16 +39,16 @@ class Campaign < ApplicationRecord # :reason_for_supporting, # :default_reason_for_supporting - validate :end_datetime_cannot_be_in_past, on: :create + 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 } + 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 + 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 @@ -56,31 +56,31 @@ class Campaign < ApplicationRecord has_one_attached :background_image has_one_attached :banner_image - has_one_attached_with_sizes(:main_image, {normal: [524, 360], thumb: [180,150]}) + has_one_attached_with_sizes(:main_image, {normal: [524, 360], thumb: [180, 150]}) has_one_attached_with_sizes(:background_image, {normal: [1000, 600]}) - has_one_attached_with_default(:main_image, Houdini.defaults.image.profile, + has_one_attached_with_default(:main_image, Houdini.defaults.image.profile, filename: "main_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.profile).extname}") has_many :donations has_many :charges, through: :donations - has_many :payments, through: :donations, source: 'payment' + 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 :campaign_gift_purchases - has_many :roles, as: :host, dependent: :destroy - has_many :activities, as: :host, dependent: :destroy + has_many :roles, 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' + 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 :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) } @@ -88,7 +88,7 @@ class Campaign < ApplicationRecord before_validation do if goal_amount_dollars.present? - self.goal_amount = (goal_amount_dollars.delete(',').to_f * 100).to_i + self.goal_amount = (goal_amount_dollars.delete(",").to_f * 100).to_i end self end @@ -117,17 +117,17 @@ def set_defaults end def parse_video_id - if video_url.include? 'vimeo' - self.vimeo_video_id = video_url.split('/').last + if video_url.include? "vimeo" + self.vimeo_video_id = video_url.split("/").last self.youtube_video_id = nil - elsif video_url.include? 'youtube' + elsif video_url.include? "youtube" match = video_url.match(/\?v=(.+)/) return if match.nil? - self.youtube_video_id = match[1].split('&').first + 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 + 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 @@ -137,7 +137,7 @@ def parse_video_id end def total_raised - self.payments.sum(:gross_amount) + payments.sum(:gross_amount) end def percentage_funded @@ -157,7 +157,7 @@ def end_datetime_cannot_be_in_past end def ready_to_publish? - [(body && body.length >= 500), (campaign_gift_options.count >= 1)].all? + [body && body.length >= 500, (campaign_gift_options.count >= 1)].all? end def url @@ -192,15 +192,14 @@ def parent_campaign? end def self.get_campaign_and_children(campaign) - where('campaigns.id = ? OR campaigns.parent_campaign_id = ? ',campaign, campaign) + where("campaigns.id = ? OR campaigns.parent_campaign_id = ? ", campaign, campaign) end def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :name) + json.call(self, :name) json.add_builder_expansion :nonprofit end end - end diff --git a/app/models/campaign_gift_option.rb b/app/models/campaign_gift_option.rb index b8dec5ad75..60180108d2 100644 --- a/app/models/campaign_gift_option.rb +++ b/app/models/campaign_gift_option.rb @@ -23,8 +23,8 @@ class CampaignGiftOption < ApplicationRecord validates :name, presence: true validates :campaign, presence: true - validates :amount_one_time, presence: true, numericality: { only_integer: true }, unless: :amount_recurring - validates :amount_recurring, presence: true, numericality: { only_integer: true }, unless: :amount_one_time + validates :amount_one_time, presence: true, numericality: {only_integer: true}, unless: :amount_recurring + validates :amount_recurring, presence: true, numericality: {only_integer: true}, unless: :amount_one_time after_create_commit :publish_created after_update_commit :publish_updated @@ -43,7 +43,7 @@ def gift_option_amounts if amount_recurring output.push(GiftOptionAmount.new( Amount.new(amount_recurring, currency), - GiftOptionRecurrence.new('monthly', 1) + GiftOptionRecurrence.new("monthly", 1) )) end output @@ -58,16 +58,14 @@ def total_gifts end def as_json(options = {}) - h = super(options) + h = super h[:total_gifts] = total_gifts h end def to_builder(*expand) - init_builder(*expand) do |json| - json.(self, :name, :description, - :hide_contributions, :order, :to_ship) + json.call(self, :name, :description, :hide_contributions, :order, :to_ship) if quantity json.quantity quantity @@ -76,12 +74,12 @@ def to_builder(*expand) json.deleted !persisted? json.gift_option_amount gift_option_amounts do |desc| - json.amount do + json.amount do json.currency desc.amount.currency json.cents desc.amount.cents end if desc.recurrence - json.recurrence do + json.recurrence do json.interval desc.recurrence.interval json.type desc.recurrence.type end @@ -95,21 +93,20 @@ def to_builder(*expand) end private + def publish_created - Houdini.event_publisher.announce(:campaign_gift_option_created, to_event('campaign_gift_option.created', :nonprofit, :campaign).attributes!) + Houdini.event_publisher.announce(:campaign_gift_option_created, to_event("campaign_gift_option.created", :nonprofit, :campaign).attributes!) end def publish_updated - Houdini.event_publisher.announce(:campaign_gift_option_updated, to_event('campaign_gift_option.updated', :nonprofit, :campaign).attributes!) + Houdini.event_publisher.announce(:campaign_gift_option_updated, to_event("campaign_gift_option.updated", :nonprofit, :campaign).attributes!) end def publish_deleted - Houdini.event_publisher.announce(:campaign_gift_option_deleted, to_event('campaign_gift_option.deleted', :nonprofit, :campaign).attributes!) + Houdini.event_publisher.announce(:campaign_gift_option_deleted, to_event("campaign_gift_option.deleted", :nonprofit, :campaign).attributes!) end end GiftOptionAmount = Struct.new(:amount, :recurrence) GiftOptionRecurrence = Struct.new(:type, :interval) - - diff --git a/app/models/campaign_gift_purchase.rb b/app/models/campaign_gift_purchase.rb index 1b4603b42a..d5596b56dc 100644 --- a/app/models/campaign_gift_purchase.rb +++ b/app/models/campaign_gift_purchase.rb @@ -8,15 +8,15 @@ class CampaignGiftPurchase < ApplicationRecord setup_houid :cgpur belongs_to :campaign - has_many :campaign_gifts, class_name: 'ModernCampaignGift' + has_many :campaign_gifts, class_name: "ModernCampaignGift" # TODO replace with Discard gem - define_model_callbacks :discard + define_model_callbacks :discard validates :amount, presence: true validates :campaign, presence: true - validates :campaign_gifts, length: { minimum: 1 } - + validates :campaign_gifts, length: {minimum: 1} + # TODO replace with discard gem def discard! run_callbacks(:discard) do @@ -25,20 +25,19 @@ def discard! end end - - def to_id - ::Jbuilder.new do |json| - json.id id - json.object 'campaign_gift_purchase' - json.type 'trx_assignment' - end - end + def to_id + ::Jbuilder.new do |json| + json.id id + json.object "campaign_gift_purchase" + json.type "trx_assignment" + end + end def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :deleted) - json.type 'trx_assignment' - + json.call(self, :deleted) + json.type "trx_assignment" + json.amount do json.cents amount json.currency nonprofit.currency @@ -51,14 +50,14 @@ def to_builder(*expand) end def publish_created - Houdini.event_publisher.announce(:campaign_gift_purchase_created, to_event('campaign_gift_purchase.created', :nonprofit, :supporter, :trx, :campaign, :campaign_gifts).attributes!) - end - - def publish_updated - Houdini.event_publisher.announce(:campaign_gift_purchase_updated, to_event('campaign_gift_purchase.updated', :nonprofit, :supporter, :trx, :campaign, :campaign_gifts).attributes!) - end + Houdini.event_publisher.announce(:campaign_gift_purchase_created, to_event("campaign_gift_purchase.created", :nonprofit, :supporter, :trx, :campaign, :campaign_gifts).attributes!) + end + + def publish_updated + Houdini.event_publisher.announce(:campaign_gift_purchase_updated, to_event("campaign_gift_purchase.updated", :nonprofit, :supporter, :trx, :campaign, :campaign_gifts).attributes!) + end - def publish_deleted - Houdini.event_publisher.announce(:campaign_gift_purchase_deleted, to_event('campaign_gift_purchase.deleted', :nonprofit, :supporter, :trx, :campaign, :campaign_gifts).attributes!) - end + def publish_deleted + Houdini.event_publisher.announce(:campaign_gift_purchase_deleted, to_event("campaign_gift_purchase.deleted", :nonprofit, :supporter, :trx, :campaign, :campaign_gifts).attributes!) + end end diff --git a/app/models/charge.rb b/app/models/charge.rb index a7dd6a254a..6ab757a04a 100644 --- a/app/models/charge.rb +++ b/app/models/charge.rb @@ -26,10 +26,10 @@ class Charge < ApplicationRecord has_one :stripe_charge, through: :payment scope :paid, -> { where(status: %w[available pending disbursed]) } - scope :not_paid, -> { where(status: [nil, 'failed']) } - scope :available, -> { where(status: 'available') } - scope :pending, -> { where(status: 'pending') } - scope :disbursed, -> { where(status: 'disbursed') } + scope :not_paid, -> { where(status: [nil, "failed"]) } + scope :available, -> { where(status: "available") } + scope :pending, -> { where(status: "pending") } + scope :disbursed, -> { where(status: "disbursed") } def paid? status.in?(%w[available pending disbursed]) diff --git a/app/models/comment.rb b/app/models/comment.rb index 4b7b844075..f3f32e9608 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -9,7 +9,7 @@ class Comment < ApplicationRecord # :body validates :profile, presence: true - validates :body, presence: true, length: { maximum: 200 } + validates :body, presence: true, length: {maximum: 200} has_one :activity, as: :attachment, dependent: :destroy belongs_to :host, polymorphic: true @@ -22,7 +22,7 @@ class Comment < ApplicationRecord after_create do create_activity( - desc: 'commented', + desc: "commented", profile_id: profile_id, host_id: host_id, host_type: host_type, diff --git a/app/models/concerns/image/attachment_extensions.rb b/app/models/concerns/image/attachment_extensions.rb index a7de39a383..22bfc8461d 100644 --- a/app/models/concerns/image/attachment_extensions.rb +++ b/app/models/concerns/image/attachment_extensions.rb @@ -1,50 +1,50 @@ module Image::AttachmentExtensions - extend ActiveSupport::Concern - class_methods do - def has_one_attached_with_sizes(attribute_name, sizes) - if sizes.nil? || !sizes.is_a?(Hash) || !sizes.any? - raise ArgumentError, "You must pass a valid hash of sizes" - end - attribute = attribute_name.to_s + extend ActiveSupport::Concern + class_methods do + def has_one_attached_with_sizes(attribute_name, sizes) + if sizes.nil? || !sizes.is_a?(Hash) || !sizes.any? + raise ArgumentError, "You must pass a valid hash of sizes" + end + attribute = attribute_name.to_s - # clean up sizes - sizes.each_key do |key| - value = sizes[key] - if value.is_a?(Numeric) - sizes[key] = [value, value] - elsif value.is_a?(Array) && value.count == 1 && value.all?{|i| i.is_a?(Numeric)} - sizes[key]= [value[0], value[0]] - elsif value.is_a?(Array) && value.count == 2 && value.all?{|i| i.is_a?(Numeric)} - sizes[key] = [value[0], value[1]] - else - raise ArgumentError, "#{value.to_s} was not a valid size." - end - end + # clean up sizes + sizes.each_key do |key| + value = sizes[key] + if value.is_a?(Numeric) + sizes[key] = [value, value] + elsif value.is_a?(Array) && value.count == 1 && value.all? { |i| i.is_a?(Numeric) } + sizes[key] = [value[0], value[0]] + elsif value.is_a?(Array) && value.count == 2 && value.all? { |i| i.is_a?(Numeric) } + sizes[key] = [value[0], value[1]] + else + raise ArgumentError, "#{value} was not a valid size." + end + end - class_eval <<-RUBY, __FILE__, __LINE__ + 1 + class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{attribute}_by_size(size) case (size) - #{sizes.map do |k,v| - <<-INNER + #{sizes.map do |k, v| + <<-INNER when :#{k.to_sym} return #{attribute}.variant(resize_to_limit: [#{v[0]}, #{v[1]}]) - INNER + INNER end.join("\n")} else - raise ArgumentError, ":" + size.to_s + " is not a valid size. Valid sizes are: #{sizes.keys.map{|i| ":" + i.to_s}.join(', ')}" + raise ArgumentError, ":" + size.to_s + " is not a valid size. Valid sizes are: #{sizes.keys.map { |i| ":" + i.to_s }.join(", ")}" end end - RUBY - end + RUBY + end - def has_one_attached_with_default(attribute_name, default_path, **options) - after_save do - attribute = send(attribute_name) - unless attribute.attached? - attribute.attach(io: File.open(default_path), **options) - end - self - end + def has_one_attached_with_default(attribute_name, default_path, **options) + after_save do + attribute = send(attribute_name) + unless attribute.attached? + attribute.attach(io: File.open(default_path), **options) end + self + end end -end \ No newline at end of file + end +end diff --git a/app/models/concerns/model/created_timeable.rb b/app/models/concerns/model/created_timeable.rb index 6a03fa5d5d..3862a2d081 100644 --- a/app/models/concerns/model/created_timeable.rb +++ b/app/models/concerns/model/created_timeable.rb @@ -3,14 +3,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Model::CreatedTimeable - extend ActiveSupport::Concern - included do - after_initialize :set_created_if_needed + extend ActiveSupport::Concern + included do + after_initialize :set_created_if_needed - private + private - def set_created_if_needed - self[:created] = Time.current unless self[:created] - end - end + def set_created_if_needed + self[:created] = Time.current unless self[:created] + end + end end diff --git a/app/models/concerns/model/eventable.rb b/app/models/concerns/model/eventable.rb index b49d47c4c8..de4701c1ef 100644 --- a/app/models/concerns/model/eventable.rb +++ b/app/models/concerns/model/eventable.rb @@ -3,19 +3,19 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Model::Eventable - extend ActiveSupport::Concern - def to_event(event_type, *expand) - Jbuilder.new do |event| - event.id "objevt_" + SecureRandom.alphanumeric(22) - event.object 'object_event' - event.type event_type - event.data do - event.object to_builder(*expand) - end - end - end - def to_builder(*expand) - raise NotImplementedError.new("to_builder must be implemented in your model") - end - -end \ No newline at end of file + extend ActiveSupport::Concern + def to_event(event_type, *expand) + Jbuilder.new do |event| + event.id "objevt_" + SecureRandom.alphanumeric(22) + event.object "object_event" + event.type event_type + event.data do + event.object to_builder(*expand) + end + end + end + + def to_builder(*expand) + raise NotImplementedError.new("to_builder must be implemented in your model") + end +end diff --git a/app/models/concerns/model/houidable.rb b/app/models/concerns/model/houidable.rb index 27966adf64..253f4b87e6 100644 --- a/app/models/concerns/model/houidable.rb +++ b/app/models/concerns/model/houidable.rb @@ -8,55 +8,55 @@ # 22 random base-62 characters (a-z, A-Z and 0-9). To use in a class, include this module and use {.setup_houid} # @see .setup_houid module Model::Houidable - extend ActiveSupport::Concern - class_methods do - ### - # Simplifies using HouIDs for an ActiveRecord class. HouIDs have the format of: - # prefix_{22 alphanumeric characters}. Prefixes must be unique across an Houdini instance. - # Given a prefix, adds the following features to a ActiveRecord class: - # - Sets a HouID to the id before save (on "before_save" callback) if - # it hasn't already been set - # - Adds a "before_houid_set" and "after_houid_set" callbacks in case you want do - # some things before or after that happens - # - Adds "before_houid_set" and "after_houid_set" callbacks if you want to take actions around - # - Adds two new public methods: - # - {#houid_prefix} - returns the prefix as a symbol - # - {#generate_houid} - creates a new HouID with given prefix - # @param prefix [string, Symbol] the prefix for the HouIDs on this model - # @param houid_attribute [string, Symbol] the attribute on this model to assign the Houid to. Defaults to :id. - # @example HouIDs for this class, on the :id attribute, will start with 'supp_' - # class CustomSupporter - # setup_houid(:supp) - # end - # @example HouIDs for this class, on the :houid attribute, will start with 'supp_' - # class CustomSupporter - # setup_houid(:supp, :houid) - # end - # - ### - def setup_houid(prefix, houid_attribute = :id) - ###### - # define_model_callbacks :houid_set - # before_save :add_houid + extend ActiveSupport::Concern + class_methods do + ### + # Simplifies using HouIDs for an ActiveRecord class. HouIDs have the format of: + # prefix_{22 alphanumeric characters}. Prefixes must be unique across an Houdini instance. + # Given a prefix, adds the following features to a ActiveRecord class: + # - Sets a HouID to the id before save (on "before_save" callback) if + # it hasn't already been set + # - Adds a "before_houid_set" and "after_houid_set" callbacks in case you want do + # some things before or after that happens + # - Adds "before_houid_set" and "after_houid_set" callbacks if you want to take actions around + # - Adds two new public methods: + # - {#houid_prefix} - returns the prefix as a symbol + # - {#generate_houid} - creates a new HouID with given prefix + # @param prefix [string, Symbol] the prefix for the HouIDs on this model + # @param houid_attribute [string, Symbol] the attribute on this model to assign the Houid to. Defaults to :id. + # @example HouIDs for this class, on the :id attribute, will start with 'supp_' + # class CustomSupporter + # setup_houid(:supp) + # end + # @example HouIDs for this class, on the :houid attribute, will start with 'supp_' + # class CustomSupporter + # setup_houid(:supp, :houid) + # end + # + ### + def setup_houid(prefix, houid_attribute = :id) + ###### + # define_model_callbacks :houid_set + # before_save :add_houid - # # The HouID prefix as a symbol - # def houid_prefix - # :supp - # end + # # The HouID prefix as a symbol + # def houid_prefix + # :supp + # end - # # Generates a HouID using the provided houid_prefix - # def generate_houid - # houid_prefix.to_s + "_" + SecureRandom.alphanumeric(22) - # end + # # Generates a HouID using the provided houid_prefix + # def generate_houid + # houid_prefix.to_s + "_" + SecureRandom.alphanumeric(22) + # end - # private - # def add_houid - # run_callbacks(:houid_set) do - # write_attribute(:id, self.generate_houid) unless read_attribute(:id) - # end - # end - ##### - class_eval <<-RUBY, __FILE__, __LINE__ + 1 # rubocop:disable Style/DocumentDynamicEvalDefinition + # private + # def add_houid + # run_callbacks(:houid_set) do + # write_attribute(:id, self.generate_houid) unless read_attribute(:id) + # end + # end + ##### + class_eval <<-RUBY, __FILE__, __LINE__ + 1 # rubocop:disable Style/DocumentDynamicEvalDefinition define_model_callbacks :houid_set before_save :add_houid @@ -83,7 +83,7 @@ def add_houid write_attribute(self.houid_attribute, self.generate_houid) unless read_attribute(self.houid_attribute) end end - RUBY - end - end + RUBY + end + end end diff --git a/app/models/concerns/model/jbuilder.rb b/app/models/concerns/model/jbuilder.rb index 327801e77c..51942a7f59 100644 --- a/app/models/concerns/model/jbuilder.rb +++ b/app/models/concerns/model/jbuilder.rb @@ -3,243 +3,242 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Model::Jbuilder - extend ActiveSupport::Concern - class_methods do - # - # Builder expansions address a common issue when using Jbuilder for generated JSON for object events work with `#init_builder` - # In some situations, a model may reference another object but, depending on the situation, may not want to expand that object - # - # As an example, consider an hypothetical Supporter class with a reference to a Nonprofit - # - # class Supporter < ApplicationRecord - # belongs_to :nonprofit - # belongs_to :group - # def to_builder(*expand) - # init_builder(*expand) do - # # build you JBuilder object - # end - # end - # end - # - # When generating the the Jbuilder object, you may want to expand the nonprofit object or in other situations not expand it. To handle this - # you would need to write the following code: - # ` - # if expand.include? :nonprofit - # json.nonprofit nonprofit.to_builder.attributes! - # else - # json.nonprofit nonprofit.to_id - # end - # ` - # You would have to write the same code for `group`. As your number of expandable attributes increase, your code gets filled with boilerplate code. - # - # `add_builder_expansion` addresses this by autocreating this code in to_builder. - # For example, if you want nonprofit to be expandable as in the nonprofit json attribute, and group into the group json attribute. You only need to write: - # `add_builder_expansion :nonprofit, :group` - # You can put as many expandable attributes there as you'd like. - # - # On the other hand, let's say you want to make group expandable BUT you want to assign it to the "supporter_group" json attribute. To do that, you - # pass in the attribute you want to be expandable along with the "json_attribute" method key set to 'supporter_group': - # `add_builder_expansion :group, json_attribute: 'supporter_group'` - # - # For enumerable attributes (like a has_many or an array), there are two ways you may want to include them into your json output. If it's a set of simple values - # like, an array of strings or numbers, you may want to want to the array output as-is. For example, let's say you have a array of tags which are strings. You may want - # it to be output like so: - # ```` - # tags: [ 'founders circle', 'large donor'] - # ``` - # We call these `:flat` enumerable attribtes. Assuming the supporter class before has a tags attribute, you would add the tags builder_expansion using: - # ``` - # add_builder_expansion :tags, enum_type: :flat - # ``` - # - # On the other hand, you may want to have an array of other Jbuilder created objects. Let's say your supporter has many groups. You may want these attributes expanded in - # one of two ways: expanded or unexpanded. - # - # For expanded, you would receive have something like this in your output: - # - # { - # # ... some other parts of the supporter json - # groups: [{ id: 546, name: 'group name 1'}, {id: 235, name: 'group name 2'}] - # } - # - # However, for unexpanded, you'd just want the ids: - # - # { - # # ... some other parts of the supporter json - # groups: [546, 235] - # } - # - # For this type of builder expansion, you would use: - # ``` - # add_builder expansion :groups, enum_type: :expandable - # ``` - # - # @param [Symbol] *attributes the attributes you'd like to make expandable. If you want to set options, there should only be a single attribute here. - # @param **options options for configuring the builder expansion. The options right now are: - # - `json_attribute`: the json attribute name in the outputted Jbuilder. Defaults to the attribute name. - # - `enum_type`: the type of enumerable for the attribute. pass :flat if the enumerable attribute is flat, or :expandable if it's expandable. ANy other value - # including the default of nil, means the attribute is not enumerable. - # - def add_builder_expansion(*attributes, **options) - builder_expansions.add_builder_expansion(*attributes, **options) - end - - # - # A set of all the builder expansions configured for a class - # - # @return [Array] the builder expansions - # - def builder_expansions - @builder_expansions ||= BuilderExpansionSet.new - end - - def init_builder(model, *expand) - JbuilderWithExpansions.new(model, *expand) do | json| - json.(model, :id) - json.object model.class.name.underscore - - yield(json) - end - end - - - @minimize_to_object = false - - def to_id_is_object - @minimize_to_object = true - end - - def to_id_object? - @minimize_to_object - end - end - - def to_id_object? - self.class.to_id_object? - end - - def to_id - id - end - - class BuilderExpansionSet < Set - def add_builder_expansion(*args, **kwargs) - be = nil - if args.any? || kwargs.any? - if (args.count == 1 && kwargs.any?) - be = BuilderExpansion.new(**{key: args[0]}.merge(kwargs)) - add(be) - else - args.each do |a| - be = BuilderExpansion.new(key: a) - add(be) - end - end - else - raise ArgumentError - end - end - - def keys - map{|i| i.key} - end - - def get_by_key(key) - select{|i| i.key == key}.first - end - end - - class BuilderExpansion - include ActiveModel::AttributeAssignment - attr_accessor :key, :json_attribute, :enum_type - - def initialize(new_attributes) - assign_attributes(new_attributes) - end - def enumerable? - expandable_enum? || flat_enum? - end - - def expandable_enum? - enum_type == :expandable - end - - def flat_enum? - enum_type == :flat - end - - def json_attribute - (@json_attribute || key).to_s - end - - def to_id - return ->(model,be=self) { - value = be.get_attribute_value model - if be.expandable_enum? - value&.map do |i| - id_result = i&.to_id - if ::Jbuilder === id_result - id_result.attributes! - else - id_result - end - end - elsif be.flat_enum? - value - else - value&.to_id - end - } - end - - def to_builder - return ->(model,be=self) { - value = be.get_attribute_value model - if be.expandable_enum? - value&.map{|i| i&.to_builder.attributes!} - elsif be.flat_enum? - value - else - value&.to_builder - end - } - end - - def get_attribute_value(model) - if model.respond_to? key - model.send(key) - else - raise ActiveModel::MissingAttributeError, "missing attribute: #{key}" - end - end - end - - def init_builder(*expand, &block) - self.class.init_builder(self, *expand, &block) - end - - - class JbuilderWithExpansions < ::Jbuilder - attr_reader :model, :expand - - delegate_missing_to :@jbuilder - - def initialize(model, *expand, &block) - @model = model - @expand = expand - super(&block) - end - - def add_builder_expansion( ... ) - builder_expansions = BuilderExpansionSet.new - builder_expansions.add_builder_expansion( ... ) - builder_expansions.keys.each do |k| - if expand.include? k - set! builder_expansions.get_by_key(k).json_attribute, builder_expansions.get_by_key(k).to_builder.(model) - else - set! builder_expansions.get_by_key(k).json_attribute, builder_expansions.get_by_key(k).to_id.(model) - end - end - end - end -end \ No newline at end of file + extend ActiveSupport::Concern + class_methods do + # + # Builder expansions address a common issue when using Jbuilder for generated JSON for object events work with `#init_builder` + # In some situations, a model may reference another object but, depending on the situation, may not want to expand that object + # + # As an example, consider an hypothetical Supporter class with a reference to a Nonprofit + # + # class Supporter < ApplicationRecord + # belongs_to :nonprofit + # belongs_to :group + # def to_builder(*expand) + # init_builder(*expand) do + # # build you JBuilder object + # end + # end + # end + # + # When generating the the Jbuilder object, you may want to expand the nonprofit object or in other situations not expand it. To handle this + # you would need to write the following code: + # ` + # if expand.include? :nonprofit + # json.nonprofit nonprofit.to_builder.attributes! + # else + # json.nonprofit nonprofit.to_id + # end + # ` + # You would have to write the same code for `group`. As your number of expandable attributes increase, your code gets filled with boilerplate code. + # + # `add_builder_expansion` addresses this by autocreating this code in to_builder. + # For example, if you want nonprofit to be expandable as in the nonprofit json attribute, and group into the group json attribute. You only need to write: + # `add_builder_expansion :nonprofit, :group` + # You can put as many expandable attributes there as you'd like. + # + # On the other hand, let's say you want to make group expandable BUT you want to assign it to the "supporter_group" json attribute. To do that, you + # pass in the attribute you want to be expandable along with the "json_attribute" method key set to 'supporter_group': + # `add_builder_expansion :group, json_attribute: 'supporter_group'` + # + # For enumerable attributes (like a has_many or an array), there are two ways you may want to include them into your json output. If it's a set of simple values + # like, an array of strings or numbers, you may want to want to the array output as-is. For example, let's say you have a array of tags which are strings. You may want + # it to be output like so: + # ```` + # tags: [ 'founders circle', 'large donor'] + # ``` + # We call these `:flat` enumerable attribtes. Assuming the supporter class before has a tags attribute, you would add the tags builder_expansion using: + # ``` + # add_builder_expansion :tags, enum_type: :flat + # ``` + # + # On the other hand, you may want to have an array of other Jbuilder created objects. Let's say your supporter has many groups. You may want these attributes expanded in + # one of two ways: expanded or unexpanded. + # + # For expanded, you would receive have something like this in your output: + # + # { + # # ... some other parts of the supporter json + # groups: [{ id: 546, name: 'group name 1'}, {id: 235, name: 'group name 2'}] + # } + # + # However, for unexpanded, you'd just want the ids: + # + # { + # # ... some other parts of the supporter json + # groups: [546, 235] + # } + # + # For this type of builder expansion, you would use: + # ``` + # add_builder expansion :groups, enum_type: :expandable + # ``` + # + # @param [Symbol] *attributes the attributes you'd like to make expandable. If you want to set options, there should only be a single attribute here. + # @param **options options for configuring the builder expansion. The options right now are: + # - `json_attribute`: the json attribute name in the outputted Jbuilder. Defaults to the attribute name. + # - `enum_type`: the type of enumerable for the attribute. pass :flat if the enumerable attribute is flat, or :expandable if it's expandable. ANy other value + # including the default of nil, means the attribute is not enumerable. + # + def add_builder_expansion(*attributes, **options) + builder_expansions.add_builder_expansion(*attributes, **options) + end + + # + # A set of all the builder expansions configured for a class + # + # @return [Array] the builder expansions + # + def builder_expansions + @builder_expansions ||= BuilderExpansionSet.new + end + + def init_builder(model, *expand) + JbuilderWithExpansions.new(model, *expand) do |json| + json.call(model, :id) + json.object model.class.name.underscore + + yield(json) + end + end + + @minimize_to_object = false + + def to_id_is_object + @minimize_to_object = true + end + + def to_id_object? + @minimize_to_object + end + end + + def to_id_object? + self.class.to_id_object? + end + + def to_id + id + end + + class BuilderExpansionSet < Set + def add_builder_expansion(*args, **kwargs) + be = nil + if args.any? || kwargs.any? + if args.count == 1 && kwargs.any? + be = BuilderExpansion.new(key: args[0], **kwargs) + add(be) + else + args.each do |a| + be = BuilderExpansion.new(key: a) + add(be) + end + end + else + raise ArgumentError + end + end + + def keys + map { |i| i.key } + end + + def get_by_key(key) + select { |i| i.key == key }.first + end + end + + class BuilderExpansion + include ActiveModel::AttributeAssignment + attr_accessor :key, :json_attribute, :enum_type + + def initialize(new_attributes) + assign_attributes(new_attributes) + end + + def enumerable? + expandable_enum? || flat_enum? + end + + def expandable_enum? + enum_type == :expandable + end + + def flat_enum? + enum_type == :flat + end + + def json_attribute + (@json_attribute || key).to_s + end + + def to_id + ->(model, be = self) { + value = be.get_attribute_value model + if be.expandable_enum? + value&.map do |i| + id_result = i&.to_id + if ::Jbuilder === id_result + id_result.attributes! + else + id_result + end + end + elsif be.flat_enum? + value + else + value&.to_id + end + } + end + + def to_builder + ->(model, be = self) { + value = be.get_attribute_value model + if be.expandable_enum? + value&.map { |i| i&.to_builder&.attributes! } + elsif be.flat_enum? + value + else + value&.to_builder + end + } + end + + def get_attribute_value(model) + if model.respond_to? key + model.send(key) + else + raise ActiveModel::MissingAttributeError, "missing attribute: #{key}" + end + end + end + + def init_builder(*expand, &block) + self.class.init_builder(self, *expand, &block) + end + + class JbuilderWithExpansions < ::Jbuilder + attr_reader :model, :expand + + delegate_missing_to :@jbuilder + + def initialize(model, *expand, &block) + @model = model + @expand = expand + super(&block) + end + + def add_builder_expansion(...) + builder_expansions = BuilderExpansionSet.new + builder_expansions.add_builder_expansion(...) + builder_expansions.keys.each do |k| + if expand.include? k + set! builder_expansions.get_by_key(k).json_attribute, builder_expansions.get_by_key(k).to_builder.call(model) + else + set! builder_expansions.get_by_key(k).json_attribute, builder_expansions.get_by_key(k).to_id.call(model) + end + end + end + end +end diff --git a/app/models/concerns/model/subtransactable.rb b/app/models/concerns/model/subtransactable.rb index 0c49eb680f..090405d751 100644 --- a/app/models/concerns/model/subtransactable.rb +++ b/app/models/concerns/model/subtransactable.rb @@ -3,18 +3,18 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Model::Subtransactable - extend ActiveSupport::Concern + extend ActiveSupport::Concern - included do - include Model::Houidable - include Model::Jbuilder - include Model::Eventable + included do + include Model::Houidable + include Model::Jbuilder + include Model::Eventable - has_one :subtransaction, as: :subtransactable, dependent: :nullify - has_one :trx, through: :subtransaction - has_one :supporter, through: :trx - has_one :nonprofit, through: :trx + has_one :subtransaction, as: :subtransactable, dependent: :nullify + has_one :trx, through: :subtransaction + has_one :supporter, through: :trx + has_one :nonprofit, through: :trx - has_many :payments, through: :subtransaction, as: 'SubtransactionPayment' - end + has_many :payments, through: :subtransaction, as: "SubtransactionPayment" + end end diff --git a/app/models/concerns/model/subtransaction_paymentable.rb b/app/models/concerns/model/subtransaction_paymentable.rb index c620930c01..7b5ad87947 100644 --- a/app/models/concerns/model/subtransaction_paymentable.rb +++ b/app/models/concerns/model/subtransaction_paymentable.rb @@ -3,18 +3,18 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Model::SubtransactionPaymentable - extend ActiveSupport::Concern + extend ActiveSupport::Concern - included do - include Model::Houidable - include Model::Jbuilder - include Model::Eventable + included do + include Model::Houidable + include Model::Jbuilder + include Model::Eventable - has_one :subtransaction_payment, as: :paymentable, touch: true, dependent: :destroy - has_one :trx, through: :subtransaction_payment - has_one :supporter, through: :subtransaction_payment - has_one :nonprofit, through: :subtransaction_payment + has_one :subtransaction_payment, as: :paymentable, touch: true, dependent: :destroy + has_one :trx, through: :subtransaction_payment + has_one :supporter, through: :subtransaction_payment + has_one :nonprofit, through: :subtransaction_payment - has_one :subtransaction, through: :subtransaction_payment - end + has_one :subtransaction, through: :subtransaction_payment + end end diff --git a/app/models/concerns/model/trx_assignable.rb b/app/models/concerns/model/trx_assignable.rb index 42e76263eb..7633c2bdca 100644 --- a/app/models/concerns/model/trx_assignable.rb +++ b/app/models/concerns/model/trx_assignable.rb @@ -3,21 +3,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Model::TrxAssignable - extend ActiveSupport::Concern + extend ActiveSupport::Concern - included do - include Model::Houidable - include Model::Jbuilder - include Model::Eventable + included do + include Model::Houidable + include Model::Jbuilder + include Model::Eventable - add_builder_expansion :nonprofit, :supporter + add_builder_expansion :nonprofit, :supporter - add_builder_expansion :trx, - json_attribute: :transaction + add_builder_expansion :trx, + json_attribute: :transaction - has_one :transaction_assignment, as: :assignable - has_one :trx, through: :transaction_assignment, class_name: 'Transaction', foreign_key: 'transaction_id' - has_one :supporter, through: :transaction_assignment - has_one :nonprofit, through: :transaction_assignment - end + has_one :transaction_assignment, as: :assignable + has_one :trx, through: :transaction_assignment, class_name: "Transaction", foreign_key: "transaction_id" + has_one :supporter, through: :transaction_assignment + has_one :nonprofit, through: :transaction_assignment + end end diff --git a/app/models/custom_field_definition.rb b/app/models/custom_field_definition.rb index a9f3c93ada..db12420b4b 100644 --- a/app/models/custom_field_definition.rb +++ b/app/models/custom_field_definition.rb @@ -3,56 +3,56 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class CustomFieldDefinition < ApplicationRecord - include Model::Eventable - include Model::Jbuilder + include Model::Eventable + include Model::Jbuilder - validates :name, presence: true - validate :no_dupes, on: :create + validates :name, presence: true + validate :no_dupes, on: :create - belongs_to :nonprofit - has_many :custom_field_joins, dependent: :destroy + belongs_to :nonprofit + has_many :custom_field_joins, dependent: :destroy - scope :not_deleted, -> { where(deleted: false) } + scope :not_deleted, -> { where(deleted: false) } - after_create_commit :publish_created + after_create_commit :publish_created - # TODO: replace with Discard gem - define_model_callbacks :discard + # TODO: replace with Discard gem + define_model_callbacks :discard - after_discard :publish_delete + after_discard :publish_delete - # TODO: replace with discard gem - def discard! - run_callbacks(:discard) do - self.deleted = true - save! - end - end + # TODO: replace with discard gem + def discard! + run_callbacks(:discard) do + self.deleted = true + save! + end + end - def no_dupes - return self if nonprofit.nil? + def no_dupes + return self if nonprofit.nil? - errors.add(:base, 'Duplicate custom field') if nonprofit.custom_field_definitions.not_deleted.where(name: name).any? - end + errors.add(:base, "Duplicate custom field") if nonprofit.custom_field_definitions.not_deleted.where(name: name).any? + end - def to_builder(*expand) - init_builder(*expand) do |json| - json.(self, :name, :deleted) - json.object 'custom_field_definition' + def to_builder(*expand) + init_builder(*expand) do |json| + json.call(self, :name, :deleted) + json.object "custom_field_definition" - json.add_builder_expansion :nonprofit - end - end + json.add_builder_expansion :nonprofit + end + end - private + private - def publish_created - Houdini.event_publisher.announce(:custom_field_definition_created, - to_event('custom_field_definition.created', :nonprofit).attributes!) - end + def publish_created + Houdini.event_publisher.announce(:custom_field_definition_created, + to_event("custom_field_definition.created", :nonprofit).attributes!) + end - def publish_delete - Houdini.event_publisher.announce(:custom_field_definition_deleted, - to_event('custom_field_definition.deleted', :nonprofit).attributes!) - end + def publish_delete + Houdini.event_publisher.announce(:custom_field_definition_deleted, + to_event("custom_field_definition.deleted", :nonprofit).attributes!) + end end diff --git a/app/models/custom_field_join.rb b/app/models/custom_field_join.rb index 1a4a313432..d3adc4e3d2 100644 --- a/app/models/custom_field_join.rb +++ b/app/models/custom_field_join.rb @@ -15,12 +15,12 @@ class CustomFieldJoin < ApplicationRecord belongs_to :supporter def self.create_with_name(nonprofit, h) - cfm = nonprofit.custom_field_definitions.find_by_name(h['name']) - cfm = nonprofit.custom_field_definitions.create(name: h['name']) if cfm.nil? - create(value: h['value'], custom_field_definition_id: cfm.id, supporter_id: h['supporter_id']) + cfm = nonprofit.custom_field_definitions.find_by_name(h["name"]) + cfm = nonprofit.custom_field_definitions.create(name: h["name"]) if cfm.nil? + create(value: h["value"], custom_field_definition_id: cfm.id, supporter_id: h["supporter_id"]) end def name custom_field_definition.name -end + end end diff --git a/app/models/direct_debit_detail.rb b/app/models/direct_debit_detail.rb index 26ff7fc4c2..953a9f8d31 100644 --- a/app/models/direct_debit_detail.rb +++ b/app/models/direct_debit_detail.rb @@ -11,5 +11,5 @@ class DirectDebitDetail < ApplicationRecord has_many :donations has_many :charges - belongs_to :holder, class_name: 'Supporter' + belongs_to :holder, class_name: "Supporter" end diff --git a/app/models/donation.rb b/app/models/donation.rb index 8f5a42a240..7a51f8f868 100644 --- a/app/models/donation.rb +++ b/app/models/donation.rb @@ -22,11 +22,11 @@ class Donation < ApplicationRecord # :direct_debit_detail_id, :direct_debit_detail, # :payment_provider - validates :amount, presence: true, numericality: { only_integer: true } + validates :amount, presence: true, numericality: {only_integer: true} validates :supporter, presence: true validates :nonprofit, presence: true validates_associated :charges - validates :payment_provider, inclusion: { in: %w[credit_card sepa] }, allow_blank: true + validates :payment_provider, inclusion: {in: %w[credit_card sepa]}, allow_blank: true has_many :charges has_many :campaign_gifts, dependent: :destroy diff --git a/app/models/errors/active_model_error.rb b/app/models/errors/active_model_error.rb index 5963e62138..ef400b627b 100644 --- a/app/models/errors/active_model_error.rb +++ b/app/models/errors/active_model_error.rb @@ -1,5 +1,2 @@ - - class Errors::ActiveModelError < StandardError - -end \ No newline at end of file +end diff --git a/app/models/errors/message_invalid.rb b/app/models/errors/message_invalid.rb index b4fed5a1c8..4eeb26d577 100644 --- a/app/models/errors/message_invalid.rb +++ b/app/models/errors/message_invalid.rb @@ -1,17 +1,14 @@ - class Errors::MessageInvalid < Errors::ActiveModelError - - attr_reader :record - def initialize(record=nil) - if record - @record = record - errors = @record.errors.full_messages.join(", ") - message = I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", errors: errors, default: :"errors.messages.record_invalid") - else - message = "Record invalid" - end - - super(message) - + attr_reader :record + def initialize(record = nil) + if record + @record = record + errors = @record.errors.full_messages.join(", ") + message = I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", errors: errors, default: :"errors.messages.record_invalid") + else + message = "Record invalid" end -end \ No newline at end of file + + super(message) + end +end diff --git a/app/models/event.rb b/app/models/event.rb index 94f8b5f497..7a69e7fd1a 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -42,7 +42,7 @@ class Event < ApplicationRecord validates :address, presence: true validates :city, presence: true validates :state_code, presence: true - validates :slug, presence: true, uniqueness: { scope: :nonprofit_id, message: 'You already have an event with that URL' } + validates :slug, presence: true, uniqueness: {scope: :nonprofit_id, message: "You already have an event with that URL"} validates :nonprofit_id, presence: true validates :profile_id, presence: true @@ -56,10 +56,8 @@ class Event < ApplicationRecord has_many :event_discounts, dependent: :destroy has_many :tickets has_many :payments, through: :tickets - has_many :roles, as: :host, dependent: :destroy - has_many :activities, as: :host, dependent: :destroy - - + has_many :roles, as: :host, dependent: :destroy + has_many :activities, as: :host, dependent: :destroy accepts_nested_attributes_for :ticket_levels, allow_destroy: true has_one_attached :main_image @@ -68,21 +66,20 @@ class Event < ApplicationRecord has_one_attached_with_sizes :main_image, {normal: 400, thumb: 100} has_one_attached_with_sizes :background_image, {normal: [1000, 600]} - has_one_attached_with_default(:main_image, Houdini.defaults.image.profile, + has_one_attached_with_default(:main_image, Houdini.defaults.image.profile, filename: "main_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.profile).extname}") - has_one_attached_with_default(:background_image, Houdini.defaults.image.campaign, - filename: "background_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.campaign).extname}") - + has_one_attached_with_default(:background_image, Houdini.defaults.image.campaign, + filename: "background_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.campaign).extname}") scope :not_deleted, -> { where(deleted: [nil, false]) } scope :deleted, -> { where(deleted: true) } scope :published, -> { where(published: true) } - scope :upcoming, -> { where('start_datetime >= ?', Date.today).published } - scope :past, -> { where('end_datetime < ?', Date.today).published } - scope :unpublished, -> { where('published != ?', true) } + scope :upcoming, -> { where("start_datetime >= ?", Date.today).published } + scope :past, -> { where("end_datetime < ?", Date.today).published } + scope :unpublished, -> { where.not(published: true) } - validates :slug, uniqueness: { scope: :nonprofit_id, message: 'You already have a campaign with that name.' } + validates :slug, uniqueness: {scope: :nonprofit_id, message: "You already have a campaign with that name."} before_validation(on: :create) do self.slug = Format::Url.convert_to_slug(name) unless slug @@ -98,9 +95,9 @@ class Event < ApplicationRecord self end - def to_builder(*expand) + def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :name) + json.call(self, :name) json.add_builder_expansion :nonprofit end end diff --git a/app/models/event_discount.rb b/app/models/event_discount.rb index 47ce938302..e19da636b0 100644 --- a/app/models/event_discount.rb +++ b/app/models/event_discount.rb @@ -15,7 +15,6 @@ class EventDiscount < ApplicationRecord validates :event, presence: true validates :percent, presence: true, numericality: {only_integer: true, greater_than: 0, less_than_or_equal_to: 100} - # we use after_create_commit because the db could be in an inconsistent state and the messages will be slightly wrong # we use after commit on the rest for consistency after_create_commit :publish_create @@ -29,9 +28,9 @@ class EventDiscount < ApplicationRecord def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :name, :code) + json.call(self, :name, :code) json.deleted !persisted? - json.discount do + json.discount do json.percent percent end @@ -41,15 +40,16 @@ def to_builder(*expand) end private + def publish_create - Houdini.event_publisher.announce(:event_discount_created, to_event('event_discount.created', :event, :nonprofit, :ticket_levels).attributes!) + Houdini.event_publisher.announce(:event_discount_created, to_event("event_discount.created", :event, :nonprofit, :ticket_levels).attributes!) end def publish_updated - Houdini.event_publisher.announce(:event_discount_updated, to_event('event_discount.updated', :event, :nonprofit, :ticket_levels).attributes!) + Houdini.event_publisher.announce(:event_discount_updated, to_event("event_discount.updated", :event, :nonprofit, :ticket_levels).attributes!) end def publish_delete - Houdini.event_publisher.announce(:event_discount_deleted, to_event('event_discount.deleted', :event, :nonprofit, :ticket_levels).attributes!) + Houdini.event_publisher.announce(:event_discount_deleted, to_event("event_discount.deleted", :event, :nonprofit, :ticket_levels).attributes!) end end diff --git a/app/models/export.rb b/app/models/export.rb index cf7b59d5e3..cf91107578 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -13,7 +13,7 @@ class Export < ApplicationRecord # :url, # :user_id, # :nonprofit_id - + STATUS = %w[queued started completed failed].freeze belongs_to :nonprofit diff --git a/app/models/image_attachment.rb b/app/models/image_attachment.rb index a027a4700f..f10022d3de 100644 --- a/app/models/image_attachment.rb +++ b/app/models/image_attachment.rb @@ -8,7 +8,7 @@ class ImageAttachment < ApplicationRecord # :file has_one_attached :file - has_one_attached_with_sizes :file, {large: [600, 400], medium: [400, 266], small: [400,266], thumb_explore: [200,133]} + has_one_attached_with_sizes :file, {large: [600, 400], medium: [400, 266], small: [400, 266], thumb_explore: [200, 133]} # not sure if poly parent is used on this model, as all values are nil in db belongs_to :parent, polymorphic: true diff --git a/app/models/import_request.rb b/app/models/import_request.rb index a330dde75b..0afc25e763 100644 --- a/app/models/import_request.rb +++ b/app/models/import_request.rb @@ -3,148 +3,146 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class ImportRequest < ApplicationRecord - belongs_to :nonprofit - has_one_attached :import_file - - def execute_safe(user) - begin - ImportRequest.transaction do - execute(user) - end - rescue Exception => e - body = "Import failed. Error: #{e}" - GenericMailer.generic_mail( - Houdini.hoster.support_email, Houdini.hoster.support_email, # FROM - body, - 'Import error', # SUBJECT - Houdini.hoster.support_email, Houdini.hoster.support_email # TO - ).deliver - end - end - - def execute(user) - import = Import.create(date:Time.current, nonprofit:nonprofit, user: user) - - row_count = 0 + belongs_to :nonprofit + has_one_attached :import_file + + def execute_safe(user) + ImportRequest.transaction do + execute(user) + end + rescue Exception => e + body = "Import failed. Error: #{e}" + GenericMailer.generic_mail( + Houdini.hoster.support_email, Houdini.hoster.support_email, # FROM + body, + "Import error", # SUBJECT + Houdini.hoster.support_email, Houdini.hoster.support_email # TO + ).deliver + end + + def execute(user) + import = Import.create(date: Time.current, nonprofit: nonprofit, user: user) + + row_count = 0 imported_count = 0 supporter_ids = [] created_payment_ids = [] - import_file_blob.open do |file| - CSV.new(file, headers: :first_row).each do |row| - row_count += 1 - # triplet of [header_name, value, import_key] - matches = row.map { |key, val| [key, val, header_matches[key]] } - next if matches.empty? - - table_data = matches.each_with_object({}) do |triplet, acc| - key, val, match = triplet - if match == 'custom_field' - acc['custom_fields'] ||= [] - acc['custom_fields'].push([key, val]) - elsif match == 'tag' - acc['tags'] ||= [] - acc['tags'].push(val) - else - table, col = match.split('.') if match.present? - if table.present? && col.present? - acc[table] ||= {} - acc[table][col] = val - end - end - end - - # Create supporter record - if table_data['supporter'] - table_data['supporter'] = InsertSupporter.defaults(table_data['supporter']) - table_data['supporter']['imported_at'] = Time.current - table_data['supporter']['import_id'] = import['id'] - table_data['supporter']['nonprofit_id'] = nonprofit.id - table_data['supporter'] = Qx.insert_into(:supporters).values(table_data['supporter']).ts.returning('*').execute.first - supporter_ids.push(table_data['supporter']['id']) - imported_count += 1 - else - table_data['supporter'] = {} - end - - # Create custom fields - if table_data['supporter']['id'] && table_data['custom_fields'] && table_data['custom_fields'].any? - InsertCustomFieldJoins.find_or_create(nonprofit.id, [table_data['supporter']['id']], table_data['custom_fields']) - end - - # Create new tags - if table_data['supporter']['id'] && table_data['tags'] && table_data['tags'].any? - # Split tags by semicolons - tags = table_data['tags'].select(&:present?).map { |t| t.split(/[;,]/).map(&:strip) }.flatten - InsertTagJoins.find_or_create(nonprofit.id, [table_data['supporter']['id']], tags) - end - - # Create donation record - if table_data['donation'] && table_data['donation']['amount'] # must have amount. donation.date without donation.amount is no good - table_data['donation']['amount'] = (table_data['donation']['amount'].gsub(/[^\d\.]/, '').to_f * 100).to_i - table_data['donation']['supporter_id'] = table_data['supporter']['id'] - table_data['donation']['nonprofit_id'] = nonprofit.id - table_data['donation']['date'] = Chronic.parse(table_data['donation']['date']) if table_data['donation']['date'].present? - table_data['donation']['date'] ||= Time.current - table_data['donation'] = Qx.insert_into(:donations).values(table_data['donation']).ts.returning('*').execute.first - imported_count += 1 - else - table_data['donation'] = {} - end - - # Create payment record - if table_data['donation'] && table_data['donation']['id'] - table_data['payment'] = Qx.insert_into(:payments).values( - gross_amount: table_data['donation']['amount'], - fee_total: 0, - net_amount: table_data['donation']['amount'], - kind: 'OffsitePayment', - nonprofit_id: nonprofit.id, - supporter_id: table_data['supporter']['id'], - donation_id: table_data['donation']['id'], - towards: table_data['donation']['designation'], - date: table_data['donation']['date'] - ).ts.returning('*') - .execute.first - imported_count += 1 - else - table_data['payment'] = {} - end - - # Create offsite payment record - if table_data['donation'] && table_data['donation']['id'] - table_data['offsite_payment'] = Qx.insert_into(:offsite_payments).values( - gross_amount: table_data['donation']['amount'], - check_number: table_data['offsite_payment'] && table_data['offsite_payment']['check_number'], - kind: table_data['offsite_payment'] && table_data['offsite_payment']['check_number'] ? 'check' : '', - nonprofit_id: nonprofit.id, - supporter_id: table_data['supporter']['id'], - donation_id: table_data['donation']['id'], - payment_id: table_data['payment']['id'], - date: table_data['donation']['date'] - ).ts.returning('*') - .execute.first - imported_count += 1 - else - table_data['offsite_payment'] = {} - end - - created_payment_ids.push(table_data['payment']['id']) if table_data['payment'] && table_data['payment']['id'] - end - end + import_file_blob.open do |file| + CSV.new(file, headers: :first_row).each do |row| + row_count += 1 + # triplet of [header_name, value, import_key] + matches = row.map { |key, val| [key, val, header_matches[key]] } + next if matches.empty? + + table_data = matches.each_with_object({}) do |triplet, acc| + key, val, match = triplet + if match == "custom_field" + acc["custom_fields"] ||= [] + acc["custom_fields"].push([key, val]) + elsif match == "tag" + acc["tags"] ||= [] + acc["tags"].push(val) + else + table, col = match.split(".") if match.present? + if table.present? && col.present? + acc[table] ||= {} + acc[table][col] = val + end + end + end + + # Create supporter record + if table_data["supporter"] + table_data["supporter"] = InsertSupporter.defaults(table_data["supporter"]) + table_data["supporter"]["imported_at"] = Time.current + table_data["supporter"]["import_id"] = import["id"] + table_data["supporter"]["nonprofit_id"] = nonprofit.id + table_data["supporter"] = Qx.insert_into(:supporters).values(table_data["supporter"]).ts.returning("*").execute.first + supporter_ids.push(table_data["supporter"]["id"]) + imported_count += 1 + else + table_data["supporter"] = {} + end + + # Create custom fields + if table_data["supporter"]["id"] && table_data["custom_fields"] && table_data["custom_fields"].any? + InsertCustomFieldJoins.find_or_create(nonprofit.id, [table_data["supporter"]["id"]], table_data["custom_fields"]) + end + + # Create new tags + if table_data["supporter"]["id"] && table_data["tags"] && table_data["tags"].any? + # Split tags by semicolons + tags = table_data["tags"].select(&:present?).map { |t| t.split(/[;,]/).map(&:strip) }.flatten + InsertTagJoins.find_or_create(nonprofit.id, [table_data["supporter"]["id"]], tags) + end + + # Create donation record + if table_data["donation"] && table_data["donation"]["amount"] # must have amount. donation.date without donation.amount is no good + table_data["donation"]["amount"] = (table_data["donation"]["amount"].gsub(/[^\d\.]/, "").to_f * 100).to_i + table_data["donation"]["supporter_id"] = table_data["supporter"]["id"] + table_data["donation"]["nonprofit_id"] = nonprofit.id + table_data["donation"]["date"] = Chronic.parse(table_data["donation"]["date"]) if table_data["donation"]["date"].present? + table_data["donation"]["date"] ||= Time.current + table_data["donation"] = Qx.insert_into(:donations).values(table_data["donation"]).ts.returning("*").execute.first + imported_count += 1 + else + table_data["donation"] = {} + end + + # Create payment record + if table_data["donation"] && table_data["donation"]["id"] + table_data["payment"] = Qx.insert_into(:payments).values( + gross_amount: table_data["donation"]["amount"], + fee_total: 0, + net_amount: table_data["donation"]["amount"], + kind: "OffsitePayment", + nonprofit_id: nonprofit.id, + supporter_id: table_data["supporter"]["id"], + donation_id: table_data["donation"]["id"], + towards: table_data["donation"]["designation"], + date: table_data["donation"]["date"] + ).ts.returning("*") + .execute.first + imported_count += 1 + else + table_data["payment"] = {} + end + + # Create offsite payment record + if table_data["donation"] && table_data["donation"]["id"] + table_data["offsite_payment"] = Qx.insert_into(:offsite_payments).values( + gross_amount: table_data["donation"]["amount"], + check_number: table_data["offsite_payment"] && table_data["offsite_payment"]["check_number"], + kind: (table_data["offsite_payment"] && table_data["offsite_payment"]["check_number"]) ? "check" : "", + nonprofit_id: nonprofit.id, + supporter_id: table_data["supporter"]["id"], + donation_id: table_data["donation"]["id"], + payment_id: table_data["payment"]["id"], + date: table_data["donation"]["date"] + ).ts.returning("*") + .execute.first + imported_count += 1 + else + table_data["offsite_payment"] = {} + end + + created_payment_ids.push(table_data["payment"]["id"]) if table_data["payment"] && table_data["payment"]["id"] + end + end # Create donation activity records InsertActivities.for_offsite_donations(created_payment_ids) if created_payment_ids.count > 0 - import.row_count = row_count - import.imported_count = imported_count - import.save! - + import.row_count = row_count + import.imported_count = imported_count + import.save! + Supporter.where("supporters.id IN (?)", supporter_ids).each do |s| - Houdini.event_publisher.announce(:supporter_create, s) + Houdini.event_publisher.announce(:supporter_create, s) end - ImportCompletedJob.perform_later(import) - destroy + ImportCompletedJob.perform_later(import) + destroy import - end + end end diff --git a/app/models/modern_campaign_gift.rb b/app/models/modern_campaign_gift.rb index 4b2a590f3f..ae144beb8b 100644 --- a/app/models/modern_campaign_gift.rb +++ b/app/models/modern_campaign_gift.rb @@ -3,68 +3,68 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class ModernCampaignGift < ApplicationRecord - include Model::Houidable + include Model::Houidable include Model::Jbuilder include Model::Eventable - setup_houid :cgift + setup_houid :cgift - belongs_to :campaign_gift_purchase - belongs_to :legacy_campaign_gift, class_name: 'CampaignGift', foreign_key: :campaign_gift_id, inverse_of: :modern_campaign_gift + belongs_to :campaign_gift_purchase + belongs_to :legacy_campaign_gift, class_name: "CampaignGift", foreign_key: :campaign_gift_id, inverse_of: :modern_campaign_gift - has_one :campaign_gift_option, through: :legacy_campaign_gift - has_one :trx, through: :campaign_gift_purchase - has_one :supporter, through: :campaign_gift_purchase - has_one :nonprofit, through: :campaign_gift_purchase - has_one :campaign, through: :campaign_gift_purchase + has_one :campaign_gift_option, through: :legacy_campaign_gift + has_one :trx, through: :campaign_gift_purchase + has_one :supporter, through: :campaign_gift_purchase + has_one :nonprofit, through: :campaign_gift_purchase + has_one :campaign, through: :campaign_gift_purchase - # TODO replace with Discard gem - define_model_callbacks :discard + # TODO replace with Discard gem + define_model_callbacks :discard - # after_discard :publish_deleted + # after_discard :publish_deleted - validates :amount, presence: true - validates :legacy_campaign_gift, presence: true - validates :campaign_gift_purchase, presence: true - - # TODO replace with discard gem + validates :amount, presence: true + validates :legacy_campaign_gift, presence: true + validates :campaign_gift_purchase, presence: true + + # TODO replace with discard gem def discard! run_callbacks(:discard) do self.deleted = true save! end - end - - def to_builder(*expand) - init_builder(*expand) do |json| - json.(self, :deleted) - json.object 'campaign_gift' - - json.add_builder_expansion :nonprofit, :supporter, :campaign, :campaign_gift_option - json.add_builder_expansion :trx, - json_attribute: :transaction + end + + def to_builder(*expand) + init_builder(*expand) do |json| + json.call(self, :deleted) + json.object "campaign_gift" - if (expand.include? :campaign_gift_purchase) - json.campaign_gift_purchase campaign_gift_purchase.to_builder - else - json.campaign_gift_purchase campaign_gift_purchase.id - end - - json.amount do + json.add_builder_expansion :nonprofit, :supporter, :campaign, :campaign_gift_option + json.add_builder_expansion :trx, + json_attribute: :transaction + + if expand.include? :campaign_gift_purchase + json.campaign_gift_purchase campaign_gift_purchase.to_builder + else + json.campaign_gift_purchase campaign_gift_purchase.id + end + + json.amount do json.cents amount json.currency nonprofit.currency end - end - end + end + end + + def publish_created + Houdini.event_publisher.announce(:campaign_gift_created, to_event("campaign_gift.created", :nonprofit, :supporter, :trx, :campaign, :campaign_gift_option, :campaign_gift_purchase).attributes!) + end - def publish_created - Houdini.event_publisher.announce(:campaign_gift_created, to_event('campaign_gift.created', :nonprofit, :supporter, :trx, :campaign, :campaign_gift_option, :campaign_gift_purchase).attributes!) - end - - def publish_updated - Houdini.event_publisher.announce(:campaign_gift_updated, to_event('campaign_gift.updated', :nonprofit, :supporter, :trx, :campaign, :campaign_gift_option, :campaign_gift_purchase).attributes!) - end + def publish_updated + Houdini.event_publisher.announce(:campaign_gift_updated, to_event("campaign_gift.updated", :nonprofit, :supporter, :trx, :campaign, :campaign_gift_option, :campaign_gift_purchase).attributes!) + end - def publish_deleted - Houdini.event_publisher.announce(:campaign_gift_deleted, to_event('campaign_gift.deleted', :nonprofit, :supporter, :trx, :campaign, :campaign_gift_option, :campaign_gift_purchase).attributes!) - end + def publish_deleted + Houdini.event_publisher.announce(:campaign_gift_deleted, to_event("campaign_gift.deleted", :nonprofit, :supporter, :trx, :campaign, :campaign_gift_option, :campaign_gift_purchase).attributes!) + end end diff --git a/app/models/modern_donation.rb b/app/models/modern_donation.rb index 3e184ad2fc..9298f9052d 100644 --- a/app/models/modern_donation.rb +++ b/app/models/modern_donation.rb @@ -6,54 +6,58 @@ class ModernDonation < ApplicationRecord include Model::TrxAssignable setup_houid :don - # TODO must associate with events and campaigns somehow - belongs_to :legacy_donation, class_name: 'Donation', foreign_key: :donation_id, inverse_of: :modern_donations - - delegate :designation, :dedication, to: :legacy_donation - - def to_id - ::Jbuilder.new do |json| - json.id id - json.object 'donation' - json.type 'trx_assignment' - end - end - - def to_builder(*expand) + # TODO must associate with events and campaigns somehow + belongs_to :legacy_donation, class_name: "Donation", foreign_key: :donation_id, inverse_of: :modern_donations + + delegate :designation, :dedication, to: :legacy_donation + + def to_id + ::Jbuilder.new do |json| + json.id id + json.object "donation" + json.type "trx_assignment" + end + end + + def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :designation) - json.object 'donation' - json.type 'trx_assignment' - - json.dedication do - json.type dedication['type'] - json.name dedication['name'] - contact = dedication['contact'] - json.contact do - json.email contact['email'] if contact['email'] - json.address contact['address'] if contact['address'] - json.phone contact['phone'] if contact['phone'] - end if contact - end if dedication - # TODO the line above is a hacky solution + json.call(self, :designation) + json.object "donation" + json.type "trx_assignment" + + if dedication + json.dedication do + json.type dedication["type"] + json.name dedication["name"] + contact = dedication["contact"] + if contact + json.contact do + json.email contact["email"] if contact["email"] + json.address contact["address"] if contact["address"] + json.phone contact["phone"] if contact["phone"] + end + end + end + end + # TODO the line above is a hacky solution json.amount do json.cents amount json.currency nonprofit.currency end - json.add_builder_expansion :nonprofit, :supporter - json.add_builder_expansion :trx, json_attribute: :transaction + json.add_builder_expansion :nonprofit, :supporter + json.add_builder_expansion :trx, json_attribute: :transaction end end def publish_created - Houdini.event_publisher.announce(:donation_created, to_event('donation.created', :nonprofit, :supporter, :trx).attributes!) - Houdini.event_publisher.announce(:trx_assignment_created, to_event('trx_assignment.created', :nonprofit, :supporter, :trx).attributes!) - end - - def publish_updated - Houdini.event_publisher.announce(:donation_updated, to_event('donation.updated', :nonprofit, :supporter, :trx).attributes!) - Houdini.event_publisher.announce(:trx_assignment_updated, to_event('trx_assignment.updated', :nonprofit, :supporter, :trx).attributes!) - end + Houdini.event_publisher.announce(:donation_created, to_event("donation.created", :nonprofit, :supporter, :trx).attributes!) + Houdini.event_publisher.announce(:trx_assignment_created, to_event("trx_assignment.created", :nonprofit, :supporter, :trx).attributes!) + end + + def publish_updated + Houdini.event_publisher.announce(:donation_updated, to_event("donation.updated", :nonprofit, :supporter, :trx).attributes!) + Houdini.event_publisher.announce(:trx_assignment_updated, to_event("trx_assignment.updated", :nonprofit, :supporter, :trx).attributes!) + end end diff --git a/app/models/nonprofit.rb b/app/models/nonprofit.rb index 5000cd8626..cac36c2283 100755 --- a/app/models/nonprofit.rb +++ b/app/models/nonprofit.rb @@ -4,7 +4,7 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Nonprofit < ApplicationRecord attr_accessor :register_np_only, :user_id, :user - Categories = ['Public Benefit', 'Human Services', 'Education', 'Civic Duty', 'Human Rights', 'Animals', 'Environment', 'Health', 'Arts, Culture, Humanities', 'International', 'Children', 'Religion', 'LGBTQ', "Women's Rights", 'Disaster Relief', 'Veterans'].freeze + Categories = ["Public Benefit", "Human Services", "Education", "Civic Duty", "Human Rights", "Animals", "Environment", "Health", "Arts, Culture, Humanities", "International", "Children", "Religion", "LGBTQ", "Women's Rights", "Disaster Relief", "Veterans"].freeze include Image::AttachmentExtensions @@ -72,9 +72,9 @@ def for_type(type) end end has_many :tickets, through: :events - has_many :roles, as: :host, dependent: :destroy + has_many :roles, as: :host, dependent: :destroy has_many :users, through: :roles - has_many :admins, -> { where('name = ?', :nonprofit_admin) }, through: :roles, class_name: 'User', autosave: true, source: :user do + has_many :admins, -> { where("name = ?", :nonprofit_admin) }, through: :roles, class_name: "User", autosave: true, source: :user do def build_admin(**kwargs) build(kwargs.merge({name: :nonprofit_admin})) end @@ -82,52 +82,50 @@ def build_admin(**kwargs) has_many :custom_field_definitions, dependent: :destroy has_many :tag_definitions, dependent: :destroy - has_many :activities, as: :host, dependent: :destroy + has_many :activities, as: :host, dependent: :destroy has_many :imports has_many :email_settings - has_one :bank_account, -> { where('COALESCE(deleted, false) = false') }, - dependent: :destroy + has_one :bank_account, -> { where("COALESCE(deleted, false) = false") }, + dependent: :destroy has_one :billing_subscription, dependent: :destroy has_one :billing_plan, through: :billing_subscription has_one :miscellaneous_np_info - + validates_associated :admins, on: :create validates :name, presence: true validates :city, presence: true validates :state_code, presence: true - validates_format_of :email, with: Email::Regex, allow_nil: true - validates_presence_of :slug - validates_uniqueness_of :slug, scope: %i[city_slug state_code_slug] - validates :website, url: { schemes: ['http', 'https'], public_suffix: true, no_local: true }, allow_nil: true - - validates_presence_of :user_id, on: :create, unless: -> {register_np_only} - validate :user_is_valid, on: :create, unless: -> {register_np_only} - validate :user_registerable_as_admin, on: :create, unless: -> {register_np_only} + validates :email, format: {with: Email::Regex, allow_nil: true} + validates :slug, presence: true + validates :slug, uniqueness: {scope: %i[city_slug state_code_slug]} + validates :website, url: {schemes: ["http", "https"], public_suffix: true, no_local: true}, allow_nil: true + + validates :user_id, presence: {on: :create, unless: -> { register_np_only }} + validate :user_is_valid, on: :create, unless: -> { register_np_only } + validate :user_registerable_as_admin, on: :create, unless: -> { register_np_only } validate :timezone_is_valid validate :state_is_valid scope :vetted, -> { where(vetted: true) } - scope :identity_verified, -> { where(verification_status: 'verified') } + scope :identity_verified, -> { where(verification_status: "verified") } scope :published, -> { where(published: true) } has_one_attached :main_image has_one_attached :background_image has_one_attached :logo - + # way too wordy has_one_attached_with_sizes(:logo, {small: 30, normal: 100, large: 180}) - has_one_attached_with_sizes(:background_image, {normal: [1000,600]}) + has_one_attached_with_sizes(:background_image, {normal: [1000, 600]}) has_one_attached_with_sizes(:main_image, {nonprofit_carousel: [590, 338], thumb: [188, 120], thumb_explore: [100, 100]}) - - has_one_attached_with_default(:logo, Houdini.defaults.image.profile, + has_one_attached_with_default(:logo, Houdini.defaults.image.profile, filename: "logo_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.profile).extname}") - has_one_attached_with_default(:background_image, Houdini.defaults.image.nonprofit, - filename: "background_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.nonprofit).extname}") - has_one_attached_with_default(:main_image, Houdini.defaults.image.profile, - filename: "main_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.profile).extname}") - + has_one_attached_with_default(:background_image, Houdini.defaults.image.nonprofit, + filename: "background_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.nonprofit).extname}") + has_one_attached_with_default(:main_image, Houdini.defaults.image.profile, + filename: "main_image_#{SecureRandom.uuid}#{Pathname.new(Houdini.defaults.image.profile).extname}") before_validation(on: :create) do set_slugs @@ -137,17 +135,17 @@ def build_admin(**kwargs) self end - after_create :build_admin_role, unless: -> {register_np_only} + after_create :build_admin_role, unless: -> { register_np_only } # Register (create) a nonprofit with an initial admin def self.register(user, params) np = create ConstructNonprofit.construct(user, params) - role = Role.create(user: user, name: 'nonprofit_admin', host: np) if np.valid? + Role.create(user: user, name: "nonprofit_admin", host: np) if np.valid? np end def nonprofit_personnel_emails - roles.nonprofit_personnel.joins(:user).pluck('users.email') + roles.nonprofit_personnel.joins(:user).pluck("users.email") end def total_recurring @@ -155,13 +153,13 @@ def total_recurring end def as_json(options = {}) - h = super(options) + h = super h[:url] = url h end def state_is_valid - errors.add(:state_code, 'must be a US two-letter state code') unless ISO3166::Country[:US].subdivisions.has_key? state_code&.upcase + errors.add(:state_code, "must be a US two-letter state code") unless ISO3166::Country[:US].subdivisions.has_key? state_code&.upcase end def url @@ -180,18 +178,16 @@ def set_slugs end self end - + def correct_nonunique_slug - begin - slug = SlugNonprofitNamingAlgorithm.new(self.state_code_slug, self.city_slug).create_copy_name(self.slug) - self.slug = slug - rescue UnableToCreateNameCopyError - errors.add(:slug, "could not be created.") - end + slug = SlugNonprofitNamingAlgorithm.new(state_code_slug, city_slug).create_copy_name(self.slug) + self.slug = slug + rescue UnableToCreateNameCopyError + errors.add(:slug, "could not be created.") end def set_user - if (user_id && User.where(id: user_id).any?) + if user_id && User.where(id: user_id).any? @user = User.find(user_id) end self @@ -202,12 +198,12 @@ def full_address end def total_raised - QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(id))['net_amount'] + QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(id))["net_amount"] end def can_make_payouts vetted && - verification_status == 'verified' && + verification_status == "verified" && bank_account && !bank_account.pending_verification end @@ -219,22 +215,23 @@ def currency_symbol concerning :JBuilder do include Model::Jbuilder - def to_builder(*expand) + def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :id, :name) + json.call(self, :id, :name) end end end -private - def build_admin_role - role = user.roles.build(host: self, name: 'nonprofit_admin') + private + + def build_admin_role + role = user.roles.build(host: self, name: "nonprofit_admin") role.save! end def add_billing_subscription billing_plan = BillingPlan.find(Houdini.default_bp) - b_sub = build_billing_subscription(billing_plan: billing_plan, status: 'active') + build_billing_subscription(billing_plan: billing_plan, status: "active") end def add_scheme_to_website @@ -244,10 +241,10 @@ def add_scheme_to_website host = uri && uri.host scheme = uri && uri.scheme - valid_scheme = host && scheme - valid_website = website && website.include?('.') + host && scheme + valid_website = website && website.include?(".") - self.website = 'http://' + website if scheme.blank? && valid_website + self.website = "http://" + website if scheme.blank? && valid_website rescue URI::InvalidURIError => e e end @@ -265,11 +262,7 @@ def user_is_valid def timezone_is_valid timezone.blank? or - ActiveSupport::TimeZone.all.map{ |t| t.tzinfo.name }.include?(timezone) or - errors.add(:timezone, 'is not a valid timezone') + ActiveSupport::TimeZone.all.map { |t| t.tzinfo.name }.include?(timezone) or + errors.add(:timezone, "is not a valid timezone") end end - - - - diff --git a/app/models/object_event_hook_config.rb b/app/models/object_event_hook_config.rb index a106f725bd..7050c8690f 100644 --- a/app/models/object_event_hook_config.rb +++ b/app/models/object_event_hook_config.rb @@ -3,7 +3,6 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class ObjectEventHookConfig < ApplicationRecord - # :webhook_service, #str, webhook service to be called # :configuration, #jsonb, configuration needed to connect to the webhook # :object_event_types, #jsonb, must be an array diff --git a/app/models/offline_transaction.rb b/app/models/offline_transaction.rb index 3813bf89d8..859e8c6083 100644 --- a/app/models/offline_transaction.rb +++ b/app/models/offline_transaction.rb @@ -4,73 +4,73 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # rubocop:disable Metrics/BlockLength, Metrics/AbcSize, Metrics/MethodLength class OfflineTransaction < ApplicationRecord - include Model::Subtransactable - delegate :created, to: :subtransaction + include Model::Subtransactable + delegate :created, to: :subtransaction - def amount_as_money - Amount.new(amount || 0, nonprofit.currency) - end + def amount_as_money + Amount.new(amount || 0, nonprofit.currency) + end - def net_amount - payments.sum(&:net_amount) - end + def net_amount + payments.sum(&:net_amount) + end - def net_amount_as_money - Amount.new(net_amount || 0, nonprofit.currency) - end + def net_amount_as_money + Amount.new(net_amount || 0, nonprofit.currency) + end - concerning :JBuilder do - included do - setup_houid :offlinetrx - end - def to_builder(*expand) - init_builder(*expand) do |json| - json.type 'subtransaction' - json.created created.to_i - json.initial_amount do - json.cents amount || 0 - json.currency nonprofit.currency - end + concerning :JBuilder do + included do + setup_houid :offlinetrx + end + def to_builder(*expand) + init_builder(*expand) do |json| + json.type "subtransaction" + json.created created.to_i + json.initial_amount do + json.cents amount || 0 + json.currency nonprofit.currency + end - json.net_amount do - json.cents net_amount - json.currency nonprofit.currency - end + json.net_amount do + json.cents net_amount + json.currency nonprofit.currency + end - if expand.include? :payments - json.payments payments do |py| - json.merge! py.to_builder.attributes! - end - else - json.payments payments do |py| - json.merge! py.to_id.attributes! - end - end + if expand.include? :payments + json.payments payments do |py| + json.merge! py.to_builder.attributes! + end + else + json.payments payments do |py| + json.merge! py.to_id.attributes! + end + end - json.add_builder_expansion :nonprofit, :supporter + json.add_builder_expansion :nonprofit, :supporter - json.add_builder_expansion( - :trx, - json_attribute: :transaction - ) - end - end + json.add_builder_expansion( + :trx, + json_attribute: :transaction + ) + end + end - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'offline_transaction' - json.type 'subtransaction' - end - end + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "offline_transaction" + json.type "subtransaction" + end + end - def publish_created - Houdini.event_publisher.announce( - :offline_transaction_created, - to_event('offline_transaction.created', :nonprofit, :trx, :supporter, - :payments).attributes! - ) - end - end + def publish_created + Houdini.event_publisher.announce( + :offline_transaction_created, + to_event("offline_transaction.created", :nonprofit, :trx, :supporter, + :payments).attributes! + ) + end + end end # rubocop:enable all diff --git a/app/models/offline_transaction_charge.rb b/app/models/offline_transaction_charge.rb index 1045224599..b3eebce439 100644 --- a/app/models/offline_transaction_charge.rb +++ b/app/models/offline_transaction_charge.rb @@ -5,90 +5,90 @@ # rubocop:disable Metrics/BlockLength, Metrics/AbcSize class OfflineTransactionCharge < ApplicationRecord - include Model::SubtransactionPaymentable - belongs_to :payment - - delegate :gross_amount, :net_amount, :fee_total, to: :payment - - def gross_amount_as_money - Amount.new(gross_amount || 0, currency) - end - - def net_amount_as_money - Amount.new(net_amount || 0, currency) - end - - def fee_total_as_money - Amount.new(fee_total || 0, currency) - end - - def created - payment.date - end - - delegate :currency, to: :nonprofit - - concerning :JBuilder do - included do - setup_houid :offtrxchrg - end - - def to_builder(*expand) - init_builder(*expand) do |json| - json.object 'offline_transaction_charge' - json.gross_amount do - json.cents gross_amount - json.currency currency - end - - json.net_amount do - json.cents net_amount - json.currency currency - end - - json.fee_total do - json.cents fee_total - json.currency currency - end - - json.created payment.date.to_i - - json.type 'payment' - - json.add_builder_expansion :nonprofit, :supporter, :subtransaction - - json.add_builder_expansion :trx, json_attribute: :transaction - end - end - - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'offline_transaction_charge' - json.type 'payment' - end - end - - def publish_created - Houdini.event_publisher.announce( - :offline_transaction_charge_created, - to_event('offline_transaction_charge.created', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_created, - to_event( - 'payment.created', - :nonprofit, - :trx, - :supporter, - :subtransaction - ).attributes! - ) - end - end + include Model::SubtransactionPaymentable + belongs_to :payment + + delegate :gross_amount, :net_amount, :fee_total, to: :payment + + def gross_amount_as_money + Amount.new(gross_amount || 0, currency) + end + + def net_amount_as_money + Amount.new(net_amount || 0, currency) + end + + def fee_total_as_money + Amount.new(fee_total || 0, currency) + end + + def created + payment.date + end + + delegate :currency, to: :nonprofit + + concerning :JBuilder do + included do + setup_houid :offtrxchrg + end + + def to_builder(*expand) + init_builder(*expand) do |json| + json.object "offline_transaction_charge" + json.gross_amount do + json.cents gross_amount + json.currency currency + end + + json.net_amount do + json.cents net_amount + json.currency currency + end + + json.fee_total do + json.cents fee_total + json.currency currency + end + + json.created payment.date.to_i + + json.type "payment" + + json.add_builder_expansion :nonprofit, :supporter, :subtransaction + + json.add_builder_expansion :trx, json_attribute: :transaction + end + end + + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "offline_transaction_charge" + json.type "payment" + end + end + + def publish_created + Houdini.event_publisher.announce( + :offline_transaction_charge_created, + to_event("offline_transaction_charge.created", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_created, + to_event( + "payment.created", + :nonprofit, + :trx, + :supporter, + :subtransaction + ).attributes! + ) + end + end end # rubocop:enable all diff --git a/app/models/offline_transaction_dispute.rb b/app/models/offline_transaction_dispute.rb index 4a510a73b3..6c0814383f 100644 --- a/app/models/offline_transaction_dispute.rb +++ b/app/models/offline_transaction_dispute.rb @@ -3,94 +3,94 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class OfflineTransactionDispute < ApplicationRecord - include Model::SubtransactionPaymentable - belongs_to :payment + include Model::SubtransactionPaymentable + belongs_to :payment - delegate :gross_amount, :net_amount, :fee_total, to: :payment + delegate :gross_amount, :net_amount, :fee_total, to: :payment - delegate :currency, to: :nonprofit + delegate :currency, to: :nonprofit - # rubocop:disable Metrics/BlockLength - concerning :JBuilder do - included do - setup_houid :offtrxdspt - end + # rubocop:disable Metrics/BlockLength + concerning :JBuilder do + included do + setup_houid :offtrxdspt + end - # rubocop:disable Metrics/AbcSize - def to_builder(*expand) - init_builder(*expand) do |json| - json.object 'offline_transaction_dispute' - json.gross_amount do - json.cents gross_amount - json.currency currency - end + # rubocop:disable Metrics/AbcSize + def to_builder(*expand) + init_builder(*expand) do |json| + json.object "offline_transaction_dispute" + json.gross_amount do + json.cents gross_amount + json.currency currency + end - json.net_amount do - json.cents net_amount - json.currency currency - end + json.net_amount do + json.cents net_amount + json.currency currency + end - json.fee_total do - json.cents fee_total - json.currency currency - end + json.fee_total do + json.cents fee_total + json.currency currency + end - json.created payment.date.to_i - json.type 'payment' - json.add_builder_expansion :nonprofit, :supporter, :subtransaction - json.add_builder_expansion :trx, json_attribute: :transaction - end - end - # rubocop:enable Metrics/AbcSize + json.created payment.date.to_i + json.type "payment" + json.add_builder_expansion :nonprofit, :supporter, :subtransaction + json.add_builder_expansion :trx, json_attribute: :transaction + end + end + # rubocop:enable Metrics/AbcSize - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'offline_transaction_dispute' - json.type 'payment' - end - end + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "offline_transaction_dispute" + json.type "payment" + end + end - def publish_created - Houdini.event_publisher.announce( - :offline_transaction_dispute_created, - to_event('offline_transaction_dispute.created', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_created, - to_event('payment.created', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - end + def publish_created + Houdini.event_publisher.announce( + :offline_transaction_dispute_created, + to_event("offline_transaction_dispute.created", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_created, + to_event("payment.created", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + end - def publish_updated - Houdini.event_publisher.announce( - :offline_transaction_dispute_updated, - to_event('offline_transaction_dispute.updated', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_updated, - to_event('payment.updated', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - end + def publish_updated + Houdini.event_publisher.announce( + :offline_transaction_dispute_updated, + to_event("offline_transaction_dispute.updated", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_updated, + to_event("payment.updated", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + end - def publish_deleted - Houdini.event_publisher.announce( - :offline_transaction_dispute_deleted, - to_event('offline_transaction_dispute.deleted', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_deleted, - to_event('payment.deleted', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - end - end - # rubocop:enable Metrics/BlockLength + def publish_deleted + Houdini.event_publisher.announce( + :offline_transaction_dispute_deleted, + to_event("offline_transaction_dispute.deleted", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_deleted, + to_event("payment.deleted", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + end + end + # rubocop:enable Metrics/BlockLength end diff --git a/app/models/offline_transaction_refund.rb b/app/models/offline_transaction_refund.rb index 7228f709d2..31d3e4bbfd 100644 --- a/app/models/offline_transaction_refund.rb +++ b/app/models/offline_transaction_refund.rb @@ -3,110 +3,110 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class OfflineTransactionRefund < ApplicationRecord - include Model::SubtransactionPaymentable - belongs_to :payment - - delegate :gross_amount, :net_amount, :fee_total, to: :payment - - delegate :currency, to: :nonprofit - - def gross_amount_as_money - Amount.new(gross_amount || 0, currency) - end - - def net_amount_as_money - Amount.new(net_amount || 0, currency) - end - - def fee_total_as_money - Amount.new(fee_total || 0, currency) - end - - def created - payment.date - end - - # rubocop:disable Metrics/BlockLength - concerning :JBuilder do - included do - setup_houid :offtrxrfnd - end - - # rubocop:disable Metrics/AbcSize - def to_builder(*expand) - init_builder(*expand) do |json| - json.object 'offline_transaction_refund' - json.gross_amount do - json.cents gross_amount - json.currency currency - end - - json.net_amount do - json.cents net_amount - json.currency currency - end - - json.fee_total do - json.cents fee_total - json.currency currency - end - - json.created payment.date.to_i - json.type 'payment' - json.add_builder_expansion :nonprofit, :supporter, :subtransaction - json.add_builder_expansion :trx, json_attribute: :transaction - end - end - # rubocop:enable Metrics/AbcSize - - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'offline_transaction_refund' - json.type 'payment' - end - end - - def publish_created - Houdini.event_publisher.announce( - :offline_transaction_refund_created, - to_event('offline_transaction_refund.created', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_created, - to_event('payment.created', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - end - - def publish_updated - Houdini.event_publisher.announce( - :offline_transaction_refund_updated, - to_event('offline_transaction_refund.updated', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_updated, - to_event('payment.updated', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - end - - def publish_deleted - Houdini.event_publisher.announce( - :offline_transaction_refund_deleted, - to_event('offline_transaction_refund.deleted', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_deleted, - to_event('payment.deleted', :nonprofit, :trx, :supporter, :subtransaction).attributes! - ) - end - end - # rubocop:enable Metrics/BlockLength + include Model::SubtransactionPaymentable + belongs_to :payment + + delegate :gross_amount, :net_amount, :fee_total, to: :payment + + delegate :currency, to: :nonprofit + + def gross_amount_as_money + Amount.new(gross_amount || 0, currency) + end + + def net_amount_as_money + Amount.new(net_amount || 0, currency) + end + + def fee_total_as_money + Amount.new(fee_total || 0, currency) + end + + def created + payment.date + end + + # rubocop:disable Metrics/BlockLength + concerning :JBuilder do + included do + setup_houid :offtrxrfnd + end + + # rubocop:disable Metrics/AbcSize + def to_builder(*expand) + init_builder(*expand) do |json| + json.object "offline_transaction_refund" + json.gross_amount do + json.cents gross_amount + json.currency currency + end + + json.net_amount do + json.cents net_amount + json.currency currency + end + + json.fee_total do + json.cents fee_total + json.currency currency + end + + json.created payment.date.to_i + json.type "payment" + json.add_builder_expansion :nonprofit, :supporter, :subtransaction + json.add_builder_expansion :trx, json_attribute: :transaction + end + end + # rubocop:enable Metrics/AbcSize + + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "offline_transaction_refund" + json.type "payment" + end + end + + def publish_created + Houdini.event_publisher.announce( + :offline_transaction_refund_created, + to_event("offline_transaction_refund.created", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_created, + to_event("payment.created", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + end + + def publish_updated + Houdini.event_publisher.announce( + :offline_transaction_refund_updated, + to_event("offline_transaction_refund.updated", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_updated, + to_event("payment.updated", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + end + + def publish_deleted + Houdini.event_publisher.announce( + :offline_transaction_refund_deleted, + to_event("offline_transaction_refund.deleted", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_deleted, + to_event("payment.deleted", :nonprofit, :trx, :supporter, :subtransaction).attributes! + ) + end + end + # rubocop:enable Metrics/BlockLength end diff --git a/app/models/offsite_payment.rb b/app/models/offsite_payment.rb index 4b16b08eba..255103de61 100644 --- a/app/models/offsite_payment.rb +++ b/app/models/offsite_payment.rb @@ -3,10 +3,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class OffsitePayment < ApplicationRecord -# :gross_amount, -# :kind, -# :date, -# :check_number + # :gross_amount, + # :kind, + # :date, + # :check_number belongs_to :payment, dependent: :destroy belongs_to :donation belongs_to :nonprofit diff --git a/app/models/payment.rb b/app/models/payment.rb index 7e8857fc6d..7e11cb4896 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -7,7 +7,6 @@ # If connected to an offsite_payment, this is money the nonprofit is recording for convenience. class Payment < ApplicationRecord - belongs_to :supporter belongs_to :nonprofit has_one :charge @@ -21,10 +20,8 @@ class Payment < ApplicationRecord has_many :payment_payouts has_many :charges - has_one :stripe_charge has_one :subtransaction, through: :subtransaction_payment has_one :trx, through: :subtransaction_payment - end diff --git a/app/models/payout.rb b/app/models/payout.rb index 267917c964..30fd922536 100644 --- a/app/models/payout.rb +++ b/app/models/payout.rb @@ -23,33 +23,33 @@ class Payout < ApplicationRecord # :nonprofit_id, :nonprofit belongs_to :nonprofit - has_one :bank_account, through: :nonprofit - has_many :payment_payouts - has_many :payments, through: :payment_payouts + has_one :bank_account, through: :nonprofit + has_many :payment_payouts + has_many :payments, through: :payment_payouts validates :stripe_transfer_id, presence: true, uniqueness: true validates :nonprofit, presence: true validates :bank_account, presence: true validates :email, presence: true - validates :net_amount, presence: true, numericality: { greater_than: 0 } - validate :nonprofit_must_be_vetted, on: :create - validate :nonprofit_must_have_identity_verified, on: :create - validate :bank_account_must_be_confirmed, on: :create + validates :net_amount, presence: true, numericality: {greater_than: 0} + validate :nonprofit_must_be_vetted, on: :create + validate :nonprofit_must_have_identity_verified, on: :create + validate :bank_account_must_be_confirmed, on: :create - scope :pending, -> { where(status: 'pending') } - scope :paid, -> { where(status: %w[paid succeeded]) } + scope :pending, -> { where(status: "pending") } + scope :paid, -> { where(status: %w[paid succeeded]) } def bank_account_must_be_confirmed if bank_account&.pending_verification - errors.add(:bank_account, 'must be confirmed via email') + errors.add(:bank_account, "must be confirmed via email") end end def nonprofit_must_have_identity_verified - errors.add(:nonprofit, 'must be verified') unless nonprofit && nonprofit.verification_status == 'verified' + errors.add(:nonprofit, "must be verified") unless nonprofit && nonprofit.verification_status == "verified" end def nonprofit_must_be_vetted - errors.add(:nonprofit, 'must be vetted') unless nonprofit&.vetted + errors.add(:nonprofit, "must be vetted") unless nonprofit&.vetted end end diff --git a/app/models/profile.rb b/app/models/profile.rb index 090ea1261e..63e5cfa9ca 100755 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -20,12 +20,12 @@ class Profile < ApplicationRecord # :city_state, # :user_id - validates :email, format: { with: Email::Regex }, allow_blank: true + validates :email, format: {with: Email::Regex}, allow_blank: true attr_accessor :email, :city_state has_one_attached :picture - has_one_attached_with_sizes(:picture, {normal: 150, medium:100, tiny: 50}) + has_one_attached_with_sizes(:picture, {normal: 150, medium: 100, tiny: 50}) belongs_to :user has_many :activities # Activities this profile has created @@ -48,19 +48,21 @@ class Profile < ApplicationRecord end def set_defaults - self.name ||= user.name if user - self.email ||= user.email if user - picture.attach(io: File.open(Houdini.defaults.image.profile), - filename: "profile-image.png") unless self.picture.attached? + self.name ||= user.name if user + self.email ||= user.email if user + unless picture.attached? + picture.attach(io: File.open(Houdini.defaults.image.profile), + filename: "profile-image.png") + end if self.name.blank? && first_name.present? && last_name.present? - self.name ||= first_name + ' ' + last_name + self.name ||= first_name + " " + last_name end end # Queries def recent_donations(npo_id) - donations.valid.order('created_at').where(nonprofit_id: npo_id).take(10) + donations.valid.order("created_at").where(nonprofit_id: npo_id).take(10) end # Attrs @@ -82,7 +84,7 @@ def full_name end def supporter_name - self.name.blank? ? 'A Supporter' : self.name + self.name.presence || "A Supporter" end def get_profile_picture(size = :normal) diff --git a/app/models/recurrence.rb b/app/models/recurrence.rb index d8ec2494fe..1e3812c931 100644 --- a/app/models/recurrence.rb +++ b/app/models/recurrence.rb @@ -3,149 +3,149 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Recurrence < ApplicationRecord # rubocop:disable Metrics/ClassLength - include Model::Houidable - include Model::Jbuilder - include Model::Eventable - - after_initialize :set_start_date_if_needed - - belongs_to :recurring_donation - belongs_to :supporter - - has_one :nonprofit, through: :supporter - - delegate :currency, to: :nonprofit - - delegate :designation, :dedication, to: :recurring_donation - - validates :recurrences, presence: true - - def trx_assignments - [{ - assignment_object: 'donation', - amount: amount || 0, - dedication: dedication, - designation: designation - }.with_indifferent_access] - end - - def recurrences - [ - { - interval: recurring_donation.interval, - type: from_recurring_time_unit_to_recurrence(recurring_donation.time_unit), - start: recurrence_start_date - } - ] - end - - def invoice_template - { - amount: amount || 0, - trx_assignments: trx_assignments, - supporter: supporter, - payment_method: { type: 'stripe' } - } - end - - concerning :JBuilder do # rubocop:disable Metrics/BlockLength - included do - setup_houid :recur - end - - def to_builder(*expand) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/CyclomaticComplexity - init_builder(*expand) do |json| # rubocop:disable Metrics/BlockLength - json.start_date start_date.to_i - - json.add_builder_expansion :nonprofit, :supporter - - json.recurrences recurrences do |rec| - json.(rec, :interval, :type) - json.start rec[:start].to_i - end - - json.invoice_template do # rubocop:disable Metrics/BlockLength - json.amount do - json.cents amount || 0 - json.currency currency - end - - json.supporter supporter.id - - json.payment_method do - json.type 'stripe' - end - - json.trx_assignments trx_assignments do |assign| - json.assignment_object assign[:assignment_object] - dedication = assign[:dedication] - - if dedication - json.dedication do - json.type dedication['type'] - json.name dedication['name'] - contact = dedication['contact'] - json.note dedication['note'] - if contact - json.contact do - json.email contact['email'] if contact['email'] - json.address contact['address'] if contact['address'] - json.phone contact['phone'] if contact['phone'] - end - end - end - end - - json.designation assign[:designation] - - json.amount do - json.cents assign[:amount] || 0 - json.currency currency - end - end - end - end - end - - def publish_created - Houdini.event_publisher.announce( - :recurrence_created, - to_event('recurrence.created', :nonprofit, :trx, :supporter).attributes! - ) - end - - def publish_updated - Houdini.event_publisher.announce( - :recurrence_updated, - to_event('recurrence.updated', :nonprofit, :trx, :supporter).attributes! - ) - end - end - - private - - def set_start_date_if_needed - self[:start_date] = Time.current unless self[:start_date] - end - - def from_recurring_time_unit_to_recurrence(time_unit) - { - 'month' => 'monthly', - 'year' => 'yearly' - }[time_unit] - end - - def recurrence_start_date # rubocop:disable Metrics/AbcSize - paydate = recurring_donation.paydate - paydate = if paydate.nil? - (1..28).cover?(start_date.day) ? start_date.day : 28 - else - paydate - end - if paydate < start_date.day - (start_date + 1.month).beginning_of_month + (paydate - 1).days - else - start_date.beginning_of_month + (paydate - 1).days - end - end + include Model::Houidable + include Model::Jbuilder + include Model::Eventable + + after_initialize :set_start_date_if_needed + + belongs_to :recurring_donation + belongs_to :supporter + + has_one :nonprofit, through: :supporter + + delegate :currency, to: :nonprofit + + delegate :designation, :dedication, to: :recurring_donation + + validates :recurrences, presence: true + + def trx_assignments + [{ + assignment_object: "donation", + amount: amount || 0, + dedication: dedication, + designation: designation + }.with_indifferent_access] + end + + def recurrences + [ + { + interval: recurring_donation.interval, + type: from_recurring_time_unit_to_recurrence(recurring_donation.time_unit), + start: recurrence_start_date + } + ] + end + + def invoice_template + { + amount: amount || 0, + trx_assignments: trx_assignments, + supporter: supporter, + payment_method: {type: "stripe"} + } + end + + concerning :JBuilder do # rubocop:disable Metrics/BlockLength + included do + setup_houid :recur + end + + def to_builder(*expand) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/CyclomaticComplexity + init_builder(*expand) do |json| # rubocop:disable Metrics/BlockLength + json.start_date start_date.to_i + + json.add_builder_expansion :nonprofit, :supporter + + json.recurrences recurrences do |rec| + json.call(rec, :interval, :type) + json.start rec[:start].to_i + end + + json.invoice_template do # rubocop:disable Metrics/BlockLength + json.amount do + json.cents amount || 0 + json.currency currency + end + + json.supporter supporter.id + + json.payment_method do + json.type "stripe" + end + + json.trx_assignments trx_assignments do |assign| + json.assignment_object assign[:assignment_object] + dedication = assign[:dedication] + + if dedication + json.dedication do + json.type dedication["type"] + json.name dedication["name"] + contact = dedication["contact"] + json.note dedication["note"] + if contact + json.contact do + json.email contact["email"] if contact["email"] + json.address contact["address"] if contact["address"] + json.phone contact["phone"] if contact["phone"] + end + end + end + end + + json.designation assign[:designation] + + json.amount do + json.cents assign[:amount] || 0 + json.currency currency + end + end + end + end + end + + def publish_created + Houdini.event_publisher.announce( + :recurrence_created, + to_event("recurrence.created", :nonprofit, :trx, :supporter).attributes! + ) + end + + def publish_updated + Houdini.event_publisher.announce( + :recurrence_updated, + to_event("recurrence.updated", :nonprofit, :trx, :supporter).attributes! + ) + end + end + + private + + def set_start_date_if_needed + self[:start_date] = Time.current unless self[:start_date] + end + + def from_recurring_time_unit_to_recurrence(time_unit) + { + "month" => "monthly", + "year" => "yearly" + }[time_unit] + end + + def recurrence_start_date # rubocop:disable Metrics/AbcSize + paydate = recurring_donation.paydate + paydate = if paydate.nil? + (1..28).cover?(start_date.day) ? start_date.day : 28 + else + paydate + end + if paydate < start_date.day + (start_date + 1.month).beginning_of_month + (paydate - 1).days + else + start_date.beginning_of_month + (paydate - 1).days + end + end end diff --git a/app/models/recurring_donation.rb b/app/models/recurring_donation.rb index 26164bc879..963f1638fd 100644 --- a/app/models/recurring_donation.rb +++ b/app/models/recurring_donation.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'timespan' +require "timespan" class RecurringDonation < ApplicationRecord # :amount, # int (cents) @@ -20,10 +20,10 @@ class RecurringDonation < ApplicationRecord # :nonprofit_id, :nonprofit, # :supporter_id #used because things are messed up in the datamodel - scope :active, -> { where(active: true) } + scope :active, -> { where(active: true) } scope :inactive, -> { where(active: [false, nil]) } - scope :monthly, -> { where(time_unit: 'month', interval: 1) } - scope :annual, -> { where(time_unit: 'year', interval: 1) } + scope :monthly, -> { where(time_unit: "month", interval: 1) } + scope :annual, -> { where(time_unit: "year", interval: 1) } belongs_to :donation belongs_to :nonprofit @@ -32,12 +32,12 @@ class RecurringDonation < ApplicationRecord has_one :supporter, through: :donation has_one :recurrence - validates :paydate, numericality: { less_than: 29 }, allow_blank: true + validates :paydate, numericality: {less_than: 29}, allow_blank: true validates :donation_id, presence: true validates :nonprofit_id, presence: true validates :start_date, presence: true - validates :interval, presence: true, numericality: { greater_than: 0 } - validates :time_unit, presence: true, inclusion: { in: Timespan::Units } + validates :interval, presence: true, numericality: {greater_than: 0} + validates :time_unit, presence: true, inclusion: {in: Timespan::Units} validates_associated :donation delegate :designation, :dedication, to: :donation @@ -51,6 +51,6 @@ def most_recent_paid_charge end def total_given - return charges.find_all(&:paid?).sum(&:amount) if charges + charges.find_all(&:paid?).sum(&:amount) if charges end end diff --git a/app/models/role.rb b/app/models/role.rb index 5a8f1942fa..1cfea1aba4 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -4,12 +4,12 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Role < ApplicationRecord Names = [ - 'super_admin', # global access - 'super_associate', # global access to everything except bank acct info - 'nonprofit_admin', # npo scoped access to everything - 'nonprofit_associate', # npo scoped access to everything except bank acct info - 'campaign_editor', # fundraising tools, without dashboard access - 'event_editor' # // + "super_admin", # global access + "super_associate", # global access to everything except bank acct info + "nonprofit_admin", # npo scoped access to everything + "nonprofit_associate", # npo scoped access to everything except bank acct info + "campaign_editor", # fundraising tools, without dashboard access + "event_editor" # // ].freeze # :name, @@ -27,15 +27,15 @@ class Role < ApplicationRecord scope :event_editors, -> { where(name: :event_editor) } validates :user, presence: true - validates :name, inclusion: { in: Names } + validates :name, inclusion: {in: Names} validates :host, presence: true, unless: %i[super_admin? super_associate?] def super_admin? - name == 'super_admin' + name == "super_admin" end def super_associate? - name == 'super_associate' + name == "super_associate" end def self.create_for_nonprofit(role_name, email, nonprofit) diff --git a/app/models/stripe_charge.rb b/app/models/stripe_charge.rb index 498a176452..8e723a140e 100644 --- a/app/models/stripe_charge.rb +++ b/app/models/stripe_charge.rb @@ -3,79 +3,79 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class StripeCharge < ApplicationRecord - include Model::SubtransactionPaymentable - belongs_to :payment + include Model::SubtransactionPaymentable + belongs_to :payment - delegate :gross_amount, :net_amount, :fee_total, to: :payment + delegate :gross_amount, :net_amount, :fee_total, to: :payment - delegate :currency, to: :nonprofit + delegate :currency, to: :nonprofit - def stripe_id - payment.charge.stripe_charge_id - end + def stripe_id + payment.charge.stripe_charge_id + end - concerning :JBuilder do # rubocop:disable Metrics/BlockLength - included do - setup_houid :stripechrg - end + concerning :JBuilder do # rubocop:disable Metrics/BlockLength + included do + setup_houid :stripechrg + end - def to_builder(*expand) # rubocop:disable Metrics/AbcSize - init_builder(*expand) do |json| - json.object 'stripe_transaction_charge' - json.gross_amount do - json.cents gross_amount - json.currency currency - end + def to_builder(*expand) # rubocop:disable Metrics/AbcSize + init_builder(*expand) do |json| + json.object "stripe_transaction_charge" + json.gross_amount do + json.cents gross_amount + json.currency currency + end - json.net_amount do - json.cents net_amount - json.currency currency - end + json.net_amount do + json.cents net_amount + json.currency currency + end - json.fee_total do - json.cents fee_total - json.currency currency - end + json.fee_total do + json.cents fee_total + json.currency currency + end - json.created payment.date.to_i + json.created payment.date.to_i - json.stripe_id stripe_id + json.stripe_id stripe_id - json.type 'payment' + json.type "payment" - json.add_builder_expansion :nonprofit, :supporter, :subtransaction + json.add_builder_expansion :nonprofit, :supporter, :subtransaction - json.add_builder_expansion :trx, json_attribute: :transaction - end - end + json.add_builder_expansion :trx, json_attribute: :transaction + end + end - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'stripe_transaction_charge' - json.type 'payment' - end - end + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "stripe_transaction_charge" + json.type "payment" + end + end - def publish_created - Houdini.event_publisher.announce( - :stripe_transaction_charge_created, - to_event('stripe_transaction_charge.created', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_created, - to_event( - 'payment.created', - :nonprofit, - :trx, - :supporter, - :subtransaction - ).attributes! - ) - end - end + def publish_created + Houdini.event_publisher.announce( + :stripe_transaction_charge_created, + to_event("stripe_transaction_charge.created", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_created, + to_event( + "payment.created", + :nonprofit, + :trx, + :supporter, + :subtransaction + ).attributes! + ) + end + end end diff --git a/app/models/stripe_dispute.rb b/app/models/stripe_dispute.rb index b6574beb2a..31ea503893 100644 --- a/app/models/stripe_dispute.rb +++ b/app/models/stripe_dispute.rb @@ -3,105 +3,105 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class StripeDispute < ApplicationRecord - include Model::SubtransactionPaymentable - belongs_to :payment - - delegate :gross_amount, :net_amount, :fee_total, to: :payment - - delegate :currency, to: :nonprofit - - def stripe_id - payment.dispute.stripe_dispute_id - end - - concerning :JBuilder do # rubocop:disable Metrics/BlockLength - included do - setup_houid :stripedisp - end - - def to_builder(*expand) # rubocop:disable Metrics/AbcSize - init_builder(*expand) do |json| - json.object 'stripe_transaction_dispute' - json.gross_amount do - json.cents gross_amount - json.currency currency - end - - json.net_amount do - json.cents net_amount - json.currency currency - end - - json.fee_total do - json.cents fee_total - json.currency currency - end - - json.created payment.date.to_i - - json.stripe_id stripe_id - - json.type 'payment' - - json.add_builder_expansion :nonprofit, :supporter, :subtransaction - - json.add_builder_expansion :trx, json_attribute: :transaction - end - end - - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'stripe_transaction_dispute' - json.type 'payment' - end - end - - def publish_created - Houdini.event_publisher.announce( - :stripe_transaction_dispute_created, - to_event('stripe_transaction_dispute.created', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - Houdini.event_publisher.announce( - :payment_created, - to_event('payment.created', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - end - - def publish_updated - Houdini.event_publisher.announce( - :stripe_transaction_dispute_updated, - to_event('stripe_transaction_dispute.updated', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - Houdini.event_publisher.announce( - :payment_updated, - to_event('payment.updated', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - end - - def publish_deleted - Houdini.event_publisher.announce( - :stripe_transaction_dispute_deleted, - to_event('stripe_transaction_dispute.deleted', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_deleted, - to_event( - 'payment.deleted', - :nonprofit, - :trx, - :supporter, - :subtransaction - ).attributes! - ) - end - end + include Model::SubtransactionPaymentable + belongs_to :payment + + delegate :gross_amount, :net_amount, :fee_total, to: :payment + + delegate :currency, to: :nonprofit + + def stripe_id + payment.dispute.stripe_dispute_id + end + + concerning :JBuilder do # rubocop:disable Metrics/BlockLength + included do + setup_houid :stripedisp + end + + def to_builder(*expand) # rubocop:disable Metrics/AbcSize + init_builder(*expand) do |json| + json.object "stripe_transaction_dispute" + json.gross_amount do + json.cents gross_amount + json.currency currency + end + + json.net_amount do + json.cents net_amount + json.currency currency + end + + json.fee_total do + json.cents fee_total + json.currency currency + end + + json.created payment.date.to_i + + json.stripe_id stripe_id + + json.type "payment" + + json.add_builder_expansion :nonprofit, :supporter, :subtransaction + + json.add_builder_expansion :trx, json_attribute: :transaction + end + end + + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "stripe_transaction_dispute" + json.type "payment" + end + end + + def publish_created + Houdini.event_publisher.announce( + :stripe_transaction_dispute_created, + to_event("stripe_transaction_dispute.created", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + Houdini.event_publisher.announce( + :payment_created, + to_event("payment.created", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + end + + def publish_updated + Houdini.event_publisher.announce( + :stripe_transaction_dispute_updated, + to_event("stripe_transaction_dispute.updated", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + Houdini.event_publisher.announce( + :payment_updated, + to_event("payment.updated", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + end + + def publish_deleted + Houdini.event_publisher.announce( + :stripe_transaction_dispute_deleted, + to_event("stripe_transaction_dispute.deleted", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_deleted, + to_event( + "payment.deleted", + :nonprofit, + :trx, + :supporter, + :subtransaction + ).attributes! + ) + end + end end diff --git a/app/models/stripe_refund.rb b/app/models/stripe_refund.rb index 0b2b331d38..f3b0275d0f 100644 --- a/app/models/stripe_refund.rb +++ b/app/models/stripe_refund.rb @@ -3,105 +3,105 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class StripeRefund < ApplicationRecord - include Model::SubtransactionPaymentable - belongs_to :payment - - delegate :gross_amount, :net_amount, :fee_total, to: :payment - - delegate :currency, to: :nonprofit - - def stripe_id - payment.refund.stripe_refund_id - end - - concerning :JBuilder do # rubocop:disable Metrics/BlockLength - included do - setup_houid :striperef - end - - def to_builder(*expand) # rubocop:disable Metrics/AbcSize - init_builder(*expand) do |json| - json.object 'stripe_transaction_refund' - json.gross_amount do - json.cents gross_amount - json.currency currency - end - - json.net_amount do - json.cents net_amount - json.currency currency - end - - json.fee_total do - json.cents fee_total - json.currency currency - end - - json.created payment.date.to_i - - json.stripe_id stripe_id - - json.type 'payment' - - json.add_builder_expansion :nonprofit, :supporter, :subtransaction - - json.add_builder_expansion :trx, json_attribute: :transaction - end - end - - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'stripe_transaction_refund' - json.type 'payment' - end - end - - def publish_created - Houdini.event_publisher.announce( - :stripe_transaction_refund_created, - to_event('stripe_transaction_refund.created', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - Houdini.event_publisher.announce( - :payment_created, - to_event('payment.created', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - end - - def publish_updated - Houdini.event_publisher.announce( - :stripe_transaction_refund_updated, - to_event('stripe_transaction_refund.updated', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - Houdini.event_publisher.announce( - :payment_updated, - to_event('payment.updated', :nonprofit, :trx, :supporter, :subtransaction) - .attributes! - ) - end - - def publish_deleted - Houdini.event_publisher.announce( - :stripe_transaction_refund_deleted, - to_event('stripe_transaction_refund.deleted', - :nonprofit, - :trx, - :supporter, - :subtransaction).attributes! - ) - Houdini.event_publisher.announce( - :payment_deleted, - to_event( - 'payment.deleted', - :nonprofit, - :trx, - :supporter, - :subtransaction - ).attributes! - ) - end - end + include Model::SubtransactionPaymentable + belongs_to :payment + + delegate :gross_amount, :net_amount, :fee_total, to: :payment + + delegate :currency, to: :nonprofit + + def stripe_id + payment.refund.stripe_refund_id + end + + concerning :JBuilder do # rubocop:disable Metrics/BlockLength + included do + setup_houid :striperef + end + + def to_builder(*expand) # rubocop:disable Metrics/AbcSize + init_builder(*expand) do |json| + json.object "stripe_transaction_refund" + json.gross_amount do + json.cents gross_amount + json.currency currency + end + + json.net_amount do + json.cents net_amount + json.currency currency + end + + json.fee_total do + json.cents fee_total + json.currency currency + end + + json.created payment.date.to_i + + json.stripe_id stripe_id + + json.type "payment" + + json.add_builder_expansion :nonprofit, :supporter, :subtransaction + + json.add_builder_expansion :trx, json_attribute: :transaction + end + end + + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "stripe_transaction_refund" + json.type "payment" + end + end + + def publish_created + Houdini.event_publisher.announce( + :stripe_transaction_refund_created, + to_event("stripe_transaction_refund.created", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + Houdini.event_publisher.announce( + :payment_created, + to_event("payment.created", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + end + + def publish_updated + Houdini.event_publisher.announce( + :stripe_transaction_refund_updated, + to_event("stripe_transaction_refund.updated", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + Houdini.event_publisher.announce( + :payment_updated, + to_event("payment.updated", :nonprofit, :trx, :supporter, :subtransaction) + .attributes! + ) + end + + def publish_deleted + Houdini.event_publisher.announce( + :stripe_transaction_refund_deleted, + to_event("stripe_transaction_refund.deleted", + :nonprofit, + :trx, + :supporter, + :subtransaction).attributes! + ) + Houdini.event_publisher.announce( + :payment_deleted, + to_event( + "payment.deleted", + :nonprofit, + :trx, + :supporter, + :subtransaction + ).attributes! + ) + end + end end diff --git a/app/models/stripe_transaction.rb b/app/models/stripe_transaction.rb index dfae1dce14..3adef00359 100644 --- a/app/models/stripe_transaction.rb +++ b/app/models/stripe_transaction.rb @@ -3,64 +3,64 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class StripeTransaction < ApplicationRecord - include Model::Subtransactable - delegate :created, to: :subtransaction + include Model::Subtransactable + delegate :created, to: :subtransaction - def net_amount - payments.sum(&:net_amount) - end + def net_amount + payments.sum(&:net_amount) + end - concerning :JBuilder do # rubocop:disable Metrics/BlockLength - included do - setup_houid :stripetrx - end - def to_builder(*expand) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - init_builder(*expand) do |json| - json.type 'subtransaction' - json.created created.to_i - json.initial_amount do - json.cents amount || 0 - json.currency nonprofit.currency - end + concerning :JBuilder do # rubocop:disable Metrics/BlockLength + included do + setup_houid :stripetrx + end + def to_builder(*expand) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength + init_builder(*expand) do |json| + json.type "subtransaction" + json.created created.to_i + json.initial_amount do + json.cents amount || 0 + json.currency nonprofit.currency + end - json.net_amount do - json.cents net_amount - json.currency nonprofit.currency - end + json.net_amount do + json.cents net_amount + json.currency nonprofit.currency + end - if expand.include? :payments - json.payments payments do |py| - json.merge! py.to_builder.attributes! - end - else - json.payments payments do |py| - json.merge! py.to_id.attributes! - end - end + if expand.include? :payments + json.payments payments do |py| + json.merge! py.to_builder.attributes! + end + else + json.payments payments do |py| + json.merge! py.to_id.attributes! + end + end - json.add_builder_expansion :nonprofit, :supporter + json.add_builder_expansion :nonprofit, :supporter - json.add_builder_expansion( - :trx, - json_attribute: :transaction - ) - end - end + json.add_builder_expansion( + :trx, + json_attribute: :transaction + ) + end + end - def to_id - ::Jbuilder.new do |json| - json.(self, :id) - json.object 'stripe_transaction' - json.type 'subtransaction' - end - end + def to_id + ::Jbuilder.new do |json| + json.call(self, :id) + json.object "stripe_transaction" + json.type "subtransaction" + end + end - def publish_created - Houdini.event_publisher.announce( - :stripe_transaction_created, - to_event('stripe_transaction.created', :nonprofit, :trx, :supporter, - :payments).attributes! - ) - end - end + def publish_created + Houdini.event_publisher.announce( + :stripe_transaction_created, + to_event("stripe_transaction.created", :nonprofit, :trx, :supporter, + :payments).attributes! + ) + end + end end diff --git a/app/models/subtransaction.rb b/app/models/subtransaction.rb index e0429ef285..ed0b48317d 100644 --- a/app/models/subtransaction.rb +++ b/app/models/subtransaction.rb @@ -3,24 +3,24 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Subtransaction < ApplicationRecord - include Model::CreatedTimeable + include Model::CreatedTimeable - concerning :JBuilder do - include Model::Houidable - included do - setup_houid :subtrx - end - end + concerning :JBuilder do + include Model::Houidable + included do + setup_houid :subtrx + end + end - belongs_to :trx, class_name: 'Transaction', foreign_key: 'transaction_id', inverse_of: :subtransaction - has_one :supporter, through: :trx - has_one :nonprofit, through: :trx + belongs_to :trx, class_name: "Transaction", foreign_key: "transaction_id", inverse_of: :subtransaction + has_one :supporter, through: :trx + has_one :nonprofit, through: :trx - has_many :payments, class_name: 'SubtransactionPayment' # rubocop:disable Rails/HasManyOrHasOneDependent + has_many :payments, class_name: "SubtransactionPayment" # rubocop:disable Rails/HasManyOrHasOneDependent - delegated_type :subtransactable, types: %w[OfflineTransaction StripeTransaction] + delegated_type :subtransactable, types: %w[OfflineTransaction StripeTransaction] - scope :with_subtransactables, -> { includes(:subtransactable) } + scope :with_subtransactables, -> { includes(:subtransactable) } - delegate :to_builder, :to_event, :to_id, :publish_created, :publish_updated, :publish_deleted, to: :subtransactable + delegate :to_builder, :to_event, :to_id, :publish_created, :publish_updated, :publish_deleted, to: :subtransactable end diff --git a/app/models/subtransaction_payment.rb b/app/models/subtransaction_payment.rb index e031bb1499..bda727d083 100644 --- a/app/models/subtransaction_payment.rb +++ b/app/models/subtransaction_payment.rb @@ -3,32 +3,32 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class SubtransactionPayment < ApplicationRecord - include Model::Houidable - include Model::CreatedTimeable + include Model::Houidable + include Model::CreatedTimeable - setup_houid :subtrxentity + setup_houid :subtrxentity - belongs_to :subtransaction - has_one :trx, class_name: 'Transaction', foreign_key: 'transaction_id', through: :subtransaction - has_one :supporter, through: :subtransaction - has_one :nonprofit, through: :subtransaction + belongs_to :subtransaction + has_one :trx, class_name: "Transaction", foreign_key: "transaction_id", through: :subtransaction + has_one :supporter, through: :subtransaction + has_one :nonprofit, through: :subtransaction - delegated_type :paymentable, types: %w[ - OfflineTransactionCharge - OfflineTransactionDispute - OfflineTransactionRefund - StripeCharge - StripeRefund - ] + delegated_type :paymentable, types: %w[ + OfflineTransactionCharge + OfflineTransactionDispute + OfflineTransactionRefund + StripeCharge + StripeRefund + ] - delegate :gross_amount, :fee_total, :net_amount, to: :paymentable + delegate :gross_amount, :fee_total, :net_amount, to: :paymentable - scope :with_entities, -> { includes(:paymentable) } + scope :with_entities, -> { includes(:paymentable) } - delegate :to_builder, - :to_event, - :to_id, - :publish_created, - :publish_updated, - :publish_deleted, to: :paymentable + delegate :to_builder, + :to_event, + :to_id, + :publish_created, + :publish_updated, + :publish_deleted, to: :paymentable end diff --git a/app/models/supporter.rb b/app/models/supporter.rb index 5b6a7497c5..eb91695d8c 100644 --- a/app/models/supporter.rb +++ b/app/models/supporter.rb @@ -32,7 +32,7 @@ class Supporter < ApplicationRecord belongs_to :profile belongs_to :nonprofit belongs_to :import - + has_many :payments has_many :offsite_payments has_many :charges @@ -48,14 +48,12 @@ class Supporter < ApplicationRecord has_many :custom_field_joins, dependent: :destroy has_many :custom_field_definitions, through: :custom_field_joins has_many :transactions - belongs_to :merged_into, class_name: 'Supporter', foreign_key: 'merged_into' - has_many :merged_from, class_name: 'Supporter', :foreign_key => "merged_into" + belongs_to :merged_into, class_name: "Supporter", foreign_key: "merged_into" + has_many :merged_from, class_name: "Supporter", foreign_key: "merged_into" validates :nonprofit, presence: true scope :not_deleted, -> { where(deleted: false) } - - # TODO replace with Discard gem define_model_callbacks :discard @@ -86,12 +84,12 @@ def as_json(options = {}) h end - concerning :Jbuilder do - included do + concerning :Jbuilder do + included do def to_builder(*expand) supporter_addresses = [self] init_builder(*expand) do |json| - json.(self, :name, :organization, :phone, :anonymous, :deleted) + json.call(self, :name, :organization, :phone, :anonymous, :deleted) json.add_builder_expansion :nonprofit, :merged_into if expand.include? :supporter_address json.supporter_addresses supporter_addresses do |i| @@ -105,8 +103,8 @@ def to_builder(*expand) def to_supporter_address_builder(*expand) init_builder(*expand) do |json| - json.(self, :address, :state_code, :city, :country, :zip_code, :deleted) - json.object 'supporter_address' + json.call(self, :address, :state_code, :city, :country, :zip_code, :deleted) + json.object "supporter_address" if expand.include? :supporter json.supporter to_builder else @@ -118,8 +116,6 @@ def to_supporter_address_builder(*expand) end end - - def full_address Format::Address.full_address(address, city, state_code) end @@ -129,7 +125,7 @@ def full_address ADDRESS_ATTRIBUTES = [:address, :city, :state_code, :zip_code, :country] def supporter_address_updated? - ADDRESS_ATTRIBUTES.any?{|attrib| saved_change_to_attribute?(attrib)} + ADDRESS_ATTRIBUTES.any? { |attrib| saved_change_to_attribute?(attrib) } end def nonsupporter_address_updated? @@ -137,37 +133,37 @@ def nonsupporter_address_updated? end def publish_create - Houdini.event_publisher.announce(:supporter_created, to_event('supporter.created', :supporter_address, :nonprofit).attributes!) - Houdini.event_publisher.announce(:supporter_address_created, to_event('supporter_address.created', :supporter, :nonprofit).attributes!) + Houdini.event_publisher.announce(:supporter_created, to_event("supporter.created", :supporter_address, :nonprofit).attributes!) + Houdini.event_publisher.announce(:supporter_address_created, to_event("supporter_address.created", :supporter, :nonprofit).attributes!) end def publish_updated if !deleted if nonsupporter_address_updated? - Houdini.event_publisher.announce(:supporter_updated, to_event('supporter.updated', :supporter_address, :nonprofit).attributes!) + Houdini.event_publisher.announce(:supporter_updated, to_event("supporter.updated", :supporter_address, :nonprofit).attributes!) end if supporter_address_updated? - Houdini.event_publisher.announce(:supporter_address_updated, to_event('supporter_address.updated', :supporter, :nonprofit).attributes!) + Houdini.event_publisher.announce(:supporter_address_updated, to_event("supporter_address.updated", :supporter, :nonprofit).attributes!) end end end def publish_deleted - Houdini.event_publisher.announce(:supporter_deleted, to_event('supporter.deleted', :supporter_address, :nonprofit, :merged_into).attributes!) - Houdini.event_publisher.announce(:supporter_address_deleted, to_event('supporter_address.deleted', :supporter, :nonprofit).attributes!) + Houdini.event_publisher.announce(:supporter_deleted, to_event("supporter.deleted", :supporter_address, :nonprofit, :merged_into).attributes!) + Houdini.event_publisher.announce(:supporter_address_deleted, to_event("supporter_address.deleted", :supporter, :nonprofit).attributes!) end # we do something custom here since Supporter and SupporterAddress are in the same model def to_event(event_type, *expand) ::Jbuilder.new do |event| - event.id "objevt_" + SecureRandom.alphanumeric(22) - event.object 'object_event' - event.type event_type - event.data do - event.object event_type.start_with?('supporter_address') ? to_supporter_address_builder(*expand) : to_builder(*expand) - end + event.id "objevt_" + SecureRandom.alphanumeric(22) + event.object "object_event" + event.type event_type + event.data do + event.object event_type.start_with?("supporter_address") ? to_supporter_address_builder(*expand) : to_builder(*expand) + end end end end -ActiveSupport.run_load_hooks(:houdini_supporter, Supporter) \ No newline at end of file +ActiveSupport.run_load_hooks(:houdini_supporter, Supporter) diff --git a/app/models/supporter_note.rb b/app/models/supporter_note.rb index 4d5a4230f7..1749a5c27a 100644 --- a/app/models/supporter_note.rb +++ b/app/models/supporter_note.rb @@ -14,7 +14,7 @@ class SupporterNote < ApplicationRecord has_many :activities, as: :attachment, dependent: :destroy belongs_to :user - validates :content, length: { minimum: 1 } + validates :content, length: {minimum: 1} validates :supporter_id, presence: true # TODO replace with Discard gem @@ -35,24 +35,25 @@ def discard! def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :deleted, :content) + json.call(self, :deleted, :content) json.add_builder_expansion :supporter, :nonprofit, :user end end private + def publish_created - Houdini.event_publisher.announce(:supporter_note_created, to_event('supporter_note.created', :supporter, :nonprofit, :user).attributes!) + Houdini.event_publisher.announce(:supporter_note_created, to_event("supporter_note.created", :supporter, :nonprofit, :user).attributes!) end def publish_updated if !deleted - Houdini.event_publisher.announce(:supporter_note_updated, to_event('supporter_note.updated', :supporter, :nonprofit, :user).attributes!) + Houdini.event_publisher.announce(:supporter_note_updated, to_event("supporter_note.updated", :supporter, :nonprofit, :user).attributes!) end end def publish_deleted - Houdini.event_publisher.announce(:supporter_note_deleted, to_event('supporter_note.deleted', :supporter, :nonprofit, :user).attributes!) + Houdini.event_publisher.announce(:supporter_note_deleted, to_event("supporter_note.deleted", :supporter, :nonprofit, :user).attributes!) end end diff --git a/app/models/tag_definition.rb b/app/models/tag_definition.rb index c7fed2dc03..12e88c5221 100644 --- a/app/models/tag_definition.rb +++ b/app/models/tag_definition.rb @@ -29,10 +29,9 @@ class TagDefinition < ApplicationRecord def no_dupes return self if nonprofit.nil? - errors.add(:base, 'Duplicate tag') if nonprofit.tag_definitions.not_deleted.where(name: name).any? + errors.add(:base, "Duplicate tag") if nonprofit.tag_definitions.not_deleted.where(name: name).any? end - # TODO replace with discard gem def discard! run_callbacks(:discard) do @@ -43,20 +42,20 @@ def discard! def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :name, :deleted) - json.object 'tag_definition' + json.call(self, :name, :deleted) + json.object "tag_definition" json.add_builder_expansion :nonprofit end end + private -private def publish_create - Houdini.event_publisher.announce(:tag_definition_created, to_event('tag_definition.created', :nonprofit).attributes!) + Houdini.event_publisher.announce(:tag_definition_created, to_event("tag_definition.created", :nonprofit).attributes!) end def publish_deleted - Houdini.event_publisher.announce(:tag_definition_deleted, to_event('tag_definition.deleted', :nonprofit).attributes!) + Houdini.event_publisher.announce(:tag_definition_deleted, to_event("tag_definition.deleted", :nonprofit).attributes!) end end diff --git a/app/models/tag_join.rb b/app/models/tag_join.rb index ff23265bd9..b71dacb90e 100644 --- a/app/models/tag_join.rb +++ b/app/models/tag_join.rb @@ -16,8 +16,8 @@ def name end def self.create_with_name(nonprofit, h) - tm = nonprofit.tag_definitions.find_by_name(h['name']) - tm = nonprofit.tag_definitions.create(name: h['name']) if tm.nil? - create tag_definition: tm, supporter_id: h['supporter_id'] + tm = nonprofit.tag_definitions.find_by_name(h["name"]) + tm = nonprofit.tag_definitions.create(name: h["name"]) if tm.nil? + create tag_definition: tm, supporter_id: h["supporter_id"] end end diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 53f2d688ef..4fc1322170 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -21,6 +21,6 @@ class Ticket < ApplicationRecord has_many :ticket_to_legacy_tickets def related_tickets - payment.tickets.where('id != ?', id) + payment.tickets.where.not(id: id) end end diff --git a/app/models/ticket_level.rb b/app/models/ticket_level.rb index 87457fb138..894e27853c 100644 --- a/app/models/ticket_level.rb +++ b/app/models/ticket_level.rb @@ -23,16 +23,16 @@ class TicketLevel < ApplicationRecord after_create :publish_create after_update :publish_updated - + attr_accessor :amount_dollars has_many :tickets belongs_to :event has_one :nonprofit, through: :event - + validates :name, presence: true validates :event_id, presence: true - + validate :amount_hasnt_changed_if_has_tickets, on: :update scope :not_deleted, -> { where(deleted: [false, nil]) } @@ -42,14 +42,13 @@ def event_discounts event.event_discounts end - before_validation do self.amount = Format::Currency.dollars_to_cents(amount_dollars) if amount_dollars.present? self.amount = 0 if amount.nil? end def amount_as_money - Amount.new(amount||0, nonprofit.currency) + Amount.new(amount || 0, nonprofit.currency) end # TODO replace with discard gem @@ -59,15 +58,15 @@ def discard! save! end end - + def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :name, :deleted, :order, :limit, :description) - json.amount do + json.call(self, :name, :deleted, :order, :limit, :description) + json.amount do json.cents amount_as_money.cents json.currency amount_as_money.currency end - json.available_to admin_only ? 'admins' : 'everyone' + json.available_to admin_only ? "admins" : "everyone" json.add_builder_expansion :nonprofit, :event @@ -76,19 +75,20 @@ def to_builder(*expand) end private + def publish_create - Houdini.event_publisher.announce(:ticket_level_created, to_event('ticket_level.created', :event, :nonprofit, :event_discounts).attributes!) + Houdini.event_publisher.announce(:ticket_level_created, to_event("ticket_level.created", :event, :nonprofit, :event_discounts).attributes!) end def publish_updated # we don't run update when we've really just discarded unless deleted - Houdini.event_publisher.announce(:ticket_level_updated, to_event('ticket_level.updated', :event, :nonprofit, :event_discounts).attributes!) + Houdini.event_publisher.announce(:ticket_level_updated, to_event("ticket_level.updated", :event, :nonprofit, :event_discounts).attributes!) end end def publish_delete - Houdini.event_publisher.announce(:ticket_level_deleted, to_event('ticket_level.deleted', :event, :nonprofit, :event_discounts).attributes!) + Houdini.event_publisher.announce(:ticket_level_deleted, to_event("ticket_level.deleted", :event, :nonprofit, :event_discounts).attributes!) end def amount_hasnt_changed_if_has_tickets diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index c2f29e6396..9efa3b7d01 100644 --- a/app/models/ticket_purchase.rb +++ b/app/models/ticket_purchase.rb @@ -10,26 +10,28 @@ class TicketPurchase < ApplicationRecord belongs_to :event_discount belongs_to :event - + has_many :ticket_to_legacy_tickets validates :event, presence: true - def to_id - ::Jbuilder.new do |json| - json.id id - json.object 'ticket_purchase' - json.type 'trx_assignment' - end - end + def to_id + ::Jbuilder.new do |json| + json.id id + json.object "ticket_purchase" + json.type "trx_assignment" + end + end def to_builder(*expand) init_builder(*expand) do |json| - json.type 'trx_assignment' - - json.original_discount do - json.percent original_discount - end if original_discount + json.type "trx_assignment" + + if original_discount + json.original_discount do + json.percent original_discount + end + end json.amount do json.cents amount @@ -37,18 +39,19 @@ def to_builder(*expand) end json.add_builder_expansion :event, :event_discount, :nonprofit, :supporter - json.add_builder_expansion :ticket_to_legacy_tickets, enum_type: :expandable, json_attribute: 'tickets' + json.add_builder_expansion :ticket_to_legacy_tickets, enum_type: :expandable, json_attribute: "tickets" json.add_builder_expansion :trx, json_attribute: :transaction end end def publish_created - Houdini.event_publisher.announce(:ticket_purchase_created, to_event('ticket_purchase.created', :event, :nonprofit, :supporter, :trx, :event_discount, :ticket_to_legacy_tickets).attributes!) - Houdini.event_publisher.announce(:trx_assignment_created, to_event('trx_assignment.created', :event, :nonprofit, :supporter, :trx, :event_discount, :ticket_to_legacy_tickets).attributes!) + Houdini.event_publisher.announce(:ticket_purchase_created, to_event("ticket_purchase.created", :event, :nonprofit, :supporter, :trx, :event_discount, :ticket_to_legacy_tickets).attributes!) + Houdini.event_publisher.announce(:trx_assignment_created, to_event("trx_assignment.created", :event, :nonprofit, :supporter, :trx, :event_discount, :ticket_to_legacy_tickets).attributes!) end private + def set_original_discount - original_discount = event_discount.nil? ? 0 : event_discount.percent + event_discount.nil? ? 0 : event_discount.percent end end diff --git a/app/models/ticket_to_legacy_ticket.rb b/app/models/ticket_to_legacy_ticket.rb index b7e80c8577..4d58b6370b 100644 --- a/app/models/ticket_to_legacy_ticket.rb +++ b/app/models/ticket_to_legacy_ticket.rb @@ -18,12 +18,12 @@ class TicketToLegacyTicket < ApplicationRecord delegate :original_discount, to: :ticket_purchase delegate :checked_in, :deleted, :note, to: :ticket - + setup_houid :tkt def to_builder(*expand) init_builder(*expand) do |json| - json.(self, :checked_in, :deleted, :note) + json.call(self, :checked_in, :deleted, :note) json.object "ticket" json.amount do @@ -32,7 +32,7 @@ def to_builder(*expand) end if original_discount - json.original_discount do + json.original_discount do json.percent original_discount end end @@ -42,7 +42,7 @@ def to_builder(*expand) end def publish_created - Houdini.event_publisher.announce(:ticket_created, to_event('ticket.created', + Houdini.event_publisher.announce(:ticket_created, to_event("ticket.created", :ticket_purchase, :ticket_level, :supporter, @@ -52,7 +52,7 @@ def publish_created end def publish_updated - Houdini.event_publisher.announce(:ticket_updated, to_event('ticket.updated', + Houdini.event_publisher.announce(:ticket_updated, to_event("ticket.updated", :ticket_purchase, :ticket_level, :supporter, @@ -62,7 +62,7 @@ def publish_updated end def publish_deleted - Houdini.event_publisher.announce(:ticket_deleted, to_event('ticket.deleted', + Houdini.event_publisher.announce(:ticket_deleted, to_event("ticket.deleted", :ticket_purchase, :ticket_level, :supporter, @@ -70,5 +70,4 @@ def publish_deleted :nonprofit, :event_discount).attributes!) end - end diff --git a/app/models/transaction.rb b/app/models/transaction.rb index b7cf6e63ee..206bb8f457 100644 --- a/app/models/transaction.rb +++ b/app/models/transaction.rb @@ -3,84 +3,83 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Transaction < ApplicationRecord - include Model::CreatedTimeable + include Model::CreatedTimeable - belongs_to :supporter - has_one :nonprofit, through: :supporter + belongs_to :supporter + has_one :nonprofit, through: :supporter - has_many :transaction_assignments, inverse_of: 'trx' + has_many :transaction_assignments, inverse_of: "trx" - has_many :donations, through: :transaction_assignments, source: :assignable, source_type: 'ModernDonation', inverse_of: 'trx' - has_many :ticket_purchases, through: :transaction_assignments, source: :assignable, source_type: 'TicketPurchase', inverse_of: 'trx' - has_many :campaign_gift_purchases, through: :transaction_assignments, source: :assignable, source_type: 'CampaignGiftPurchase', inverse_of: 'trx' + has_many :donations, through: :transaction_assignments, source: :assignable, source_type: "ModernDonation", inverse_of: "trx" + has_many :ticket_purchases, through: :transaction_assignments, source: :assignable, source_type: "TicketPurchase", inverse_of: "trx" + has_many :campaign_gift_purchases, through: :transaction_assignments, source: :assignable, source_type: "CampaignGiftPurchase", inverse_of: "trx" - has_one :subtransaction - has_many :payments, through: :subtransaction + has_one :subtransaction + has_many :payments, through: :subtransaction - validates :supporter, presence: true + validates :supporter, presence: true - def amount_as_money - Amount.new(amount||0, nonprofit.currency) + def amount_as_money + Amount.new(amount || 0, nonprofit.currency) end - concerning :JBuilder do - include Model::Houidable - include Model::Jbuilder - include Model::Eventable - - included do - setup_houid :trx - end - - def to_builder(*expand) - init_builder(*expand) do |json| - json.amount do - json.cents amount || 0 - json.currency nonprofit.currency - end - json.created created.to_i - - json.add_builder_expansion :nonprofit, :supporter, :subtransaction - json.add_builder_expansion :payments, enum_type: :expandable - json.add_builder_expansion :transaction_assignments, enum_type: :expandable - end - end - end - - concerning :ObjectEvents do - - include JBuilder - def publish_created - Houdini.event_publisher.announce(:transaction_created, - to_event('transaction.created', :nonprofit, :supporter, :payments, :transaction_assignments, :subtransaction).attributes!) - end - - def publish_updated - Houdini.event_publisher.announce(:transaction_updated, - to_event('transaction.updated', :nonprofit, :supporter, :payments, :transaction_assignments, :subtransaction).attributes!) - end - - def publish_refunded - Houdini.event_publisher.announce(:transaction_refunded, - to_event('transaction.refunded', :nonprofit, :supporter, :payments, :transaction_assignments, :subtransaction).attributes!) - end - - def publish_disputed - Houdini.event_publisher.announce(:transaction_disputed, - to_event('transaction.refunded', :nonprofit, :supporter, :payments, :transaction_assignments).attributes!) - end - - def publish_deleted - Houdini.event_publisher.announce(:transaction_deleted, - to_event('transaction.deleted', :nonprofit, :supporter, :payments, :transaction_assignments).attributes!) - end - end - - private - def set_created_if_needed - write_attribute(:created, Time.now) unless read_attribute(:created) - end -end + concerning :JBuilder do + include Model::Houidable + include Model::Jbuilder + include Model::Eventable + + included do + setup_houid :trx + end + + def to_builder(*expand) + init_builder(*expand) do |json| + json.amount do + json.cents amount || 0 + json.currency nonprofit.currency + end + json.created created.to_i + + json.add_builder_expansion :nonprofit, :supporter, :subtransaction + json.add_builder_expansion :payments, enum_type: :expandable + json.add_builder_expansion :transaction_assignments, enum_type: :expandable + end + end + end + + concerning :ObjectEvents do + include JBuilder + def publish_created + Houdini.event_publisher.announce(:transaction_created, + to_event("transaction.created", :nonprofit, :supporter, :payments, :transaction_assignments, :subtransaction).attributes!) + end + + def publish_updated + Houdini.event_publisher.announce(:transaction_updated, + to_event("transaction.updated", :nonprofit, :supporter, :payments, :transaction_assignments, :subtransaction).attributes!) + end + + def publish_refunded + Houdini.event_publisher.announce(:transaction_refunded, + to_event("transaction.refunded", :nonprofit, :supporter, :payments, :transaction_assignments, :subtransaction).attributes!) + end + + def publish_disputed + Houdini.event_publisher.announce(:transaction_disputed, + to_event("transaction.refunded", :nonprofit, :supporter, :payments, :transaction_assignments).attributes!) + end + + def publish_deleted + Houdini.event_publisher.announce(:transaction_deleted, + to_event("transaction.deleted", :nonprofit, :supporter, :payments, :transaction_assignments).attributes!) + end + end + private + + def set_created_if_needed + self[:created] = Time.now unless self[:created] + end +end ActiveSupport.run_load_hooks(:houdini_transaction, Transaction) diff --git a/app/models/transaction_assignment.rb b/app/models/transaction_assignment.rb index 78ab1f1fdf..cdc45bd567 100644 --- a/app/models/transaction_assignment.rb +++ b/app/models/transaction_assignment.rb @@ -6,16 +6,15 @@ class TransactionAssignment < ApplicationRecord include Model::Houidable setup_houid :trxassign - delegated_type :assignable, types: ['ModernDonation', 'CampaignGiftPurchase', 'TicketPurchase'] + delegated_type :assignable, types: ["ModernDonation", "CampaignGiftPurchase", "TicketPurchase"] delegate :to_id, - :to_builder, - :publish_created, - :publish_updated, - :publish_deleted, to: :assignable + :to_builder, + :publish_created, + :publish_updated, + :publish_deleted, to: :assignable - belongs_to :trx, class_name: 'Transaction', foreign_key: "transaction_id" + belongs_to :trx, class_name: "Transaction", foreign_key: "transaction_id" has_one :supporter, through: :trx has_one :nonprofit, through: :trx - end diff --git a/app/models/user.rb b/app/models/user.rb index 333f5b15e4..0ac8892447 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,13 +29,13 @@ class User < ApplicationRecord attr_accessor :offsite_donation_id, :current_password validates :email, - presence: true, - uniqueness: { case_sensitive: false }, - format: { with: Email::Regex } + presence: true, + uniqueness: {case_sensitive: false}, + format: {with: Email::Regex} has_many :donations, through: :profile - has_many :roles, dependent: :destroy - has_one :profile, dependent: :destroy + has_many :roles, dependent: :destroy + has_one :profile, dependent: :destroy has_many :imports has_many :email_settings @@ -61,10 +61,10 @@ def self.register_donor!(params) u = User.create!(params) u.send_confirmation_instructions u - end + end def self.find_or_create_with_email(em) - user = where('lower(email) = ?', em.downcase).first + user = where("lower(email) = ?", em.downcase).first return user if user.present? User.create!(email: em, auto_generated: true) @@ -78,8 +78,8 @@ def profile_picture(size) # https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview def self.new_with_session(params, session) super.tap do |user| - if data = session['devise.facebook_data'] && session['devise.facebook_data']['extra']['raw_info'] - user.email = data['email'] if user.email.blank? + if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] + user.email = data["email"] if user.email.blank? end end end diff --git a/app/views/api/campaign_gift_options/_campaign_gift_option.json.jbuilder b/app/views/api/campaign_gift_options/_campaign_gift_option.json.jbuilder index 4daadec36c..b45b2b22c0 100644 --- a/app/views/api/campaign_gift_options/_campaign_gift_option.json.jbuilder +++ b/app/views/api/campaign_gift_options/_campaign_gift_option.json.jbuilder @@ -2,28 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(campaign_gift_option, :id, :name, :description, :deleted, - :hide_contributions, :order, :to_ship, :quantity) +json.call(campaign_gift_option, :id, :name, :description, :deleted, :hide_contributions, :order, :to_ship, :quantity) -json.object 'campaign_gift_option' +json.object "campaign_gift_option" json.url api_nonprofit_campaign_campaign_gift_option_url( - campaign_gift_option.nonprofit, - campaign_gift_option.campaign, - campaign_gift_option + campaign_gift_option.nonprofit, + campaign_gift_option.campaign, + campaign_gift_option ) json.gift_option_amount campaign_gift_option.gift_option_amounts do |desc| - json.amount do - json.partial! '/api/common/amount', amount: desc.amount - end - if desc.recurrence.present? - json.recurrence do - json.(desc.recurrence, :type, :interval) - end - else - json.recurrence nil - end + json.amount do + json.partial! "/api/common/amount", amount: desc.amount + end + if desc.recurrence.present? + json.recurrence do + json.call(desc.recurrence, :type, :interval) + end + else + json.recurrence nil + end end json.nonprofit campaign_gift_option.nonprofit.id diff --git a/app/views/api/campaign_gift_options/index.json.jbuilder b/app/views/api/campaign_gift_options/index.json.jbuilder index 497957228d..565085d20c 100644 --- a/app/views/api/campaign_gift_options/index.json.jbuilder +++ b/app/views/api/campaign_gift_options/index.json.jbuilder @@ -3,9 +3,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE json.data( - @campaign_gift_options, - partial: '/api/campaign_gift_options/campaign_gift_option', - as: 'campaign_gift_option' + @campaign_gift_options, + partial: "/api/campaign_gift_options/campaign_gift_option", + as: "campaign_gift_option" ) json.current_page @campaign_gift_options.current_page diff --git a/app/views/api/campaigns/_campaign.json.jbuilder b/app/views/api/campaigns/_campaign.json.jbuilder index b6a9e5facc..9142b4d530 100644 --- a/app/views/api/campaigns/_campaign.json.jbuilder +++ b/app/views/api/campaigns/_campaign.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(campaign, :id, :name) +json.call(campaign, :id, :name) -json.object 'campaign' +json.object "campaign" json.url api_nonprofit_campaign_url(campaign.nonprofit, campaign) diff --git a/app/views/api/common/_amount.json.jbuilder b/app/views/api/common/_amount.json.jbuilder index 0420ea824a..1215c21467 100644 --- a/app/views/api/common/_amount.json.jbuilder +++ b/app/views/api/common/_amount.json.jbuilder @@ -3,4 +3,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(amount, :cents, :currency) +json.call(amount, :cents, :currency) diff --git a/app/views/api/custom_field_definitions/_custom_field_definition.json.jbuilder b/app/views/api/custom_field_definitions/_custom_field_definition.json.jbuilder index e38185cd16..392e9767b3 100644 --- a/app/views/api/custom_field_definitions/_custom_field_definition.json.jbuilder +++ b/app/views/api/custom_field_definitions/_custom_field_definition.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(custom_field_definition, :id, :name, :deleted) +json.call(custom_field_definition, :id, :name, :deleted) -json.object 'custom_field_definition' +json.object "custom_field_definition" json.url api_nonprofit_custom_field_definition_url(custom_field_definition.nonprofit, custom_field_definition) diff --git a/app/views/api/custom_field_definitions/index.json.jbuilder b/app/views/api/custom_field_definitions/index.json.jbuilder index c41d00f86f..f7ee59fbe9 100644 --- a/app/views/api/custom_field_definitions/index.json.jbuilder +++ b/app/views/api/custom_field_definitions/index.json.jbuilder @@ -3,9 +3,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data( - @custom_field_definitions, - partial: '/api/custom_field_definitions/custom_field_definition', - as: 'custom_field_definition' + @custom_field_definitions, + partial: "/api/custom_field_definitions/custom_field_definition", + as: "custom_field_definition" ) json.current_page @custom_field_definitions.current_page diff --git a/app/views/api/events/_event.json.jbuilder b/app/views/api/events/_event.json.jbuilder index 61712d241c..8c0b497a0d 100644 --- a/app/views/api/events/_event.json.jbuilder +++ b/app/views/api/events/_event.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(event, :id, :name) +json.call(event, :id, :name) -json.object 'event' +json.object "event" json.url api_nonprofit_event_url(event.nonprofit, event) diff --git a/app/views/api/nonprofits/_nonprofit.json.jbuilder b/app/views/api/nonprofits/_nonprofit.json.jbuilder index ddd4e2bb14..6b1934b587 100644 --- a/app/views/api/nonprofits/_nonprofit.json.jbuilder +++ b/app/views/api/nonprofits/_nonprofit.json.jbuilder @@ -2,6 +2,6 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(nonprofit, :id, :name) +json.call(nonprofit, :id, :name) -json.object 'nonprofit' +json.object "nonprofit" diff --git a/app/views/api/nonprofits/create.json.jbuilder b/app/views/api/nonprofits/create.json.jbuilder index 2a0f1a0d1a..d783ea0672 100644 --- a/app/views/api/nonprofits/create.json.jbuilder +++ b/app/views/api/nonprofits/create.json.jbuilder @@ -15,6 +15,6 @@ json.website @nonprofit.website json.phone @nonprofit.phone json.urls do - json.plain_url nonprofit_url(@nonprofit) - json.slug_url nonprofit_slug_url(@nonprofit) -end \ No newline at end of file + json.plain_url nonprofit_url(@nonprofit) + json.slug_url nonprofit_slug_url(@nonprofit) +end diff --git a/app/views/api/offline_transaction_charges/_offline_transaction_charge.json.jbuilder b/app/views/api/offline_transaction_charges/_offline_transaction_charge.json.jbuilder index 1c6c7c6f4c..07d902125b 100644 --- a/app/views/api/offline_transaction_charges/_offline_transaction_charge.json.jbuilder +++ b/app/views/api/offline_transaction_charges/_offline_transaction_charge.json.jbuilder @@ -3,18 +3,18 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.object 'offline_transaction_charge' +json.object "offline_transaction_charge" json.net_amount do - json.partial! '/api/common/amount', amount: paymentable.net_amount_as_money + json.partial! "/api/common/amount", amount: paymentable.net_amount_as_money end json.gross_amount do - json.partial! '/api/common/amount', amount: paymentable.gross_amount_as_money + json.partial! "/api/common/amount", amount: paymentable.gross_amount_as_money end json.fee_total do - json.partial! '/api/common/amount', amount: paymentable.fee_total_as_money + json.partial! "/api/common/amount", amount: paymentable.fee_total_as_money end json.created paymentable.created.to_i diff --git a/app/views/api/offline_transaction_refunds/_offline_transaction_refund.json.jbuilder b/app/views/api/offline_transaction_refunds/_offline_transaction_refund.json.jbuilder index 15fe2e5224..0cef6524f9 100644 --- a/app/views/api/offline_transaction_refunds/_offline_transaction_refund.json.jbuilder +++ b/app/views/api/offline_transaction_refunds/_offline_transaction_refund.json.jbuilder @@ -3,18 +3,18 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.object 'offline_transaction_refund' +json.object "offline_transaction_refund" json.net_amount do - json.partial! '/api/common/amount', amount: paymentable.net_amount_as_money + json.partial! "/api/common/amount", amount: paymentable.net_amount_as_money end json.gross_amount do - json.partial! '/api/common/amount', amount: paymentable.gross_amount_as_money + json.partial! "/api/common/amount", amount: paymentable.gross_amount_as_money end json.fee_total do - json.partial! '/api/common/amount', amount: paymentable.fee_total_as_money + json.partial! "/api/common/amount", amount: paymentable.fee_total_as_money end json.created paymentable.created.to_i diff --git a/app/views/api/offline_transactions/_offline_transaction.json.jbuilder b/app/views/api/offline_transactions/_offline_transaction.json.jbuilder index 961229537c..cd29b7b994 100644 --- a/app/views/api/offline_transactions/_offline_transaction.json.jbuilder +++ b/app/views/api/offline_transactions/_offline_transaction.json.jbuilder @@ -3,14 +3,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.object 'offline_transaction' +json.object "offline_transaction" json.created subtransactable.created.to_i json.amount do - json.partial! '/api/common/amount', amount: subtransactable.amount_as_money + json.partial! "/api/common/amount", amount: subtransactable.amount_as_money end json.net_amount do - json.partial! '/api/common/amount', amount: subtransactable.net_amount_as_money + json.partial! "/api/common/amount", amount: subtransactable.net_amount_as_money end diff --git a/app/views/api/payments/index.json.jbuilder b/app/views/api/payments/index.json.jbuilder index 916a2d24ea..a2c4654679 100644 --- a/app/views/api/payments/index.json.jbuilder +++ b/app/views/api/payments/index.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.data @payments, partial: '/api/subtransaction_payments/subtransaction_payment', as: :subtransaction_payment +json.data @payments, partial: "/api/subtransaction_payments/subtransaction_payment", as: :subtransaction_payment json.current_page @payments.current_page json.first_page @payments.first_page? diff --git a/app/views/api/roles/_role.json.jbuilder b/app/views/api/roles/_role.json.jbuilder index c98599df0d..8f1987ec07 100644 --- a/app/views/api/roles/_role.json.jbuilder +++ b/app/views/api/roles/_role.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(role, :id, :name) +json.call(role, :id, :name) json.user_id role.user.id json.host role.host_type -json.object 'role' +json.object "role" diff --git a/app/views/api/roles/index.json.jbuilder b/app/views/api/roles/index.json.jbuilder index 04e389d75d..9019e01a06 100644 --- a/app/views/api/roles/index.json.jbuilder +++ b/app/views/api/roles/index.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.data @roles, partial: '/api/roles/role', as: :role +json.data @roles, partial: "/api/roles/role", as: :role json.current_page @roles.current_page json.first_page @roles.first_page? diff --git a/app/views/api/subtransaction_payments/_subtransaction_payment.json.jbuilder b/app/views/api/subtransaction_payments/_subtransaction_payment.json.jbuilder index 6574435b35..0ae09d46e1 100644 --- a/app/views/api/subtransaction_payments/_subtransaction_payment.json.jbuilder +++ b/app/views/api/subtransaction_payments/_subtransaction_payment.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.type 'payment' +json.type "payment" json.id subtransaction_payment.paymentable.id @@ -11,12 +11,12 @@ json.nonprofit subtransaction_payment.nonprofit.id json.transaction subtransaction_payment.trx.id json.subtransaction do - json.merge! subtransaction_payment.subtransaction&.to_id + json.merge! subtransaction_payment.subtransaction&.to_id end json.partial! subtransaction_payment.paymentable, as: :paymentable json.url api_nonprofit_transaction_subtransaction_payment_url( - subtransaction_payment.nonprofit, - subtransaction_payment.trx, subtransaction_payment.paymentable + subtransaction_payment.nonprofit, + subtransaction_payment.trx, subtransaction_payment.paymentable ) diff --git a/app/views/api/subtransactions/_subtransaction.json.jbuilder b/app/views/api/subtransactions/_subtransaction.json.jbuilder index 5857bd2bac..540888ed3d 100644 --- a/app/views/api/subtransactions/_subtransaction.json.jbuilder +++ b/app/views/api/subtransactions/_subtransaction.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(subtransaction.subtransactable, :id) +json.call(subtransaction.subtransactable, :id) -json.type 'subtransaction' +json.type "subtransaction" json.supporter subtransaction.supporter.id json.nonprofit subtransaction.nonprofit.id json.transaction subtransaction.trx.id @@ -12,7 +12,7 @@ json.transaction subtransaction.trx.id json.partial! subtransaction.subtransactable, as: :subtransactable json.payments subtransaction.payments do |py| - json.partial! py, as: :subtransaction_payment + json.partial! py, as: :subtransaction_payment end json.url api_nonprofit_transaction_subtransaction_url(subtransaction.nonprofit, subtransaction.trx) diff --git a/app/views/api/supporter_addresses/_supporter_address.json.jbuilder b/app/views/api/supporter_addresses/_supporter_address.json.jbuilder index 8eeea014e2..e5b0b671a3 100644 --- a/app/views/api/supporter_addresses/_supporter_address.json.jbuilder +++ b/app/views/api/supporter_addresses/_supporter_address.json.jbuilder @@ -2,12 +2,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(supporter_address, :id, :address, :city, :state_code, :country, :zip_code, :deleted) +json.call(supporter_address, :id, :address, :city, :state_code, :country, :zip_code, :deleted) -json.object 'supporter_address' +json.object "supporter_address" json.url api_nonprofit_supporter_supporter_address_url(supporter_address.nonprofit, supporter_address, - supporter_address) + supporter_address) json.nonprofit supporter_address.nonprofit.id diff --git a/app/views/api/supporter_addresses/index.json.jbuilder b/app/views/api/supporter_addresses/index.json.jbuilder index 92e6f244e7..7bbb8087ec 100644 --- a/app/views/api/supporter_addresses/index.json.jbuilder +++ b/app/views/api/supporter_addresses/index.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.data @supporter_addresses, partial: '/api/supporter_addresses/supporter_address', as: 'supporter_address' +json.data @supporter_addresses, partial: "/api/supporter_addresses/supporter_address", as: "supporter_address" json.current_page @supporter_addresses.current_page json.first_page @supporter_addresses.first_page? diff --git a/app/views/api/supporter_addresses/show.json.jbuilder b/app/views/api/supporter_addresses/show.json.jbuilder index ced9656e63..3697648b84 100644 --- a/app/views/api/supporter_addresses/show.json.jbuilder +++ b/app/views/api/supporter_addresses/show.json.jbuilder @@ -2,4 +2,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.partial! '/api/supporter_addresses/supporter_address', supporter_address: @supporter_address +json.partial! "/api/supporter_addresses/supporter_address", supporter_address: @supporter_address diff --git a/app/views/api/supporter_notes/_supporter_note.json.jbuilder b/app/views/api/supporter_notes/_supporter_note.json.jbuilder index e2871f3cfa..277cd4475d 100644 --- a/app/views/api/supporter_notes/_supporter_note.json.jbuilder +++ b/app/views/api/supporter_notes/_supporter_note.json.jbuilder @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(supporter_note, :id, :content, :deleted) +json.call(supporter_note, :id, :content, :deleted) -json.object 'supporter_note' +json.object "supporter_note" json.url api_nonprofit_supporter_supporter_note_url( - supporter_note.nonprofit, - supporter_note.supporter, - supporter_note + supporter_note.nonprofit, + supporter_note.supporter, + supporter_note ) json.nonprofit supporter_note.nonprofit.id diff --git a/app/views/api/supporter_notes/index.json.jbuilder b/app/views/api/supporter_notes/index.json.jbuilder index b0568abefa..96f92fe1b8 100644 --- a/app/views/api/supporter_notes/index.json.jbuilder +++ b/app/views/api/supporter_notes/index.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.data @supporter_notes, partial: '/api/supporter_notes/supporter_note', as: 'supporter_note' +json.data @supporter_notes, partial: "/api/supporter_notes/supporter_note", as: "supporter_note" json.current_page @supporter_notes.current_page json.first_page @supporter_notes.first_page? diff --git a/app/views/api/supporters/_supporter.json.jbuilder b/app/views/api/supporters/_supporter.json.jbuilder index 63d9365055..e9ab7ed784 100644 --- a/app/views/api/supporters/_supporter.json.jbuilder +++ b/app/views/api/supporters/_supporter.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(supporter, :id, :name, :organization, :phone, :anonymous, :deleted) +json.call(supporter, :id, :name, :organization, :phone, :anonymous, :deleted) -json.object 'supporter' +json.object "supporter" json.merged_into supporter.merged_into&.id diff --git a/app/views/api/supporters/index.json.jbuilder b/app/views/api/supporters/index.json.jbuilder index eca94f47b3..242bd86734 100644 --- a/app/views/api/supporters/index.json.jbuilder +++ b/app/views/api/supporters/index.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.data @supporters, partial: '/api/supporters/supporter', as: :supporter +json.data @supporters, partial: "/api/supporters/supporter", as: :supporter json.current_page @supporters.current_page json.first_page @supporters.first_page? diff --git a/app/views/api/tag_definitions/_tag_definition.json.jbuilder b/app/views/api/tag_definitions/_tag_definition.json.jbuilder index edfa754bff..a11458d26a 100644 --- a/app/views/api/tag_definitions/_tag_definition.json.jbuilder +++ b/app/views/api/tag_definitions/_tag_definition.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(tag_definition, :id, :name, :deleted) +json.call(tag_definition, :id, :name, :deleted) -json.object 'tag_definition' +json.object "tag_definition" json.url api_nonprofit_tag_definition_url(tag_definition.nonprofit, tag_definition) diff --git a/app/views/api/tag_definitions/index.json.jbuilder b/app/views/api/tag_definitions/index.json.jbuilder index 885bf55fdc..012182ce62 100644 --- a/app/views/api/tag_definitions/index.json.jbuilder +++ b/app/views/api/tag_definitions/index.json.jbuilder @@ -3,9 +3,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data( - @tag_definitions, - partial: '/api/tag_definitions/tag_definition', - as: 'tag_definition' + @tag_definitions, + partial: "/api/tag_definitions/tag_definition", + as: "tag_definition" ) json.current_page @tag_definitions.current_page diff --git a/app/views/api/ticket_levels/_ticket_level.json.jbuilder b/app/views/api/ticket_levels/_ticket_level.json.jbuilder index 62da084574..c667168ec5 100644 --- a/app/views/api/ticket_levels/_ticket_level.json.jbuilder +++ b/app/views/api/ticket_levels/_ticket_level.json.jbuilder @@ -2,15 +2,15 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(ticket_level, :id, :name, :name, :deleted, :order, :limit, :description) +json.call(ticket_level, :id, :name, :name, :deleted, :order, :limit, :description) -json.object 'ticket_level' +json.object "ticket_level" json.amount do - json.partial! '/api/common/amount', amount: ticket_level.amount_as_money + json.partial! "/api/common/amount", amount: ticket_level.amount_as_money end -json.available_to ticket_level.admin_only ? 'admins' : 'everyone' +json.available_to ticket_level.admin_only ? "admins" : "everyone" json.url api_nonprofit_event_ticket_level_url(ticket_level.nonprofit, ticket_level.event, ticket_level) diff --git a/app/views/api/ticket_levels/index.json.jbuilder b/app/views/api/ticket_levels/index.json.jbuilder index 2e9d4de5b5..228ed0fbec 100644 --- a/app/views/api/ticket_levels/index.json.jbuilder +++ b/app/views/api/ticket_levels/index.json.jbuilder @@ -3,9 +3,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data( - @ticket_levels, - partial: '/api/ticket_levels/ticket_level', - as: 'ticket_level' + @ticket_levels, + partial: "/api/ticket_levels/ticket_level", + as: "ticket_level" ) json.current_page @ticket_levels.current_page diff --git a/app/views/api/transactions/_transaction.json.jbuilder b/app/views/api/transactions/_transaction.json.jbuilder index 32e870df69..6a6ab916e6 100644 --- a/app/views/api/transactions/_transaction.json.jbuilder +++ b/app/views/api/transactions/_transaction.json.jbuilder @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(transaction, :id) +json.call(transaction, :id) -json.object 'transaction' +json.object "transaction" json.created transaction.created.to_i @@ -13,17 +13,17 @@ json.supporter transaction.supporter.id json.nonprofit transaction.nonprofit.id json.amount do - json.partial! '/api/common/amount', amount: transaction.amount_as_money + json.partial! "/api/common/amount", amount: transaction.amount_as_money end json.subtransaction transaction&.subtransaction&.to_id json.transaction_assignments transaction.transaction_assignments do |tra| - json.merge! tra.to_id.attributes! + json.merge! tra.to_id.attributes! end json.payments transaction.payments do |subt_p| - json.merge! subt_p.to_id.attributes! + json.merge! subt_p.to_id.attributes! end json.url api_nonprofit_transaction_url(transaction.nonprofit, transaction) diff --git a/app/views/api/transactions/index.json.jbuilder b/app/views/api/transactions/index.json.jbuilder index 860ca9fb82..86f1d00a61 100644 --- a/app/views/api/transactions/index.json.jbuilder +++ b/app/views/api/transactions/index.json.jbuilder @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.data @transactions, partial: '/api/transactions/transaction', as: 'transaction' +json.data @transactions, partial: "/api/transactions/transaction", as: "transaction" json.current_page @transactions.current_page json.first_page @transactions.first_page? diff --git a/app/views/api/users/_user.json.jbuilder b/app/views/api/users/_user.json.jbuilder index 9e2c3bf2d0..0615db7398 100644 --- a/app/views/api/users/_user.json.jbuilder +++ b/app/views/api/users/_user.json.jbuilder @@ -5,7 +5,7 @@ json.extract! user, :id json.roles user.roles do |role| - json.partial! 'api/roles/role', role: role + json.partial! "api/roles/role", role: role end -json.object 'user' +json.object "user" diff --git a/app/views/app_data/_nonprofit.jbuilder b/app/views/app_data/_nonprofit.jbuilder index fa03279542..c79ae1344d 100644 --- a/app/views/app_data/_nonprofit.jbuilder +++ b/app/views/app_data/_nonprofit.jbuilder @@ -5,13 +5,13 @@ # described in app/javascript/legacy/app_data/Nonprofit.ts -json.extract! nonprofit, :id, :name, #basics - :brand_color, :brand_font, :tagline, #brand - :zip_code, :state_code, :city, - :slug, :state_code_slug, :city_slug, #slugs - :no_anon #options +json.extract! nonprofit, :id, :name, # basics + :brand_color, :brand_font, :tagline, # brand + :zip_code, :state_code, :city, + :slug, :state_code_slug, :city_slug, # slugs + :no_anon # options json.url nonprofit_path(nonprofit) json.logo do - json.normal rails_storage_proxy_url(nonprofit.logo_by_size(:normal)) - json.small rails_storage_proxy_url(nonprofit.logo_by_size(:small)) -end \ No newline at end of file + json.normal rails_storage_proxy_url(nonprofit.logo_by_size(:normal)) + json.small rails_storage_proxy_url(nonprofit.logo_by_size(:small)) +end diff --git a/app/views/app_data/_user.jbuilder b/app/views/app_data/_user.jbuilder index a0329c28bf..1a5827d016 100644 --- a/app/views/app_data/_user.jbuilder +++ b/app/views/app_data/_user.jbuilder @@ -6,4 +6,4 @@ json.extract! user, :id, :created_at, :updated_at, :email json.unconfirmed_email user.unconfirmed_email json.confirmed user.confirmed? -json.partial! 'app_data/profile', profile: user.profile +json.partial! "app_data/profile", profile: user.profile diff --git a/app/views/app_data/_user_with_profile_as_child.jbuilder b/app/views/app_data/_user_with_profile_as_child.jbuilder index 917d2353d6..35dbb1091d 100644 --- a/app/views/app_data/_user_with_profile_as_child.jbuilder +++ b/app/views/app_data/_user_with_profile_as_child.jbuilder @@ -8,7 +8,7 @@ json.unconfirmed_email user.unconfirmed_email json.confirmed user.confirmed? if user.profile - json.profile do - json.partial! 'app_data/profile', profile: user.profile - end + json.profile do + json.partial! "app_data/profile", profile: user.profile + end end diff --git a/app/views/campaigns/_campaign.json.jbuilder b/app/views/campaigns/_campaign.json.jbuilder index 7ac1363c98..87a4f2a1c1 100644 --- a/app/views/campaigns/_campaign.json.jbuilder +++ b/app/views/campaigns/_campaign.json.jbuilder @@ -3,23 +3,23 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.extract! campaign, :id, :name, # basics - :nonprofit_id, :profile_id, :parent_campaign_id, # references - :reason_for_supporting, :default_reason_for_supporting, - :published, :deleted + :nonprofit_id, :profile_id, :parent_campaign_id, # references + :reason_for_supporting, :default_reason_for_supporting, + :published, :deleted json.url campaign_locateable_url(campaign) if campaign.main_image.attached? - json.main_image do - json.full rails_storage_proxy_url(campaign.main_image) - json.normal rails_storage_proxy_url(campaign.main_image_by_size(:normal)) - json.thumb rails_storage_proxy_url(campaign.main_image_by_size(:thumb)) - end + json.main_image do + json.full rails_storage_proxy_url(campaign.main_image) + json.normal rails_storage_proxy_url(campaign.main_image_by_size(:normal)) + json.thumb rails_storage_proxy_url(campaign.main_image_by_size(:thumb)) + end end if campaign.background_image.attached? - json.background_image do - json.full rails_storage_proxy_url(campaign.background_image) - json.normal rails_storage_proxy_url(campaign.background_image_by_size(:normal)) - end + json.background_image do + json.full rails_storage_proxy_url(campaign.background_image) + json.normal rails_storage_proxy_url(campaign.background_image_by_size(:normal)) + end end diff --git a/app/views/campaigns/create.json.jbuilder b/app/views/campaigns/create.json.jbuilder index 586232c3af..4e592e9ac4 100644 --- a/app/views/campaigns/create.json.jbuilder +++ b/app/views/campaigns/create.json.jbuilder @@ -3,26 +3,26 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.extract!( - @campaign, - :id, :name, # basics - :nonprofit_id, :profile_id, :parent_campaign_id, # references - :reason_for_supporting, :default_reason_for_supporting, - :published, :deleted + @campaign, + :id, :name, # basics + :nonprofit_id, :profile_id, :parent_campaign_id, # references + :reason_for_supporting, :default_reason_for_supporting, + :published, :deleted ) json.url campaign_locateable_url(@campaign) if @campaign.main_image.attached? - json.main_image do - json.full rails_storage_proxy_url(@campaign.main_image) - json.normal rails_storage_proxy_url(@campaign.main_image_by_size(:normal)) - json.thumb rails_storage_proxy_url(@campaign.main_image_by_size(:thumb)) - end + json.main_image do + json.full rails_storage_proxy_url(@campaign.main_image) + json.normal rails_storage_proxy_url(@campaign.main_image_by_size(:normal)) + json.thumb rails_storage_proxy_url(@campaign.main_image_by_size(:thumb)) + end end if @campaign.background_image.attached? - json.background_image do - json.full rails_storage_proxy_url(@campaign.background_image) - json.normal rails_storage_proxy_url(@campaign.background_image_by_size(:normal)) - end + json.background_image do + json.full rails_storage_proxy_url(@campaign.background_image) + json.normal rails_storage_proxy_url(@campaign.background_image_by_size(:normal)) + end end diff --git a/app/views/campaigns/index.jbuilder b/app/views/campaigns/index.jbuilder index eec96dba91..b48950ad9d 100644 --- a/app/views/campaigns/index.jbuilder +++ b/app/views/campaigns/index.jbuilder @@ -5,4 +5,4 @@ json.data @campaigns do |campaign| json.extract! campaign, :name, :total_raised, :goal_amount, :id json.url campaign_locateable_url(campaign) -end \ No newline at end of file +end diff --git a/app/views/campaigns/update.json.jbuilder b/app/views/campaigns/update.json.jbuilder index da03786400..2e60a575da 100644 --- a/app/views/campaigns/update.json.jbuilder +++ b/app/views/campaigns/update.json.jbuilder @@ -2,4 +2,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.partial! 'campaigns/campaign', campaign: @campaign +json.partial! "campaigns/campaign", campaign: @campaign diff --git a/app/views/cards/create.json.jbuilder b/app/views/cards/create.json.jbuilder index bd81b89a2a..be03aff38b 100644 --- a/app/views/cards/create.json.jbuilder +++ b/app/views/cards/create.json.jbuilder @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(@source_token, :token) +json.call(@source_token, :token) json.holder_id @source_token.tokenizable.holder_id json.holder_type @source_token.tokenizable.holder_type diff --git a/app/views/components/_side_nav.json.jbuilder b/app/views/components/_side_nav.json.jbuilder index a1139d8f7a..311c26bcb2 100644 --- a/app/views/components/_side_nav.json.jbuilder +++ b/app/views/components/_side_nav.json.jbuilder @@ -3,23 +3,23 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE -json.partial! 'users/sign_in' +json.partial! "users/sign_in" json.innerProps do - if administered_nonprofit - json.administeredNonprofit do - json.partial! 'app_data/nonprofit', nonprofit: administered_nonprofit - end - end + if administered_nonprofit + json.administeredNonprofit do + json.partial! "app_data/nonprofit", nonprofit: administered_nonprofit + end + end - if current_user - json.currentUser do - json.partial! 'app_data/user_with_profile_as_child', user: current_user - end - end + if current_user + json.currentUser do + json.partial! "app_data/user_with_profile_as_child", user: current_user + end + end - json.logo do - json.url Houdini.general.logo - json.alt Houdini.general.name - end + json.logo do + json.url Houdini.general.logo + json.alt Houdini.general.name + end end diff --git a/app/views/events/name_and_id.json.jbuilder b/app/views/events/name_and_id.json.jbuilder index 911ff94745..b777b208c9 100644 --- a/app/views/events/name_and_id.json.jbuilder +++ b/app/views/events/name_and_id.json.jbuilder @@ -3,5 +3,5 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.array! @events do |event| - json.(event, :name, :id) + json.call(event, :name, :id) end diff --git a/app/views/events/update.json.jbuilder b/app/views/events/update.json.jbuilder index 471d3a5df4..320de4254a 100644 --- a/app/views/events/update.json.jbuilder +++ b/app/views/events/update.json.jbuilder @@ -3,4 +3,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.partial! 'api/events/event', event: @event +json.partial! "api/events/event", event: @event diff --git a/app/views/nonprofits/_transaction_title.json.jbuilder b/app/views/nonprofits/_transaction_title.json.jbuilder index a4799a8f73..86b9aa6eda 100644 --- a/app/views/nonprofits/_transaction_title.json.jbuilder +++ b/app/views/nonprofits/_transaction_title.json.jbuilder @@ -4,11 +4,11 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE json.innerProps do - json.nonprofit do - json.partial! 'app_data/nonprofit', nonprofit: administered_nonprofit - end + json.nonprofit do + json.partial! "app_data/nonprofit", nonprofit: administered_nonprofit + end - json.active active - json.page_name page_name - json.icon_class icon_class + json.active active + json.page_name page_name + json.icon_class icon_class end diff --git a/app/views/nonprofits/custom_field_joins/index.jbuilder b/app/views/nonprofits/custom_field_joins/index.jbuilder index 3d743574f0..b3f194d019 100644 --- a/app/views/nonprofits/custom_field_joins/index.jbuilder +++ b/app/views/nonprofits/custom_field_joins/index.jbuilder @@ -4,6 +4,5 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data @custom_field_joins do |cfj| - json.extract! cfj, :name, :created_at, :id, :value + json.extract! cfj, :name, :created_at, :id, :value end - diff --git a/app/views/nonprofits/donations/create.json.jbuilder b/app/views/nonprofits/donations/create.json.jbuilder index 38793eb24a..fbcdafbd9d 100644 --- a/app/views/nonprofits/donations/create.json.jbuilder +++ b/app/views/nonprofits/donations/create.json.jbuilder @@ -3,8 +3,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -donation = @result['donation'] +donation = @result["donation"] json.donation do - json.id donation.id + json.id donation.id end diff --git a/app/views/nonprofits/payments/show.jbuilder b/app/views/nonprofits/payments/show.jbuilder index 6d6957185b..b376d482fb 100644 --- a/app/views/nonprofits/payments/show.jbuilder +++ b/app/views/nonprofits/payments/show.jbuilder @@ -3,77 +3,91 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data do - json.extract! @payment, :id, :gross_amount, - :towards, :net_amount, - :fee_total, :date, - :refund_total, :kind - + json.extract! @payment, :id, :gross_amount, + :towards, :net_amount, + :fee_total, :date, + :refund_total, :kind + d_anonymous = @payment.donation.nil? ? false : @payment.donation.anonymous - json.consider_donation_anonymous (!!d_anonymous || !!@payment.supporter.anonymous) - + json.consider_donation_anonymous(!!d_anonymous || !!@payment.supporter.anonymous) + json.charge do json.extract! @payment.charge, :created_at, :id, :status end - json.donation do - d = @payment.donation - json.extract! d, :designation, :dedication, :origin_url, :id, :comment + if @payment.donation + json.donation do + d = @payment.donation + json.extract! d, :designation, :dedication, :origin_url, :id, :comment - - json.campaign do - c = d.campaign - json.extract! c, :name, :id - json.url campaign_locateable_url(c) - end if d.campaign - + if d.campaign + json.campaign do + c = d.campaign + json.extract! c, :name, :id + json.url campaign_locateable_url(c) + end + end - json.campaign_gift do - json.name(d.campaign_gifts.any? ? d.campaign_gifts.last.campaign_gift_option.name : nil) - end + json.campaign_gift do + json.name(d.campaign_gifts.any? ? d.campaign_gifts.last.campaign_gift_option.name : nil) + end - json.event(d.event, partial: "events/event", as: :event) if d.event + json.event(d.event, partial: "events/event", as: :event) if d.event - json.recurring_donation do - rd = d.recurring_donation - json.extract! rd, :interval, :time_unit, :created_at - end if d.recurring_donation - end if @payment.donation + if d.recurring_donation + json.recurring_donation do + rd = d.recurring_donation + json.extract! rd, :interval, :time_unit, :created_at + end + end + end + end - json.dispute do - dis =@payment.dispute - json.extract! dis, :id, :status, :reason - end if @payment.dispute + if @payment.dispute + json.dispute do + dis = @payment.dispute + json.extract! dis, :id, :status, :reason + end + end - json.refund do - ref = @payment.refund - json.extract! ref, :reason, :comment, :disbursed - end if @payment.refund + if @payment.refund + json.refund do + ref = @payment.refund + json.extract! ref, :reason, :comment, :disbursed + end + end - json.offsite_payment do - off_p = @payment.offsite_payment - json.extract! off_p, :check_number, :kind - end if @payment.offsite_payment + if @payment.offsite_payment + json.offsite_payment do + off_p = @payment.offsite_payment + json.extract! off_p, :check_number, :kind + end + end - json.ticket do + if @payment&.tickets&.last&.event + json.ticket do event = @payment.tickets.last.event json.event do json.extract! event, :name, :id json.url event_locateable_url(event) end - json.levels @payment.tickets.map { |t| "#{t.ticket_level&.name} (#{t.quantity}x)" }.join(', ') - json.discount @payment.tickets.map { |t| t.event_discount ? "#{t.event_discount.name} (#{t.event_discount.percent}%)" : nil }.compact.join(', ') - end if @payment&.tickets&.last&.event + json.levels @payment.tickets.map { |t| "#{t.ticket_level&.name} (#{t.quantity}x)" }.join(", ") + json.discount @payment.tickets.map { |t| t.event_discount ? "#{t.event_discount.name} (#{t.event_discount.percent}%)" : nil }.compact.join(", ") + end + end - json.tickets @payment.tickets do |t| - json.id t.id - json.ticket_level t.ticket_level, :name - end if @payment.tickets.any? + if @payment.tickets.any? + json.tickets @payment.tickets do |t| + json.id t.id + json.ticket_level t.ticket_level, :name + end + end - json.supporter do + json.supporter do json.extract! @payment.supporter, :name, :email, :city, :state_code, :address, :zip_code, :phone, :id, :country end - json.nonprofit do + json.nonprofit do json.id @payment.nonprofit.id end -end \ No newline at end of file +end diff --git a/app/views/nonprofits/recurring_donations/show.jbuilder b/app/views/nonprofits/recurring_donations/show.jbuilder index e74f1f75b4..df5b65481d 100644 --- a/app/views/nonprofits/recurring_donations/show.jbuilder +++ b/app/views/nonprofits/recurring_donations/show.jbuilder @@ -3,11 +3,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data recurring_donation do |rd| - json.extract! rd, :id, :total_given, - :supporter_id, :interval, - :time_unit, :designation, - :anonymous, :start_date, :end_date, - :created_at, :paydate, :edit_token + json.extract! rd, :id, :total_given, + :supporter_id, :interval, + :time_unit, :designation, + :anonymous, :start_date, :end_date, + :created_at, :paydate, :edit_token json.donation recurring_donation.donation do |d| json.extract! d, :id, :amount, :designation end @@ -19,4 +19,4 @@ json.data recurring_donation do |rd| json.card recurring_donation.card do |c| json.extract! c, :name end -end \ No newline at end of file +end diff --git a/app/views/nonprofits/refunds/index.jbuilder b/app/views/nonprofits/refunds/index.jbuilder index c92f48cc09..f268925e2c 100644 --- a/app/views/nonprofits/refunds/index.jbuilder +++ b/app/views/nonprofits/refunds/index.jbuilder @@ -4,4 +4,4 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data refunds do |refund| json.extract refund, :id, :amount, :created_at, :reason, :comment -end \ No newline at end of file +end diff --git a/app/views/nonprofits/show.json.jbuilder b/app/views/nonprofits/show.json.jbuilder index ba5a40dba6..d92fb75688 100644 --- a/app/views/nonprofits/show.json.jbuilder +++ b/app/views/nonprofits/show.json.jbuilder @@ -2,28 +2,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.( - @nonprofit, - :id, - :name, - :url, - :tagline, - :phone, - :email, - :website, - :summary, - :categories, - :full_description, - :published, - :no_anon, - :timezone, - :brand_color, - :hide_activity_feed, - :state_code, - :state_code_slug, - :city, - :city_slug, - :slug, - :zip_code, - :currency -) +json.call(@nonprofit, :id, :name, :url, :tagline, :phone, :email, :website, :summary, :categories, :full_description, :published, :no_anon, :timezone, :brand_color, :hide_activity_feed, :state_code, :state_code_slug, :city, :city_slug, :slug, :zip_code, :currency) diff --git a/app/views/nonprofits/supporters/create.json.jbuilder b/app/views/nonprofits/supporters/create.json.jbuilder index 679884d214..f94b990ba0 100644 --- a/app/views/nonprofits/supporters/create.json.jbuilder +++ b/app/views/nonprofits/supporters/create.json.jbuilder @@ -3,4 +3,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -json.(@supporter, :id, :name, :email, :zip_code) +json.call(@supporter, :id, :name, :email, :zip_code) diff --git a/app/views/nonprofits/tag_definitions/index.json.jbuilder b/app/views/nonprofits/tag_definitions/index.json.jbuilder index c726410060..d9eb80fe57 100644 --- a/app/views/nonprofits/tag_definitions/index.json.jbuilder +++ b/app/views/nonprofits/tag_definitions/index.json.jbuilder @@ -4,5 +4,5 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE json.data @tag_definitions do |tag_definition| - json.(tag_definition, :id, :name, :created_at) + json.call(tag_definition, :id, :name, :created_at) end diff --git a/app/views/users/_sign_in.jbuilder b/app/views/users/_sign_in.jbuilder index b9cb03e4b8..18ffb2a6bf 100644 --- a/app/views/users/_sign_in.jbuilder +++ b/app/views/users/_sign_in.jbuilder @@ -4,9 +4,9 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE json.i18n do - json.locale 'en' + json.locale "en" end json.hoster do - json.(Houdini.hoster, :legal_name, :casual_name) + json.call(Houdini.hoster, :legal_name, :casual_name) end diff --git a/app/views/users/sessions/create.jbuilder b/app/views/users/sessions/create.jbuilder index 9164176d4c..5c123a171f 100644 --- a/app/views/users/sessions/create.jbuilder +++ b/app/views/users/sessions/create.jbuilder @@ -3,4 +3,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE -json.partial! '/api/users/user', user: @user +json.partial! "/api/users/user", user: @user diff --git a/commands/rails/commands/houdini/nonprofit/create/create_command.rb b/commands/rails/commands/houdini/nonprofit/create/create_command.rb index 50dea579ac..d5d25530b3 100644 --- a/commands/rails/commands/houdini/nonprofit/create/create_command.rb +++ b/commands/rails/commands/houdini/nonprofit/create/create_command.rb @@ -7,65 +7,65 @@ # NOTE: if this is moved to bess, it should be in the `houdini/lib/` subdirectory of bess. # module Houdini # rubocop:disable Style/ClassAndModuleChildren -- can't combine because Houdini hasn't been defined before - class Nonprofit - # Used for creating nonprofits at the command line - class CreateCommand < Rails::Command::Base - desc 'Create a new nonprofit on your Houdini instance' - option :super_admin, aliases: '-s', default: false, type: :boolean, - desc: "Make the nonprofit admin a super user (they can access any nonprofit's dashboards)" - option :confirm_admin, default: true, type: :boolean, - desc: 'Autoconfirm the admin instead of waiting for them to click the email link' + class Nonprofit + # Used for creating nonprofits at the command line + class CreateCommand < Rails::Command::Base + desc "Create a new nonprofit on your Houdini instance" + option :super_admin, aliases: "-s", default: false, type: :boolean, + desc: "Make the nonprofit admin a super user (they can access any nonprofit's dashboards)" + option :confirm_admin, default: true, type: :boolean, + desc: "Autoconfirm the admin instead of waiting for them to click the email link" - option :nonprofit_name, default: nil, desc: "Provide the nonprofit's name" - option :state_code, default: nil, desc: "Provide the nonprofit's state code, e.g. WI for Wisconsin" - option :city, default: nil, desc: "Provide the nonprofit's city" - option :nonprofit_website, default: nil, desc: "[OPTIONAL] Provide the nonprofit's public website" - option :nonprofit_email, default: nil, desc: "[OPTIONAL] Provide the nonprofit's public email" - option :nonprofit_phone, default: nil, desc: "[OPTIONAL] Provide the nonprofit's public phone number" + option :nonprofit_name, default: nil, desc: "Provide the nonprofit's name" + option :state_code, default: nil, desc: "Provide the nonprofit's state code, e.g. WI for Wisconsin" + option :city, default: nil, desc: "Provide the nonprofit's city" + option :nonprofit_website, default: nil, desc: "[OPTIONAL] Provide the nonprofit's public website" + option :nonprofit_email, default: nil, desc: "[OPTIONAL] Provide the nonprofit's public email" + option :nonprofit_phone, default: nil, desc: "[OPTIONAL] Provide the nonprofit's public phone number" - option :user_name, default: nil, desc: "Provide the nonprofit's admin's name" - option :user_email, - default: nil, - desc: "Provide the nonprofit's admin's email address (It'll be used for logging in)" - option :user_password, default: nil, desc: "Provide the nonprofit's admin's password" + option :user_name, default: nil, desc: "Provide the nonprofit's admin's name" + option :user_email, + default: nil, + desc: "Provide the nonprofit's admin's email address (It'll be used for logging in)" + option :user_password, default: nil, desc: "Provide the nonprofit's admin's password" - def perform - result = { - nonprofit: ask_for_nonprofit_information(options), - user: ask_for_user_information(options) - } - say - require_application_and_environment! + def perform + result = { + nonprofit: ask_for_nonprofit_information(options), + user: ask_for_user_information(options) + } + say + require_application_and_environment! - creation_result = ::NonprofitCreation.new(result, options).call + creation_result = ::NonprofitCreation.new(result, options).call - creation_result[:messages].each do |msg| - say(msg) - end - end + creation_result[:messages].each do |msg| + say(msg) + end + end - private + private - def ask_for_nonprofit_information(options) - { - name: options[:nonprofit_name] || ask("What is the nonprofit's name?"), - state_code: options[:state_code] || ask("What is the nonprofit's state?"), - city: options[:city] || ask("What is the nonprofit's city?"), - website: options[:nonprofit_website] || ask("[OPTIONAL] What is the nonprofit's public website?"), - email: options[:nonprofit_email] || ask("[OPTIONAL] What is the nonprofit's public e-mail?"), - phone: options[:nonprofit_phone] || ask("[OPTIONAL] What is your nonprofit's public phone number?") - } - end + def ask_for_nonprofit_information(options) + { + name: options[:nonprofit_name] || ask("What is the nonprofit's name?"), + state_code: options[:state_code] || ask("What is the nonprofit's state?"), + city: options[:city] || ask("What is the nonprofit's city?"), + website: options[:nonprofit_website] || ask("[OPTIONAL] What is the nonprofit's public website?"), + email: options[:nonprofit_email] || ask("[OPTIONAL] What is the nonprofit's public e-mail?"), + phone: options[:nonprofit_phone] || ask("[OPTIONAL] What is your nonprofit's public phone number?") + } + end - def ask_for_user_information(options) - { - name: options[:user_name] || ask("What is your nonprofit's admin's name?"), - email: options[:user_email] || ask( - "What is your nonprofit's admin's email address? (It'll be used for logging in)" - ), - password: options[:user_password] || ask("What is the nonprofit's admin's password?", echo: false) - } - end - end - end + def ask_for_user_information(options) + { + name: options[:user_name] || ask("What is your nonprofit's admin's name?"), + email: options[:user_email] || ask( + "What is your nonprofit's admin's email address? (It'll be used for logging in)" + ), + password: options[:user_password] || ask("What is the nonprofit's admin's password?", echo: false) + } + end + end + end end diff --git a/config/application.rb b/config/application.rb index 7586fcb07d..9f54cbf63d 100755 --- a/config/application.rb +++ b/config/application.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative 'boot' +require_relative "boot" require "rails" # Pick the frameworks you want: @@ -26,7 +26,7 @@ module Commitchange class Application < Rails::Application - config.load_defaults '5.0' + config.load_defaults "5.0" # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. @@ -34,20 +34,20 @@ class Application < Rails::Application # Custom directories with classes and modules you want to be autoloadable. # config.autoload_paths += %W(#{config.root}/extras) - config.paths.add File.join('app', 'listeners'), glob: File.join('**', '*.rb') + config.paths.add File.join("app", "listeners"), glob: File.join("**", "*.rb") # config.eager_load_paths += Dir[Rails.root.join('app', 'api', '*'), Rails.root.join('app', 'listeners', '*')] # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "bin/rails -D time" for a list of tasks for finding time zone names. Default is UTC. - config.time_zone = 'UTC' + config.time_zone = "UTC" # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml')] + config.i18n.load_path += Dir[Rails.root.join("config/locales/**/*.yml")] # config.i18n.default_locale = :de # Configure the default encoding used in templates for Ruby 1.9. - config.encoding = 'utf-8' + config.encoding = "utf-8" # Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password] @@ -66,7 +66,7 @@ class Application < Rails::Application # Precompile all "page" files config.assets.precompile << proc do |path| if /.*page\.(css|js)/.match?(path) - puts 'Compiling asset: ' + path + puts "Compiling asset: " + path true else false @@ -74,7 +74,7 @@ class Application < Rails::Application end # add fonts to assets pipeline - config.assets.paths << Rails.root.join('app', 'assets', 'fonts') + config.assets.paths << Rails.root.join("app/assets/fonts") # Version of your assets, change this If you want to expire all your assets # config.assets.version = '1.0' @@ -99,19 +99,23 @@ class Application < Rails::Application config.active_job.queue_adapter = :good_job # this works around a bug where the the webpacker proxy - # only waits 60 seconds for a compilation to happen. That's not + # only waits 60 seconds for a compilation to happen. That's not # fast enough on startup and Webpacker doesn't allow us to override. - # + # # TODO: figure out how to delete the first instance of DevServerProxy initializer "houdini.webpacker.proxy" do |app| - insert_middleware = Webpacker.config.dev_server.present? rescue nil + insert_middleware = begin + Webpacker.config.dev_server.present? + rescue + nil + end if insert_middleware app.middleware.insert_before 0, - Webpacker::DevServerProxy, ssl_verify_none: true, read_timeout: 500 + Webpacker::DevServerProxy, ssl_verify_none: true, read_timeout: 500 end end end end # we want to add the houdini configuration -require_relative './houdini_config' +require_relative "houdini_config" diff --git a/config/boot.rb b/config/boot.rb index 9f69ff0205..166a4ce263 100755 --- a/config/boot.rb +++ b/config/boot.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" # Set up gems listed in the Gemfile. require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/config/environment.rb b/config/environment.rb index f6b2ffb64e..7a617c4c0f 100755 --- a/config/environment.rb +++ b/config/environment.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # Load the Rails application -require_relative 'application' +require_relative "application" Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 diff --git a/config/environments/ci.rb b/config/environments/ci.rb index 8677e50e36..a48384787e 100755 --- a/config/environments/ci.rb +++ b/config/environments/ci.rb @@ -22,11 +22,11 @@ # config.action_mailer.delivery_method = :aws_ses # config.action_mailer.default_url_options = { host: 'commitchange.com' } config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym - config.action_mailer.smtp_settings = { address: Settings.mailer.address, port: Settings.mailer.port } - config.action_mailer.smtp_settings['user_name'] = Settings.mailer.username if Settings.mailer.username - config.action_mailer.smtp_settings['password'] = Settings.mailer.password if Settings.mailer.password + config.action_mailer.smtp_settings = {address: Settings.mailer.address, port: Settings.mailer.port} + config.action_mailer.smtp_settings["user_name"] = Settings.mailer.username if Settings.mailer.username + config.action_mailer.smtp_settings["password"] = Settings.mailer.password if Settings.mailer.password - config.action_mailer.default_url_options = { host: Settings.mailer.host } + config.action_mailer.default_url_options = {host: Settings.mailer.host} # Print deprecation notices to the Rails logger config.active_support.deprecation = :log diff --git a/config/environments/development.rb b/config/environments/development.rb index 909c3b1875..f46f8dd141 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -19,13 +19,13 @@ # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. - if Rails.root.join('tmp', 'caching-dev.txt').exist? + if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.to_i}" + "Cache-Control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false @@ -66,7 +66,7 @@ # config.action_view.raise_on_missing_translations = true # config.i18n.raise_on_missing_translations = true - + # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true @@ -76,7 +76,7 @@ config.log_level = :debug - config.action_mailer.default_url_options = {host: 'http://localhost:5000'} + config.action_mailer.default_url_options = {host: "http://localhost:5000"} # don't load factories in development config.factory_bot.definition_file_paths = [] diff --git a/config/environments/production.rb b/config/environments/production.rb index 2b514a48d3..7a5395c07a 100755 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -13,7 +13,7 @@ config.eager_load = true # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] @@ -22,7 +22,7 @@ # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? # Compress CSS using a preprocessor. # config.assets.css_compressor = :sass @@ -50,7 +50,7 @@ config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -86,9 +86,9 @@ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) + logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) + config.logger = ActiveSupport::TaggedLogging.new(logger) end # Do not dump schema after migrations. diff --git a/config/environments/staging.rb b/config/environments/staging.rb index b3dc58ce17..f92b0c7dc1 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -47,7 +47,7 @@ # cdn_url = "https://d2e5we1j08b82a.cloudfront.net" # config.action_controller.asset_host = cdn_url # config.action_mailer.asset_host = cdn_url - config.font_assets.origin = '*' + config.font_assets.origin = "*" # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) # config.assets.precompile = ['application', 'manifests/*'] @@ -55,7 +55,7 @@ # Disable delivery errors, bad email addresses will be ignored # config.action_mailer.raise_delivery_errors = false config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym - config.action_mailer.default_url_options = { host: Settings.mailer.host } + config.action_mailer.default_url_options = {host: Settings.mailer.host} # Enable threaded mode # config.threadsafe! diff --git a/config/environments/test.rb b/config/environments/test.rb index 03d0fb2b2e..7807fd505c 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -18,11 +18,11 @@ # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + "Cache-Control" => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false config.cache_store = :null_store @@ -46,13 +46,13 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - config.action_mailer.default_url_options = { host: 'houdiniproject.test' } + config.action_mailer.default_url_options = {host: "houdiniproject.test"} - config.default_url_options = { host: 'houdiniproject.test' } + config.default_url_options = {host: "houdiniproject.test"} # Raise exceptions for disallowed deprecations. config.active_support.disallowed_deprecation = :raise - + # Tell Active Support which deprecation messages to disallow. config.active_support.disallowed_deprecation_warnings = [] @@ -61,5 +61,4 @@ # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - end diff --git a/config/houdini_config.rb b/config/houdini_config.rb index 08876e72fb..266d6212b4 100755 --- a/config/houdini_config.rb +++ b/config/houdini_config.rb @@ -5,5 +5,5 @@ # customize Houdini configuration here. Rails.application.configure do - config.houdini.hoster.legal_name = 'SET config.houdini.hoster.legal_name IN app/config/houdini_config.rb' + config.houdini.hoster.legal_name = "SET config.houdini.hoster.legal_name IN app/config/houdini_config.rb" end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index cf6c081960..92c5089d98 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -3,11 +3,11 @@ # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' +Rails.application.config.assets.version = "1.0" # Add additional assets to the asset load path # Rails.application.config.assets.paths << Emoji.images_path # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -Rails.application.config.assets.precompile += %w( widget/donate-button.css widget/donate-button-v2.css) +Rails.application.config.assets.precompile += %w[widget/donate-button.css widget/donate-button-v2.css] diff --git a/config/initializers/chunked_uploader_service.rb b/config/initializers/chunked_uploader_service.rb index 670cfdbe46..c0e1bda53a 100644 --- a/config/initializers/chunked_uploader_service.rb +++ b/config/initializers/chunked_uploader_service.rb @@ -3,11 +3,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE - ActiveSupport.on_load(:active_storage_blob) do - CHUNKED_UPLOAD_SERVICE = ENV['CHUNKED_UPLOAD_SERVICE'] ? ActiveStorage::Service.configure( - ENV['CHUNKED_UPLOAD_SERVICE'], - Rails.configuration.active_storage.service_configurations) : ActiveStorage::Blob.service + CHUNKED_UPLOAD_SERVICE = ENV["CHUNKED_UPLOAD_SERVICE"] ? ActiveStorage::Service.configure( + ENV["CHUNKED_UPLOAD_SERVICE"], + Rails.configuration.active_storage.service_configurations + ) : ActiveStorage::Blob.service end - - diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index e99ccec08b..81e32dce75 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -5,17 +5,17 @@ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy Rails.application.config.content_security_policy do |policy| -# policy.default_src :self, :https -# policy.font_src :self, :https, :data -# policy.img_src :self, :https, :data -# policy.object_src :none -# policy.script_src :self, :https -# policy.style_src :self, :https + # policy.default_src :self, :https + # policy.font_src :self, :https, :data + # policy.img_src :self, :https, :data + # policy.object_src :none + # policy.script_src :self, :https + # policy.style_src :self, :https -# # Specify URI for violation reports -# # policy.report_uri "/csp-violation-report-endpoint" + # # Specify URI for violation reports + # # policy.report_uri "/csp-violation-report-endpoint" - policy.connect_src :self, :https, 'http://localhost:3035', 'ws://localhost:3035' if Rails.env.development? + policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? end # If you are using UJS then enable automatic nonce generation diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index a54ea0de3b..8752507f26 100755 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -17,7 +17,7 @@ # Load and configure the ORM. Supports :active_record (default) and # :mongoid (bson_ext recommended) by default. Other ORMs may be # available as additional gems. - require 'devise/orm/active_record' + require "devise/orm/active_record" # ==> Configuration for any authentication mechanism # Configure which keys are used when authenticating a user. The default is @@ -203,7 +203,7 @@ # The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = :get - config.secret_key = ENV.fetch('DEVISE_SECRET_KEY') + config.secret_key = ENV.fetch("DEVISE_SECRET_KEY") # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or @@ -229,17 +229,16 @@ # config.omniauth_path_prefix = "/my_engine/users/auth" end - ActiveSupport.on_load(:devise_failure_app) do module Devise class FailureApp # we don't every want to return WWW-Authenticate because we never want a popup. def http_auth self.status = 401 - #self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header? + # self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header? self.content_type = request.format.to_s self.response_body = http_auth_body end end end -end \ No newline at end of file +end diff --git a/config/initializers/email_jobs.rb b/config/initializers/email_jobs.rb index 95d0ae97f7..c93c084d04 100644 --- a/config/initializers/email_jobs.rb +++ b/config/initializers/email_jobs.rb @@ -2,4 +2,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -MAX_EMAIL_JOB_ATTEMPTS = Rails.env == 'production' ? 50 : 2 +MAX_EMAIL_JOB_ATTEMPTS = Rails.env.production? ? 50 : 2 diff --git a/config/initializers/houdini_event_publisher.rb b/config/initializers/houdini_event_publisher.rb index 718da0e5c6..f748c0f30b 100644 --- a/config/initializers/houdini_event_publisher.rb +++ b/config/initializers/houdini_event_publisher.rb @@ -6,9 +6,9 @@ Wisper.clear if Rails.env.development? Rails.application.config.houdini.listeners.push( - NonprofitMailerListener, - CreditCardPaymentListener, - SepaPaymentListener, - TicketMailingListener, - ObjectEventListener + NonprofitMailerListener, + CreditCardPaymentListener, + SepaPaymentListener, + TicketMailingListener, + ObjectEventListener ) diff --git a/config/initializers/js_routes.rb b/config/initializers/js_routes.rb index b1f92216f1..3d3e983684 100644 --- a/config/initializers/js_routes.rb +++ b/config/initializers/js_routes.rb @@ -3,8 +3,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE JsRoutes.setup do |c| - # Setup your JS module system: - # ESM, CJS, AMD, UMD or nil - c.module_type = 'CJS' - c.camel_case = true + # Setup your JS module system: + # ESM, CJS, AMD, UMD or nil + c.module_type = "CJS" + c.camel_case = true end diff --git a/config/initializers/mailchimp.rb b/config/initializers/mailchimp.rb index 3892521a48..775b461028 100644 --- a/config/initializers/mailchimp.rb +++ b/config/initializers/mailchimp.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'mailchimp' +require "mailchimp" Mailchimp.config( - api_key: ENV['MAILCHIMP_API_KEY'] + api_key: ENV["MAILCHIMP_API_KEY"] ) diff --git a/config/initializers/pg_type_map.rb b/config/initializers/pg_type_map.rb index 9cb72c58af..27cc605954 100644 --- a/config/initializers/pg_type_map.rb +++ b/config/initializers/pg_type_map.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'active_record' -require 'qx' -require 'pg' +require "active_record" +require "qx" +require "pg" def database_exists? ActiveRecord::Base.connection rescue ActiveRecord::NoDatabaseError false else Qx.config(type_map: PG::BasicTypeMapForResults.new(ActiveRecord::Base.connection.raw_connection)) - Qx.execute('SET TIME ZONE utc') + Qx.execute("SET TIME ZONE utc") end diff --git a/config/initializers/react_on_rails.rb b/config/initializers/react_on_rails.rb index 1bb4e1f1f7..cd70f1ac97 100644 --- a/config/initializers/react_on_rails.rb +++ b/config/initializers/react_on_rails.rb @@ -4,42 +4,42 @@ # for many more options. ReactOnRails.configure do |config| - # This configures the script to run to build the production assets by webpack. Set this to nil - # if you don't want react_on_rails building this file for you. - # If nil, then the standard rails/webpacker assets:precompile will run - # config.build_production_command = nil + # This configures the script to run to build the production assets by webpack. Set this to nil + # if you don't want react_on_rails building this file for you. + # If nil, then the standard rails/webpacker assets:precompile will run + # config.build_production_command = nil - ################################################################################ - ################################################################################ - # TEST CONFIGURATION OPTIONS - # Below options are used with the use of this test helper: - # ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) - ################################################################################ + ################################################################################ + ################################################################################ + # TEST CONFIGURATION OPTIONS + # Below options are used with the use of this test helper: + # ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) + ################################################################################ - # If you are using this in your spec_helper.rb (or rails_helper.rb): - # - # ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) - # - # with rspec then this controls what yarn command is run - # to automatically refresh your webpack assets on every test run. - # - # Alternately, you can remove the `ReactOnRails::TestHelper.configure_rspec_to_compile_assets` - # and set the config/webpacker.yml option for test to true. - config.build_test_command = 'RAILS_ENV=test bin/webpack' + # If you are using this in your spec_helper.rb (or rails_helper.rb): + # + # ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) + # + # with rspec then this controls what yarn command is run + # to automatically refresh your webpack assets on every test run. + # + # Alternately, you can remove the `ReactOnRails::TestHelper.configure_rspec_to_compile_assets` + # and set the config/webpacker.yml option for test to true. + config.build_test_command = "RAILS_ENV=test bin/webpack" - ################################################################################ - ################################################################################ - # SERVER RENDERING OPTIONS - ################################################################################ - # This is the file used for server rendering of React when using `(prerender: true)` - # If you are never using server rendering, you should set this to "". - # Note, there is only one server bundle, unlike JavaScript where you want to minimize the size - # of the JS sent to the client. For the server rendering, React on Rails creates a pool of - # JavaScript execution instances which should handle any component requested. - # - # While you may configure this to be the same as your client bundle file, this file is typically - # different. You should have ONE server bundle which can create all of your server rendered - # React components. - # - # config.server_bundle_js_file = 'hello-world-bundle.js' + ################################################################################ + ################################################################################ + # SERVER RENDERING OPTIONS + ################################################################################ + # This is the file used for server rendering of React when using `(prerender: true)` + # If you are never using server rendering, you should set this to "". + # Note, there is only one server bundle, unlike JavaScript where you want to minimize the size + # of the JS sent to the client. For the server rendering, React on Rails creates a pool of + # JavaScript execution instances which should handle any component requested. + # + # While you may configure this to be the same as your client bundle file, this file is typically + # different. You should have ONE server bundle which can create all of your server rendered + # React components. + # + # config.server_bundle_js_file = 'hello-world-bundle.js' end diff --git a/config/initializers/reload_api.rb b/config/initializers/reload_api.rb index 8ec0657e90..06979db1de 100644 --- a/config/initializers/reload_api.rb +++ b/config/initializers/reload_api.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true if Rails.env.development? - ActiveSupport::Dependencies.explicitly_unloadable_constants << 'Houdini::V1' + ActiveSupport::Dependencies.explicitly_unloadable_constants << "Houdini::V1" - api_files = Dir[Rails.root.join('app', 'api', '**', '*.rb')] + api_files = Dir[Rails.root.join("app/api/**/*.rb")] api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do Rails.application.reload_routes! end diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index 3148b1f872..66d55896b0 100755 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -8,4 +8,4 @@ # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -Rails.application.config.secret_key_base = ENV.fetch('SECRET_TOKEN') +Rails.application.config.secret_key_base = ENV.fetch("SECRET_TOKEN") diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index abbdc30ae2..0f269f57b2 100755 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -2,4 +2,4 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.session_store :cookie_store, key: ENV['COOKIE_STORE_KEY'] || '_commitchange_session' +Rails.application.config.session_store :cookie_store, key: ENV["COOKIE_STORE_KEY"] || "_commitchange_session" diff --git a/config/initializers/stripe.rb b/config/initializers/stripe.rb index ec149d59e3..5a339d5283 100644 --- a/config/initializers/stripe.rb +++ b/config/initializers/stripe.rb @@ -2,10 +2,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'stripe' +require "stripe" -Stripe.api_version = '2017-06-05' +Stripe.api_version = "2017-06-05" -#Stripe.api_key = Houdini.payment_providers.stripe.stripe.private_key +# Stripe.api_key = Houdini.payment_providers.stripe.stripe.private_key -#Rails.application.config.Houdini.hoster.support_email = "support@email.com" +# Rails.application.config.Houdini.hoster.support_email = "support@email.com" diff --git a/config/initializers/time.rb b/config/initializers/time.rb index cf70be9f57..5d70f63a4e 100644 --- a/config/initializers/time.rb +++ b/config/initializers/time.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -ENV['TZ'] = 'UTC' -Time.zone = 'UTC' +ENV["TZ"] = "UTC" +Time.zone = "UTC" module Chronic def self.time_class diff --git a/config/initializers/zeitwerk.rb b/config/initializers/zeitwerk.rb index 570affd773..bec47a773e 100644 --- a/config/initializers/zeitwerk.rb +++ b/config/initializers/zeitwerk.rb @@ -4,8 +4,8 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE Rails.autoloaders.each do |autoloader| - autoloader.inflector.inflect( - 'uuid' => 'UUID', - 'html' => 'HTML' - ) + autoloader.inflector.inflect( + "uuid" => "UUID", + "html" => "HTML" + ) end diff --git a/config/puma.rb b/config/puma.rb index c015330523..c6b749073a 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -15,7 +15,7 @@ # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 5000 } +port ENV.fetch("PORT") { 5000 } # Specifies the `environment` that Puma will run in. # @@ -30,14 +30,14 @@ # Workers do not work on JRuby or Windows (both of which do not support # processes). # - workers ENV.fetch("WEB_CONCURRENCY") { 2 } if ENV['RAILS_ENV'] != 'development' +workers ENV.fetch("WEB_CONCURRENCY") { 2 } if ENV["RAILS_ENV"] != "development" # Use the `preload_app!` method when specifying a `workers` number. # This directive tells Puma to first boot the application and load code # before forking the application. This takes advantage of Copy On Write # process behavior so workers use less memory. # -preload_app! if ENV['RAILS_ENV'] != 'development' +preload_app! if ENV["RAILS_ENV"] != "development" # Allow puma to be restarted by `rails restart` command. plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb index 903da0a7eb..c7e9831e61 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,12 +4,12 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE Rails.application.routes.draw do # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html - require_relative "./state_code_constraint" - if Rails.env == 'development' - get '/button_debug/embedded' => 'button_debug#embedded' - get '/button_debug/button' => 'button_debug#button' - get '/button_debug/embedded/:id' => 'button_debug#embedded' - get '/button_debug/button/:id' => 'button_debug#button' + require_relative "state_code_constraint" + if Rails.env.development? + get "/button_debug/embedded" => "button_debug#embedded" + get "/button_debug/button" => "button_debug#button" + get "/button_debug/embedded/:id" => "button_debug#embedded" + get "/button_debug/button/:id" => "button_debug#button" end defaults format: :json do # they're APIs, you have to use JSON @@ -23,7 +23,7 @@ resources :events, only: [:show] do resources :ticket_levels, only: [:index, :show] end - resources :supporters, only: [:index, :show] do + resources :supporters, only: [:index, :show] do resources :supporter_addresses, only: [:index, :show] resources :supporter_notes, only: [:index, :show] end @@ -45,7 +45,7 @@ resources(:settings, only: [:index]) resources(:campaign_gifts, only: [:create]) resource(:cards, only: %i[create update destroy]) - resource(:direct_debit_details, path: 'sepa', controller: :direct_debit_details, only: [:create]) + resource(:direct_debit_details, path: "sepa", controller: :direct_debit_details, only: [:create]) # Creating presigned posts for direct-to-S3 upload resources(:aws_presigned_posts, only: [:create]) @@ -60,7 +60,7 @@ get(:donations_history, on: :member) end - namespace(:nonprofits, path: 'nonprofits/:nonprofit_id') do + namespace(:nonprofits, path: "nonprofits/:nonprofit_id") do resources(:payouts, only: %i[create index show]) resources(:imports, only: [:create]) resources(:nonprofit_keys, only: [:index]) do @@ -81,7 +81,7 @@ put(:followup, on: :member) post(:create_offsite, on: :collection) end - + resources(:charges, only: [:index]) do resources(:refunds, only: %i[create index]) end @@ -133,10 +133,10 @@ post(:send_code) end - post 'tracking', controller: 'trackings', action: 'create' + post "tracking", controller: "trackings", action: "create" end - namespace(:campaigns, path: '/nonprofits/:nonprofit_id/campaigns/:campaign_id/admin', only: []) do + namespace(:campaigns, path: "/nonprofits/:nonprofit_id/campaigns/:campaign_id/admin", only: []) do resources(:supporters, only: [:index]) resources(:donations, only: [:index]) resources(:campaign_gift_options, only: [:index]) @@ -197,7 +197,7 @@ get(:dashboard_metrics, on: :member) get(:payment_history, on: :member) - post(:donate, on: :member, as: 'create_donation') + post(:donate, on: :member, as: "create_donation") end resources(:recurring_donations, only: %i[edit destroy update]) do @@ -205,109 +205,109 @@ end devise_for :users, - controllers: { - sessions: 'users/sessions', - registrations: 'users/registrations', - confirmations: 'users/confirmations' - } + controllers: { + sessions: "users/sessions", + registrations: "users/registrations", + confirmations: "users/confirmations" + } devise_scope :user do - match '/sign_in' => 'users/sessions#new', via: %i[get post] - match '/signup' => 'devise/registrations#new', via: %i[get post] - post '/confirm' => 'users/confirmations#confirm', via: [:get] - match '/users/is_confirmed' => 'users/confirmations#is_confirmed', via: %i[get post] - match '/users/exists' => 'users/confirmations#exists', via: [:get] - post '/users/confirm_auth', action: :confirm_auth, controller: 'users/sessions', via: %i[get post] + match "/sign_in" => "users/sessions#new", :via => %i[get post] + match "/signup" => "devise/registrations#new", :via => %i[get post] + post "/confirm" => "users/confirmations#confirm", :via => [:get] + match "/users/is_confirmed" => "users/confirmations#is_confirmed", :via => %i[get post] + get "/users/exists" => "users/confirmations#exists" + post "/users/confirm_auth", action: :confirm_auth, controller: "users/sessions", via: %i[get post] end # Super admin - match '/admin' => 'super_admins#index', :as => 'admin', via: %i[get post] - match '/admin/search-nonprofits' => 'super_admins#search_nonprofits', via: %i[get post] - match '/admin/search-profiles' => 'super_admins#search_profiles', via: %i[get post] - match '/admin/search-fullcontact' => 'super_admins#search_fullcontact', via: %i[get post] - match '/admin/recurring-donations-without-cards' => 'super_admins#recurring_donations_without_cards', via: %i[get post] - match '/admin/export_supporters_with_rds' => 'super_admins#export_supporters_with_rds', via: %i[get post] - match '/admin/resend_user_confirmation' => 'super_admins#resend_user_confirmation', via: %i[get post] + match "/admin" => "super_admins#index", :as => "admin", :via => %i[get post] + match "/admin/search-nonprofits" => "super_admins#search_nonprofits", :via => %i[get post] + match "/admin/search-profiles" => "super_admins#search_profiles", :via => %i[get post] + match "/admin/search-fullcontact" => "super_admins#search_fullcontact", :via => %i[get post] + match "/admin/recurring-donations-without-cards" => "super_admins#recurring_donations_without_cards", :via => %i[get post] + match "/admin/export_supporters_with_rds" => "super_admins#export_supporters_with_rds", :via => %i[get post] + match "/admin/resend_user_confirmation" => "super_admins#resend_user_confirmation", :via => %i[get post] # GoodJob dashboard authenticate :user, ->(user) { user.super_admin? } do - mount GoodJob::Engine => 'good_job' + mount GoodJob::Engine => "good_job" end # Events - match '/events' => 'events#index', via: [:get] - match '/events/:event_slug' => 'events#show', via: %i[get post] + get "/events" => "events#index" + match "/events/:event_slug" => "events#show", :via => %i[get post] # Campaigns - match '/peer-to-peer' => 'campaigns#peer_to_peer', via: %i[get post] + match "/peer-to-peer" => "campaigns#peer_to_peer", :via => %i[get post] - scope ':state_code/:city/:name' do + scope ":state_code/:city/:name" do constraints StateCodeConstraint.new do # Nonprofits - match '' => 'nonprofits#show', :as => :nonprofit_location, via: %i[get post] - match 'donate' => 'nonprofits#donate', :as => :nonprofit_donation, via: %i[get post] - match 'button' => 'nonprofits/button#guided', via: %i[get post] + match "" => "nonprofits#show", :as => :nonprofit_location, :via => %i[get post] + match "donate" => "nonprofits#donate", :as => :nonprofit_donation, :via => %i[get post] + match "button" => "nonprofits/button#guided", :via => %i[get post] # Campaigns - match 'campaigns' => 'campaigns#index', via: %i[get post] - match 'campaigns/:campaign_slug' => 'campaigns#show', via: %i[get post], as: :campaign_location - match 'campaigns/:campaign_slug/supporters' => 'campaigns/supporters#index', via: %i[get post] + match "campaigns" => "campaigns#index", :via => %i[get post] + match "campaigns/:campaign_slug" => "campaigns#show", :via => %i[get post], :as => :campaign_location + match "campaigns/:campaign_slug/supporters" => "campaigns/supporters#index", :via => %i[get post] # Events - match 'events' => 'events#index', via: %i[get post] - match 'events/:event_slug' => 'events#show', via: %i[get post], as: :event_location - match 'events/:event_slug/stats' => 'events#stats', via: %i[get post] - match 'events/:event_slug/tickets' => 'tickets#index', via: %i[get post] + match "events" => "events#index", :via => %i[get post] + match "events/:event_slug" => "events#show", :via => %i[get post], :as => :event_location + match "events/:event_slug/stats" => "events#stats", :via => %i[get post] + match "events/:event_slug/tickets" => "tickets#index", :via => %i[get post] # Dashboard - match 'dashboard' => 'nonprofits#dashboard', as: :np_dashboard, via: %i[get post] + match "dashboard" => "nonprofits#dashboard", :as => :np_dashboard, :via => %i[get post] end end direct :campaign_locateable do |model, options| nonprofit = model.nonprofit route_for(:campaign_location, nonprofit.state_code_slug, nonprofit.city_slug, nonprofit.slug, - model.slug, options) + model.slug, options) end direct :event_locateable do |model, options| nonprofit = model.nonprofit - route_for(:event_location, nonprofit.state_code_slug, nonprofit.city_slug, + route_for(:event_location, nonprofit.state_code_slug, nonprofit.city_slug, nonprofit.slug, model.slug, options) end # Mailchimp Landing - match '/mailchimp-landing' => 'nonprofits/nonprofit_keys#mailchimp_landing', via: %i[get post] + match "/mailchimp-landing" => "nonprofits/nonprofit_keys#mailchimp_landing", :via => %i[get post] # Webhooks - post '/webhooks/stripe_subscription_payment' => 'webhooks#subscription_payment' - post '/webhooks/stripe' => 'webhooks#stripe' + post "/webhooks/stripe_subscription_payment" => "webhooks#subscription_payment" + post "/webhooks/stripe" => "webhooks#stripe" - get '/static/terms_and_privacy' => 'static#terms_and_privacy' - get '/static/ccs' => 'static#ccs' + get "/static/terms_and_privacy" => "static#terms_and_privacy" + get "/static/ccs" => "static#ccs" - get '/js/donate-button.v2.js' => 'widget#v2' - get '/js/i18n.js' => 'widget#i18n' - get '/css/donate-button.css' => 'widget#v1_css' - get '/css/donate-button.v2.css' => 'widget#v2_css' + get "/js/donate-button.v2.js" => "widget#v2" + get "/js/i18n.js" => "widget#i18n" + get "/css/donate-button.css" => "widget#v1_css" + get "/css/donate-button.v2.css" => "widget#v2_css" scope ActiveStorage.routes_prefix do - get "/blobs/redirect/:signed_id/*filename" => "active_storage/blobs/redirect#show", as: :rails_service_blob - get "/blobs/proxy/:signed_id/*filename" => "active_storage/blobs/proxy#show", as: :rails_service_blob_proxy + get "/blobs/redirect/:signed_id/*filename" => "active_storage/blobs/redirect#show", :as => :rails_service_blob + get "/blobs/proxy/:signed_id/*filename" => "active_storage/blobs/proxy#show", :as => :rails_service_blob_proxy get "/blobs/:signed_id/*filename" => "active_storage/blobs/redirect#show" - get "/representations/redirect/:signed_blob_id/:variation_key/*filename" => "active_storage/representations/redirect#show", as: :rails_blob_representation - get "/representations/proxy/:signed_blob_id/:variation_key/*filename" => "active_storage/representations/proxy#show", as: :rails_blob_representation_proxy + get "/representations/redirect/:signed_blob_id/:variation_key/*filename" => "active_storage/representations/redirect#show", :as => :rails_blob_representation + get "/representations/proxy/:signed_blob_id/:variation_key/*filename" => "active_storage/representations/proxy#show", :as => :rails_blob_representation_proxy get "/representations/:signed_blob_id/:variation_key/*filename" => "active_storage/representations/redirect#show" - get "/disk/:encoded_key/*filename" => "active_storage/disk#show", as: :rails_disk_service - put "/disk/:encoded_token" => "active_storage/disk#update", as: :update_rails_disk_service - post "/direct_uploads" => "direct_uploads#create", as: :rails_direct_uploads + get "/disk/:encoded_key/*filename" => "active_storage/disk#show", :as => :rails_disk_service + put "/disk/:encoded_token" => "active_storage/disk#update", :as => :update_rails_disk_service + post "/direct_uploads" => "direct_uploads#create", :as => :rails_direct_uploads end direct :rails_representation do |representation, options| signed_blob_id = representation.blob.signed_id - variation_key = representation.variation.key - filename = representation.blob.filename + variation_key = representation.variation.key + filename = representation.blob.filename route_for(:rails_blob_representation, signed_blob_id, variation_key, filename, options) end @@ -320,7 +320,7 @@ route_for(:rails_service_blob, blob.signed_id, blob.filename, options) end - resolve("ActiveStorage::Blob") { |blob, options| route_for(ActiveStorage.resolve_model_to_route, blob, options) } + resolve("ActiveStorage::Blob") { |blob, options| route_for(ActiveStorage.resolve_model_to_route, blob, options) } resolve("ActiveStorage::Attachment") { |attachment, options| route_for(ActiveStorage.resolve_model_to_route, attachment.blob, options) } direct :rails_storage_proxy do |model, options| @@ -333,8 +333,8 @@ ) else signed_blob_id = model.blob.signed_id - variation_key = model.variation.key - filename = model.blob.filename + variation_key = model.variation.key + filename = model.blob.filename route_for( :rails_blob_representation_proxy, @@ -356,8 +356,8 @@ ) else signed_blob_id = model.blob.signed_id - variation_key = model.variation.key - filename = model.blob.filename + variation_key = model.variation.key + filename = model.blob.filename route_for( :rails_blob_representation, @@ -368,5 +368,5 @@ ) end end - root to: 'front#index' -end \ No newline at end of file + root to: "front#index" +end diff --git a/config/state_code_constraint.rb b/config/state_code_constraint.rb index 64402218ba..cd2b14ebdb 100755 --- a/config/state_code_constraint.rb +++ b/config/state_code_constraint.rb @@ -6,4 +6,4 @@ class StateCodeConstraint def matches?(request) ISO3166::Country[:US].subdivisions.has_key? request.params[:state_code].upcase end -end \ No newline at end of file +end diff --git a/db/migrate/20210105192022_create_active_storage_variant_records.active_storage.rb b/db/migrate/20210105192022_create_active_storage_variant_records.active_storage.rb index a2862695e1..fb6e2b0175 100644 --- a/db/migrate/20210105192022_create_active_storage_variant_records.active_storage.rb +++ b/db/migrate/20210105192022_create_active_storage_variant_records.active_storage.rb @@ -5,7 +5,7 @@ def change t.belongs_to :blob, null: false, index: false t.string :variation_digest, null: false - t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true + t.index %i[blob_id variation_digest], name: "index_active_storage_variant_records_uniqueness", unique: true t.foreign_key :active_storage_blobs, column: :blob_id end end diff --git a/db/migrate/20210122203303_create_ticket_purchases.rb b/db/migrate/20210122203303_create_ticket_purchases.rb index 3852e99038..fdb7157776 100644 --- a/db/migrate/20210122203303_create_ticket_purchases.rb +++ b/db/migrate/20210122203303_create_ticket_purchases.rb @@ -11,7 +11,7 @@ def change create_table :transaction_assignments, id: :string do |t| t.references :transaction, foreign_key: true, type: :string, null: false - t.references :assignable, polymorphic: true, type: :string, index: { unique: true }, null: false + t.references :assignable, polymorphic: true, type: :string, index: {unique: true}, null: false end end end diff --git a/db/migrate/20210208211655_create_campaign_gift_purchases.rb b/db/migrate/20210208211655_create_campaign_gift_purchases.rb index de23afaed0..26c5cc35bd 100644 --- a/db/migrate/20210208211655_create_campaign_gift_purchases.rb +++ b/db/migrate/20210208211655_create_campaign_gift_purchases.rb @@ -1,6 +1,6 @@ class CreateCampaignGiftPurchases < ActiveRecord::Migration[6.1] def change - create_table :campaign_gift_purchases, id: :string do |t| + create_table :campaign_gift_purchases, id: :string do |t| t.boolean :deleted, null: false, default: false t.integer :amount, null: false t.references :campaign, foreign_key: true diff --git a/db/migrate/20210209174657_remove_is_valid_json_function.rb b/db/migrate/20210209174657_remove_is_valid_json_function.rb index 5f1bd1acb6..75e02deb84 100644 --- a/db/migrate/20210209174657_remove_is_valid_json_function.rb +++ b/db/migrate/20210209174657_remove_is_valid_json_function.rb @@ -10,17 +10,17 @@ def up end def down - execute <<-SQL - CREATE FUNCTION public.is_valid_json(p_json text) RETURNS boolean - LANGUAGE plpgsql IMMUTABLE - AS $$ -begin - return (p_json::json is not null); -exception - when others then - return false; -end; -$$; + execute <<~SQL + CREATE FUNCTION public.is_valid_json(p_json text) RETURNS boolean + LANGUAGE plpgsql IMMUTABLE + AS $$ + begin + return (p_json::json is not null); + exception + when others then + return false; + end; + $$; SQL end end diff --git a/db/migrate/20210209181808_drop_update_supporter_assoc_search_vectors_function.rb b/db/migrate/20210209181808_drop_update_supporter_assoc_search_vectors_function.rb index 2c7b055425..8f1a93a16d 100644 --- a/db/migrate/20210209181808_drop_update_supporter_assoc_search_vectors_function.rb +++ b/db/migrate/20210209181808_drop_update_supporter_assoc_search_vectors_function.rb @@ -10,41 +10,41 @@ def up end def down - execute <<-SQL - CREATE FUNCTION public.update_supporter_assoc_search_vectors() RETURNS trigger - LANGUAGE plpgsql - AS $$ BEGIN - IF pg_trigger_depth() <> 1 THEN RETURN new; END IF; - UPDATE supporters - SET search_vectors=to_tsvector('english', data.search_blob) - FROM ( -SELECT supporters.id, concat_ws(' ' - , custom_field_joins.value - , supporters.name - , supporters.organization - , supporters.id - , supporters.email - , supporters.city - , supporters.state_code - , donations.designation - , donations.dedication - , payments.kind - , payments.towards - ) AS search_blob -FROM supporters -LEFT OUTER JOIN payments - ON payments.supporter_id=supporters.id -LEFT OUTER JOIN donations - ON donations.supporter_id=supporters.id -LEFT OUTER JOIN ( -SELECT string_agg(value::text, ' ') AS value, supporter_id -FROM custom_field_joins -GROUP BY supporter_id) AS custom_field_joins - ON custom_field_joins.supporter_id=supporters.id -WHERE (supporters.id=NEW.supporter_id)) AS data - WHERE data.id=supporters.id; - RETURN new; - END $$; + execute <<~SQL + CREATE FUNCTION public.update_supporter_assoc_search_vectors() RETURNS trigger + LANGUAGE plpgsql + AS $$ BEGIN + IF pg_trigger_depth() <> 1 THEN RETURN new; END IF; + UPDATE supporters + SET search_vectors=to_tsvector('english', data.search_blob) + FROM ( + SELECT supporters.id, concat_ws(' ' + , custom_field_joins.value + , supporters.name + , supporters.organization + , supporters.id + , supporters.email + , supporters.city + , supporters.state_code + , donations.designation + , donations.dedication + , payments.kind + , payments.towards + ) AS search_blob + FROM supporters + LEFT OUTER JOIN payments + ON payments.supporter_id=supporters.id + LEFT OUTER JOIN donations + ON donations.supporter_id=supporters.id + LEFT OUTER JOIN ( + SELECT string_agg(value::text, ' ') AS value, supporter_id + FROM custom_field_joins + GROUP BY supporter_id) AS custom_field_joins + ON custom_field_joins.supporter_id=supporters.id + WHERE (supporters.id=NEW.supporter_id)) AS data + WHERE data.id=supporters.id; + RETURN new; + END $$; SQL end end diff --git a/db/migrate/20210217225909_create_good_jobs.rb b/db/migrate/20210217225909_create_good_jobs.rb index ce7664d109..33ed9d96e7 100644 --- a/db/migrate/20210217225909_create_good_jobs.rb +++ b/db/migrate/20210217225909_create_good_jobs.rb @@ -1,6 +1,6 @@ class CreateGoodJobs < ActiveRecord::Migration[6.1] def change - enable_extension 'pgcrypto' + enable_extension "pgcrypto" create_table :good_jobs, id: :uuid do |t| t.text :queue_name diff --git a/db/migrate/20210329213633_add_subtransaction_hierarchy.rb b/db/migrate/20210329213633_add_subtransaction_hierarchy.rb index 170540958e..a51e4bf9c7 100644 --- a/db/migrate/20210329213633_add_subtransaction_hierarchy.rb +++ b/db/migrate/20210329213633_add_subtransaction_hierarchy.rb @@ -7,7 +7,7 @@ def change create_table :subtransactions, id: :string do |t| t.references :transaction, foreign_key: true, type: :string, null: false t.references :subtransactable, polymorphic: true, type: :string, null: false, index: {unique: true} - t.datetime "created", comment: 'the moment that the subtransaction was created. Could be earlier than created_at if the transaction was in the past.' + t.datetime "created", comment: "the moment that the subtransaction was created. Could be earlier than created_at if the transaction was in the past." t.timestamps end @@ -19,7 +19,7 @@ def change create_table :subtransaction_payments, id: :string do |t| t.references :subtransaction, type: :string, foreign_key: true t.references :paymentable, polymorphic: true, type: :string - t.datetime "created", comment: 'the moment that the subtransaction_payment was created. Could be earlier than created_at if the transaction was in the past.' + t.datetime "created", comment: "the moment that the subtransaction_payment was created. Could be earlier than created_at if the transaction was in the past." t.timestamps end diff --git a/db/migrate/20210412172433_create_offline_transaction_refunds.rb b/db/migrate/20210412172433_create_offline_transaction_refunds.rb index bfa4549755..e1f5324292 100644 --- a/db/migrate/20210412172433_create_offline_transaction_refunds.rb +++ b/db/migrate/20210412172433_create_offline_transaction_refunds.rb @@ -5,7 +5,7 @@ class CreateOfflineTransactionRefunds < ActiveRecord::Migration[6.1] def change create_table :offline_transaction_refunds, id: :string do |t| - t.references :payment, foreign_key:true + t.references :payment, foreign_key: true t.timestamps end diff --git a/db/migrate/20210506172332_create_stripe_transactions.rb b/db/migrate/20210506172332_create_stripe_transactions.rb index 0912356f9a..44d15faf3b 100644 --- a/db/migrate/20210506172332_create_stripe_transactions.rb +++ b/db/migrate/20210506172332_create_stripe_transactions.rb @@ -1,7 +1,7 @@ class CreateStripeTransactions < ActiveRecord::Migration[6.1] def change create_table :stripe_transactions, id: :string do |t| - t.integer :amount, null:false + t.integer :amount, null: false t.timestamps end diff --git a/db/migrate/20210513211918_create_stripe_refunds.rb b/db/migrate/20210513211918_create_stripe_refunds.rb index 974ea83cc4..2ef4fab477 100644 --- a/db/migrate/20210513211918_create_stripe_refunds.rb +++ b/db/migrate/20210513211918_create_stripe_refunds.rb @@ -2,7 +2,7 @@ class CreateStripeRefunds < ActiveRecord::Migration[6.1] def change create_table :stripe_refunds, id: :string do |t| t.references :payment, foreign_key: true, id: :string - + t.timestamps end end diff --git a/db/migrate/20210602220525_create_recurrences.rb b/db/migrate/20210602220525_create_recurrences.rb index 62fa0cccc9..8ad08e6930 100644 --- a/db/migrate/20210602220525_create_recurrences.rb +++ b/db/migrate/20210602220525_create_recurrences.rb @@ -1,10 +1,10 @@ class CreateRecurrences < ActiveRecord::Migration[6.1] def change - create_table :recurrences, id: :string do |t| + create_table :recurrences, id: :string do |t| t.integer "amount", null: false t.references :recurring_donation, foreign_key: true, null: false t.references :supporter, foreign_key: true, null: false, id: :string - t.datetime "start_date", comment: 'the moment that the recurrence should start. Could be earlier than created_at if this was imported.' + t.datetime "start_date", comment: "the moment that the recurrence should start. Could be earlier than created_at if this was imported." t.timestamps end end diff --git a/db/migrate/20210925171712_change_tag_masters_to_tag_definitions.rb b/db/migrate/20210925171712_change_tag_masters_to_tag_definitions.rb index 97059b3210..ac0508e298 100644 --- a/db/migrate/20210925171712_change_tag_masters_to_tag_definitions.rb +++ b/db/migrate/20210925171712_change_tag_masters_to_tag_definitions.rb @@ -14,6 +14,6 @@ def change rename_column :tag_joins_backup, :tag_master_id, :tag_definition_id add_index :tag_joins, :tag_definition_id - add_index :tag_joins, %i(tag_definition_id supporter_id), unique: true + add_index :tag_joins, %i[tag_definition_id supporter_id], unique: true end end diff --git a/db/migrate/20211101214501_remove_stripe_subscription_id_from_billing_subscription.rb b/db/migrate/20211101214501_remove_stripe_subscription_id_from_billing_subscription.rb index 8a23cebbd5..e411ea607f 100644 --- a/db/migrate/20211101214501_remove_stripe_subscription_id_from_billing_subscription.rb +++ b/db/migrate/20211101214501_remove_stripe_subscription_id_from_billing_subscription.rb @@ -4,6 +4,6 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class RemoveStripeSubscriptionIdFromBillingSubscription < ActiveRecord::Migration[6.1] def change - remove_column :billing_subscriptions, :stripe_subscription_id + remove_column :billing_subscriptions, :stripe_subscription_id end end diff --git a/db/migrate/20220427052418_add_active_job_id_concurrency_key_cron_key_to_good_jobs.rb b/db/migrate/20220427052418_add_active_job_id_concurrency_key_cron_key_to_good_jobs.rb index 6c1b08b147..e6b07beaf6 100644 --- a/db/migrate/20220427052418_add_active_job_id_concurrency_key_cron_key_to_good_jobs.rb +++ b/db/migrate/20220427052418_add_active_job_id_concurrency_key_cron_key_to_good_jobs.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class AddActiveJobIdConcurrencyKeyCronKeyToGoodJobs < ActiveRecord::Migration[5.2] def change reversible do |dir| diff --git a/db/migrate/20220427052419_add_active_job_id_index_and_concurrency_key_index_to_good_jobs.rb b/db/migrate/20220427052419_add_active_job_id_index_and_concurrency_key_index_to_good_jobs.rb index 3d8a018216..794c63d8fa 100644 --- a/db/migrate/20220427052419_add_active_job_id_index_and_concurrency_key_index_to_good_jobs.rb +++ b/db/migrate/20220427052419_add_active_job_id_index_and_concurrency_key_index_to_good_jobs.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class AddActiveJobIdIndexAndConcurrencyKeyIndexToGoodJobs < ActiveRecord::Migration[5.2] disable_ddl_transaction! diff --git a/db/migrate/20220427052420_add_retried_good_job_id_to_good_jobs.rb b/db/migrate/20220427052420_add_retried_good_job_id_to_good_jobs.rb index 3d7f4cca4b..743740887b 100644 --- a/db/migrate/20220427052420_add_retried_good_job_id_to_good_jobs.rb +++ b/db/migrate/20220427052420_add_retried_good_job_id_to_good_jobs.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class AddRetriedGoodJobIdToGoodJobs < ActiveRecord::Migration[5.2] def change reversible do |dir| diff --git a/db/migrate/20220713192154_add_modern_achievements.rb b/db/migrate/20220713192154_add_modern_achievements.rb index f778121bf2..b442a47cda 100644 --- a/db/migrate/20220713192154_add_modern_achievements.rb +++ b/db/migrate/20220713192154_add_modern_achievements.rb @@ -6,13 +6,13 @@ class AddModernAchievements < ActiveRecord::Migration[6.1] module TemporaryConcern extend ActiveSupport::Concern - included do + included do serialize :achievements, Array serialize :categories, Array end end - def change + def change add_column :nonprofits, :achievements_json, :jsonb add_column :nonprofits, :categories_json, :jsonb @@ -23,15 +23,15 @@ def change np.achievements_json = np.achievements unless np.save puts "NP ##{np.id} could not be saved" - np.save(validate:false) + np.save(validate: false) end np.reload - + raise "NP ##{np.id} does not have identical values" if np.achievements_json != np.achievements end end end - + rename_column :nonprofits, :achievements, :achievements_legacy rename_column :nonprofits, :categories, :categories_legacy diff --git a/db/migrate/20220805212521_add_cron_at_to_good_jobs.rb b/db/migrate/20220805212521_add_cron_at_to_good_jobs.rb index e7c7a37028..d926c17e8d 100644 --- a/db/migrate/20220805212521_add_cron_at_to_good_jobs.rb +++ b/db/migrate/20220805212521_add_cron_at_to_good_jobs.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class AddCronAtToGoodJobs < ActiveRecord::Migration[6.1] def change reversible do |dir| diff --git a/db/migrate/20220805212522_add_cron_key_cron_at_index_to_good_jobs.rb b/db/migrate/20220805212522_add_cron_key_cron_at_index_to_good_jobs.rb index 5a0991371c..7a9b8ad880 100644 --- a/db/migrate/20220805212522_add_cron_key_cron_at_index_to_good_jobs.rb +++ b/db/migrate/20220805212522_add_cron_key_cron_at_index_to_good_jobs.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class AddCronKeyCronAtIndexToGoodJobs < ActiveRecord::Migration[6.1] disable_ddl_transaction! @@ -12,9 +13,9 @@ def change end add_index :good_jobs, - [:cron_key, :cron_at], - algorithm: :concurrently, - name: :index_good_jobs_on_cron_key_and_cron_at, - unique: true + [:cron_key, :cron_at], + algorithm: :concurrently, + name: :index_good_jobs_on_cron_key_and_cron_at, + unique: true end end diff --git a/db/migrate/20220805212523_create_good_job_processes.rb b/db/migrate/20220805212523_create_good_job_processes.rb index 8ea603f6f9..1490c2ef01 100644 --- a/db/migrate/20220805212523_create_good_job_processes.rb +++ b/db/migrate/20220805212523_create_good_job_processes.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class CreateGoodJobProcesses < ActiveRecord::Migration[6.1] def change reversible do |dir| diff --git a/db/migrate/20220805212524_index_good_job_jobs_on_finished_at.rb b/db/migrate/20220805212524_index_good_job_jobs_on_finished_at.rb index 9ca9997be2..32821f458f 100644 --- a/db/migrate/20220805212524_index_good_job_jobs_on_finished_at.rb +++ b/db/migrate/20220805212524_index_good_job_jobs_on_finished_at.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class IndexGoodJobJobsOnFinishedAt < ActiveRecord::Migration[6.1] disable_ddl_transaction! @@ -12,14 +13,14 @@ def change end add_index :good_jobs, - [:active_job_id], - name: :index_good_jobs_on_active_job_id, - algorithm: :concurrently + [:active_job_id], + name: :index_good_jobs_on_active_job_id, + algorithm: :concurrently add_index :good_jobs, - [:finished_at], - where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", - name: :index_good_jobs_jobs_on_finished_at, - algorithm: :concurrently + [:finished_at], + where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", + name: :index_good_jobs_jobs_on_finished_at, + algorithm: :concurrently end end diff --git a/db/migrate/20230404172827_create_good_job_settings.rb b/db/migrate/20230404172827_create_good_job_settings.rb index a9b881fe01..4ef9a6fbb7 100644 --- a/db/migrate/20230404172827_create_good_job_settings.rb +++ b/db/migrate/20230404172827_create_good_job_settings.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class CreateGoodJobSettings < ActiveRecord::Migration[6.1] def change reversible do |dir| diff --git a/db/migrate/20230404172828_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb b/db/migrate/20230404172828_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb index c94a26b41a..50beaa9f2c 100644 --- a/db/migrate/20230404172828_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb +++ b/db/migrate/20230404172828_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class CreateIndexGoodJobsJobsOnPriorityCreatedAtWhenUnfinished < ActiveRecord::Migration[6.1] disable_ddl_transaction! @@ -11,7 +12,7 @@ def change end end - add_index :good_jobs, [:priority, :created_at], order: { priority: "DESC NULLS LAST", created_at: :asc }, + add_index :good_jobs, [:priority, :created_at], order: {priority: "DESC NULLS LAST", created_at: :asc}, where: "finished_at IS NULL", name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished, algorithm: :concurrently end diff --git a/db/migrate/20230404172829_create_good_job_batches.rb b/db/migrate/20230404172829_create_good_job_batches.rb index b18dcf64c3..da118eb255 100644 --- a/db/migrate/20230404172829_create_good_job_batches.rb +++ b/db/migrate/20230404172829_create_good_job_batches.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class CreateGoodJobBatches < ActiveRecord::Migration[6.1] def change reversible do |dir| diff --git a/db/migrate/20230611211704_create_good_job_executions.rb b/db/migrate/20230611211704_create_good_job_executions.rb index 0a2756974b..864305d0cf 100644 --- a/db/migrate/20230611211704_create_good_job_executions.rb +++ b/db/migrate/20230611211704_create_good_job_executions.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class CreateGoodJobExecutions < ActiveRecord::Migration[6.1] def change reversible do |dir| diff --git a/db/seeds.rb b/db/seeds.rb index 03a24f1429..5ad4a088d7 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE bp = BillingPlan.new -bp.name = 'Default billing plan' +bp.name = "Default billing plan" bp.amount = 0 bp.percentage_fee = 0 bp.save! diff --git a/gemfiles/rubocop.gemfile b/gemfiles/rubocop.gemfile index f2f9efa2d1..78afe23797 100644 --- a/gemfiles/rubocop.gemfile +++ b/gemfiles/rubocop.gemfile @@ -1,12 +1,11 @@ source "https://rubygems.org" do gem "standard", "~> 1.28" - + gem "standard-rails" - + gem "rubocop-rspec" gem "rubocop-factory_bot" - + gem "rubocop-rake" - end diff --git a/gems/bess/Gemfile b/gems/bess/Gemfile index 09e2a8e23a..1e877e59eb 100644 --- a/gems/bess/Gemfile +++ b/gems/bess/Gemfile @@ -1,6 +1,6 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" # Specify your gem's dependencies in bess.gemspec gemspec diff --git a/gems/bess/Rakefile b/gems/bess/Rakefile index f3e4726646..8c4059653d 100644 --- a/gems/bess/Rakefile +++ b/gems/bess/Rakefile @@ -9,27 +9,27 @@ load "rails/tasks/statistics.rake" require "bundler/gem_tasks" begin - require 'bundler/gem_tasks' + require "bundler/gem_tasks" rescue LoadError nil end -require 'rubygems' -require 'bundler' -require 'rdoc/task' +require "rubygems" +require "bundler" +require "rdoc/task" begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + warn e.message + warn "Run `bundle install` to install missing gems" exit e.status_code end -require 'rake' +require "rake" -require 'rspec/core' -require 'rspec/core/rake_task' +require "rspec/core" +require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] + spec.pattern = FileList["spec/**/*_spec.rb"] end -task :default => :spec +task default: :spec diff --git a/gems/bess/bess.gemspec b/gems/bess/bess.gemspec index 4d9c92561f..8cc0deb795 100644 --- a/gems/bess/bess.gemspec +++ b/gems/bess/bess.gemspec @@ -1,14 +1,14 @@ require_relative "lib/bess/version" Gem::Specification.new do |spec| - spec.name = "bess" - spec.version = Bess::VERSION - spec.authors = [""] - spec.email = ["eric@commitchange.com"] - spec.homepage = "https://houdiniproject.org" - spec.summary = "Support library for Houdini" + spec.name = "bess" + spec.version = Bess::VERSION + spec.authors = [""] + spec.email = ["eric@commitchange.com"] + spec.homepage = "https://houdiniproject.org" + spec.summary = "Support library for Houdini" spec.description = "Support library for Houdini" - spec.license = "AGPL-3.0-or-later WITH WTO-AP-3.0-or-later" + spec.license = "AGPL-3.0-or-later WITH WTO-AP-3.0-or-later" spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "https://github.com/houdiniproject/houdini" @@ -16,13 +16,11 @@ Gem::Specification.new do |spec| spec.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "AGPL-3.0.txt", "GPL-3.0.txt", "LGPL-3.0.txt", "Rakefile", "README.md"] spec.add_dependency "rails", "~> 6.1.3" - spec.add_dependency 'wisper', '~> 2.0' - spec.add_dependency 'wisper-activejob', '~> 1.0.0' - spec.add_dependency 'rest-client' - - spec.add_development_dependency 'rspec', '~> 3.13.0' - spec.add_development_dependency 'rspec-rails', '~> 4.0.0' - spec.add_development_dependency "concurrent-ruby", "1.3.4" # until Rails 7.1 becuase of the regression in concurrent-ruby - + spec.add_dependency "wisper", "~> 2.0" + spec.add_dependency "wisper-activejob", "~> 1.0.0" + spec.add_dependency "rest-client" + spec.add_development_dependency "rspec", "~> 3.13.0" + spec.add_development_dependency "rspec-rails", "~> 4.0.0" + spec.add_development_dependency "concurrent-ruby", "1.3.4" end diff --git a/gems/bess/bin/rails b/gems/bess/bin/rails index ad2ed1cd4f..60c4845f1b 100755 --- a/gems/bess/bin/rails +++ b/gems/bess/bin/rails @@ -2,26 +2,25 @@ # This command will automatically be run when you run "rails" with Rails gems # installed from the root of your application. -ENGINE_ROOT = File.expand_path('..', __dir__) -ENGINE_PATH = File.expand_path('../lib/houdini/engine', __dir__) +ENGINE_ROOT = File.expand_path("..", __dir__) +ENGINE_PATH = File.expand_path("../lib/houdini/engine", __dir__) # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) require "rails" # Pick the frameworks you want -#require "active_model/railtie" - -#require "active_job/railtie" -#require "active_record/railtie" -#require "active_storage/engine" # required because, bizarrely ActiveSupport doesn't work -#require "action_controller/railtie" -#require "action_mailer/railtie" -#require "action_view/railtie" -#require "action_cable/engine" -#require "sprockets/railtie" +# require "active_model/railtie" +# require "active_job/railtie" +# require "active_record/railtie" +# require "active_storage/engine" # required because, bizarrely ActiveSupport doesn't work +# require "action_controller/railtie" +# require "action_mailer/railtie" +# require "action_view/railtie" +# require "action_cable/engine" +# require "sprockets/railtie" require "rails/engine/commands" diff --git a/gems/bess/bin/rspec b/gems/bess/bin/rspec index a6c78521d3..4305353def 100755 --- a/gems/bess/bin/rspec +++ b/gems/bess/bin/rspec @@ -15,7 +15,7 @@ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", bundle_binstub = File.expand_path("../bundle", __FILE__) if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. diff --git a/gems/bess/lib/bess.rb b/gems/bess/lib/bess.rb index 4c3f90552a..5a1bc2b142 100644 --- a/gems/bess/lib/bess.rb +++ b/gems/bess/lib/bess.rb @@ -2,4 +2,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative './houdini' +require_relative "houdini" diff --git a/gems/bess/lib/bess/version.rb b/gems/bess/lib/bess/version.rb index a6e6d26a1a..2fd5dee4f2 100644 --- a/gems/bess/lib/bess/version.rb +++ b/gems/bess/lib/bess/version.rb @@ -3,5 +3,5 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Bess - VERSION = '0.1.0' + VERSION = "0.1.0" end diff --git a/gems/bess/lib/generators/react/component_generator.rb b/gems/bess/lib/generators/react/component_generator.rb index bb276b2e57..cfa47bbe5f 100644 --- a/gems/bess/lib/generators/react/component_generator.rb +++ b/gems/bess/lib/generators/react/component_generator.rb @@ -4,10 +4,10 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # from: https://github.com/reactjs/react-rails/blob/master/lib/generators/react/component_generator.rb module React - module Generators - class ComponentGenerator < ::Rails::Generators::NamedBase - source_root File.expand_path '../../templates', __FILE__ - desc <<-DESC.strip_heredoc + module Generators + class ComponentGenerator < ::Rails::Generators::NamedBase + source_root File.expand_path "../../templates", __FILE__ + desc <<~DESC Description: Scaffold a React component into `components/` of your Webpacker source or asset pipeline. The generated component will include a basic render function and a PropTypes @@ -40,212 +40,210 @@ class ComponentGenerator < ::Rails::Generators::NamedBase rails g react:component restaurant name:string rating:number owner:instanceOf{Person} rails g react:component food 'kind:oneOf{meat,cheese,vegetable}' rails g react:component events 'location:oneOfType{string,Restaurant}' - DESC - - argument :attributes, - :type => :array, - :default => [], - :banner => 'field[:type] field[:type] ...' - - class_option :ts, - type: :boolean, - default: true, - desc: 'Output tsx class based component' - - REACT_PROP_TYPES = { - 'node' => 'PropTypes.node', - 'bool' => 'PropTypes.bool', - 'boolean' => 'PropTypes.bool', - 'string' => 'PropTypes.string', - 'number' => 'PropTypes.number', - 'object' => 'PropTypes.object', - 'array' => 'PropTypes.array', - 'shape' => 'PropTypes.shape({})', - 'element' => 'PropTypes.element', - 'func' => 'PropTypes.func', - 'function' => 'PropTypes.func', - 'any' => 'PropTypes.any', - - 'instanceOf' => ->(type) { - 'PropTypes.instanceOf(%s)' % type.to_s.camelize - }, - - 'oneOf' => ->(*options) { - enums = options.map{ |k| "'#{k.to_s}'" }.join(',') - 'PropTypes.oneOf([%s])' % enums - }, - - 'oneOfType' => ->(*options) { - types = options.map{ |k| "#{lookup(k.to_s, k.to_s)}" }.join(',') - 'PropTypes.oneOfType([%s])' % types - } + DESC + + argument :attributes, + type: :array, + default: [], + banner: "field[:type] field[:type] ..." + + class_option :ts, + type: :boolean, + default: true, + desc: "Output tsx class based component" + + REACT_PROP_TYPES = { + "node" => "PropTypes.node", + "bool" => "PropTypes.bool", + "boolean" => "PropTypes.bool", + "string" => "PropTypes.string", + "number" => "PropTypes.number", + "object" => "PropTypes.object", + "array" => "PropTypes.array", + "shape" => "PropTypes.shape({})", + "element" => "PropTypes.element", + "func" => "PropTypes.func", + "function" => "PropTypes.func", + "any" => "PropTypes.any", + + "instanceOf" => ->(type) { + "PropTypes.instanceOf(%s)" % type.to_s.camelize + }, + + "oneOf" => ->(*options) { + enums = options.map { |k| "'#{k}'" }.join(",") + "PropTypes.oneOf([%s])" % enums + }, + + "oneOfType" => ->(*options) { + types = options.map { |k| "#{lookup(k.to_s, k.to_s)}" }.join(",") + "PropTypes.oneOfType([%s])" % types } - - TYPESCRIPT_TYPES = { - 'node' => 'React.ReactNode', - 'bool' => 'boolean', - 'boolean' => 'boolean', - 'string' => 'string', - 'number' => 'number', - 'object' => 'object', - 'array' => 'Array', - 'shape' => 'object', - 'element' => 'object', - 'func' => 'object', - 'function' => 'object', - 'any' => 'any', - - 'instanceOf' => ->(type) { - type.to_s.camelize - }, - - 'oneOf' => ->(*opts) { - opts.map{ |k| "'#{k.to_s}'" }.join(" | ") - }, - - 'oneOfType' => ->(*opts) { - opts.map{ |k| "#{ts_lookup(k.to_s, k.to_s)}" }.join(" | ") - } + } + + TYPESCRIPT_TYPES = { + "node" => "React.ReactNode", + "bool" => "boolean", + "boolean" => "boolean", + "string" => "string", + "number" => "number", + "object" => "object", + "array" => "Array", + "shape" => "object", + "element" => "object", + "func" => "object", + "function" => "object", + "any" => "any", + + "instanceOf" => ->(type) { + type.to_s.camelize + }, + + "oneOf" => ->(*opts) { + opts.map { |k| "'#{k}'" }.join(" | ") + }, + + "oneOfType" => ->(*opts) { + opts.map { |k| "#{ts_lookup(k.to_s, k.to_s)}" }.join(" | ") } - - def create_component_file - template_extension = if options[:coffee] - 'js.jsx.coffee' + } + + def create_component_file + template_extension = if options[:coffee] + "js.jsx.coffee" + elsif options[:ts] + "js.jsx.tsx.erb" + elsif options[:es6] || webpacker? + "es6.jsx" + else + "js.jsx" + end + + # Prefer webpacker to sprockets: + if webpacker? + new_file_name = file_name.camelize + extension = if options[:coffee] + "coffee" elsif options[:ts] - 'js.jsx.tsx.erb' - elsif options[:es6] || webpacker? - 'es6.jsx' + "tsx" else - 'js.jsx' + "js" end - - # Prefer webpacker to sprockets: - if webpacker? - new_file_name = file_name.camelize - extension = if options[:coffee] - 'coffee' - elsif options[:ts] - 'tsx' - else - 'js' - end - target_dir = webpack_configuration.source_path - .join('components') - .relative_path_from(::Rails.root) - .to_s - else - new_file_name = file_name - extension = template_extension - target_dir = 'app/assets/javascripts/components' - end - - file_path = File.join(target_dir, class_path, "#{new_file_name}.#{extension}") - template("component.#{template_extension}", file_path) + target_dir = webpack_configuration.source_path + .join("components") + .relative_path_from(::Rails.root) + .to_s + else + new_file_name = file_name + extension = template_extension + target_dir = "app/assets/javascripts/components" end - - private - - def webpack_configuration - Webpacker.respond_to?(:config) ? Webpacker.config : Webpacker::Configuration + + file_path = File.join(target_dir, class_path, "#{new_file_name}.#{extension}") + template("component.#{template_extension}", file_path) + end + + private + + def webpack_configuration + Webpacker.respond_to?(:config) ? Webpacker.config : Webpacker::Configuration + end + + def component_name + file_name.camelize + end + + def file_header + if webpacker? + return %(import * as React from "react"\n) if options[:ts] + %(import React from "react"\nimport PropTypes from "prop-types"\n) + else + "" end - - def component_name - file_name.camelize + end + + def file_footer + if webpacker? + %(export default #{component_name}) + else + "" end - - def file_header - if webpacker? - return %|import * as React from "react"\n| if options[:ts] - %|import React from "react"\nimport PropTypes from "prop-types"\n| + end + + def webpacker? + defined?(Webpacker) + end + + def parse_attributes! + self.attributes = (attributes || []).map do |attr| + args = "" + args_regex = /(?{.*})/ + + name, type = attr.split(":") + + if matchdata = args_regex.match(type) + args = matchdata[:args] + type = type.gsub(args_regex, "") + end + + if options[:ts] + {name: name, type: ts_lookup(name, type, args), union: union?(args)} else - '' + {name: name, type: lookup(type, args)} end end - - def file_footer - if webpacker? - %|export default #{component_name}| + end + + def union?(args = "") + args.to_s.gsub(/[{}]/, "").split(",").count > 1 + end + + def self.ts_lookup(name, type = "node", args = "") + ts_type = TYPESCRIPT_TYPES[type] + if ts_type.blank? + ts_type = if /^[[:upper:]]/.match?(type) + TYPESCRIPT_TYPES["instanceOf"] else - '' + TYPESCRIPT_TYPES["node"] end end - - def webpacker? - defined?(Webpacker) - end - - def parse_attributes! - self.attributes = (attributes || []).map do |attr| - name = '' - type = '' - args = '' - args_regex = /(?{.*})/ - - name, type = attr.split(':') - - if matchdata = args_regex.match(type) - args = matchdata[:args] - type = type.gsub(args_regex, '') - end - - if options[:ts] - { :name => name, :type => ts_lookup(name, type, args), :union => union?(args) } - else - { :name => name, :type => lookup(type, args) } - end + + args = args.to_s.gsub(/[{}]/, "").split(",") + + if ts_type.respond_to? :call + if args.blank? + return ts_type.call(type) end + + ts_type = ts_type.call(*args) end - - def union?(args = '') - return args.to_s.gsub(/[{}]/, '').split(',').count > 1 - end - - def self.ts_lookup(name, type = 'node', args = '') - ts_type = TYPESCRIPT_TYPES[type] - if ts_type.blank? - if type =~ /^[[:upper:]]/ - ts_type = TYPESCRIPT_TYPES['instanceOf'] - else - ts_type = TYPESCRIPT_TYPES['node'] - end - end - - args = args.to_s.gsub(/[{}]/, '').split(',') - - if ts_type.respond_to? :call - if args.blank? - return ts_type.call(type) - end - - ts_type = ts_type.call(*args) + + ts_type + end + + def ts_lookup(name, type = "node", args = "") + self.class.ts_lookup(name, type, args) + end + + def self.lookup(type = "node", options = "") + react_prop_type = REACT_PROP_TYPES[type] + if react_prop_type.blank? + react_prop_type = if /^[[:upper:]]/.match?(type) + REACT_PROP_TYPES["instanceOf"] + else + REACT_PROP_TYPES["node"] end - - ts_type - end - - def ts_lookup(name, type = 'node', args = '') - self.class.ts_lookup(name, type, args) end - - def self.lookup(type = 'node', options = '') - react_prop_type = REACT_PROP_TYPES[type] - if react_prop_type.blank? - if type =~ /^[[:upper:]]/ - react_prop_type = REACT_PROP_TYPES['instanceOf'] - else - react_prop_type = REACT_PROP_TYPES['node'] - end - end - - options = options.to_s.gsub(/[{}]/, '').split(',') - - react_prop_type = react_prop_type.call(*options) if react_prop_type.respond_to? :call - react_prop_type - end - - def lookup(type = 'node', options = '') - self.class.lookup(type, options) - end + + options = options.to_s.gsub(/[{}]/, "").split(",") + + react_prop_type = react_prop_type.call(*options) if react_prop_type.respond_to? :call + react_prop_type + end + + def lookup(type = "node", options = "") + self.class.lookup(type, options) end end - end \ No newline at end of file + end +end diff --git a/gems/bess/lib/houdini.rb b/gems/bess/lib/houdini.rb index 085b81b036..9e3598054b 100644 --- a/gems/bess/lib/houdini.rb +++ b/gems/bess/lib/houdini.rb @@ -20,7 +20,7 @@ module Houdini mattr_accessor :general, default: {} mattr_accessor :defaults, default: {} - + mattr_accessor :payment_providers, default: {} mattr_accessor :maps, default: {} @@ -37,10 +37,9 @@ module Houdini mattr_accessor :hoster, default: Houdini::Hoster - mattr_accessor :core_classes, default: {supporter: 'Supporter', nonprofit: 'Nonprofit'} + mattr_accessor :core_classes, default: {supporter: "Supporter", nonprofit: "Nonprofit"} mattr_accessor :event_publisher, default: Houdini::EventPublisher.new - end # need to have Houdini loaded first before we can add engine diff --git a/gems/bess/lib/houdini/ccs.rb b/gems/bess/lib/houdini/ccs.rb index d5d9ccb2eb..0195d4f058 100644 --- a/gems/bess/lib/houdini/ccs.rb +++ b/gems/bess/lib/houdini/ccs.rb @@ -1,22 +1,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Houdini::Ccs - extend ActiveSupport::Autoload + extend ActiveSupport::Autoload - autoload :GithubAdapter - autoload :LocalTarGzAdapter + autoload :GithubAdapter + autoload :LocalTarGzAdapter - ADAPTER = 'Adapter' - private_constant :ADAPTER + ADAPTER = "Adapter" + private_constant :ADAPTER - # based on ActiveJob's configuration - class << self - def build(name, **options) - lookup(name).new(**options) - end + # based on ActiveJob's configuration + class << self + def build(name, **options) + lookup(name).new(**options) + end - def lookup(name) - const_get(name.to_s.camelize << ADAPTER) - end + def lookup(name) + const_get(name.to_s.camelize << ADAPTER) end -end \ No newline at end of file + end +end diff --git a/gems/bess/lib/houdini/ccs/github_adapter.rb b/gems/bess/lib/houdini/ccs/github_adapter.rb index 515c41852b..0db9e69f98 100644 --- a/gems/bess/lib/houdini/ccs/github_adapter.rb +++ b/gems/bess/lib/houdini/ccs/github_adapter.rb @@ -1,22 +1,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::Ccs::GithubAdapter - include ActiveModel::AttributeAssignment - attr_accessor :account, :repo - def initialize(attributes={}) - assign_attributes(attributes) if attributes - end + include ActiveModel::AttributeAssignment + attr_accessor :account, :repo + def initialize(attributes = {}) + assign_attributes(attributes) if attributes + end - # returns passes a url or io to the block - def retrieve_ccs(&block) - if !account || !repo - raise ('You must provide an account and repo for the CCS adapter for Github') - end - begin - git_hash = File.read("#{Rails.root}/CCS_HASH") - yield "https://github.com/#{account}/#{repo}/tree/#{git_hash}" - rescue => e - raise "Your CCS_HASH couldn't be read. Make sure it's in your Rails root" - end + # returns passes a url or io to the block + def retrieve_ccs(&block) + if !account || !repo + raise("You must provide an account and repo for the CCS adapter for Github") + end + begin + git_hash = File.read("#{Rails.root.join("CCS_HASH")}") + yield "https://github.com/#{account}/#{repo}/tree/#{git_hash}" + rescue + raise "Your CCS_HASH couldn't be read. Make sure it's in your Rails root" end -end \ No newline at end of file + end +end diff --git a/gems/bess/lib/houdini/ccs/local_tar_gz_adapter.rb b/gems/bess/lib/houdini/ccs/local_tar_gz_adapter.rb index cb5a6a39e0..64f71209c9 100644 --- a/gems/bess/lib/houdini/ccs/local_tar_gz_adapter.rb +++ b/gems/bess/lib/houdini/ccs/local_tar_gz_adapter.rb @@ -1,23 +1,23 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::Ccs::LocalTarGzAdapter - def initialize(**options) - @options = options + def initialize(**options) + @options = options + end + + # returns passes a url or io to the block + def retrieve_ccs(&block) + temp_file = Tempfile.new + result = Kernel.system("git archive --format=tar.gz -o #{temp_file.path} HEAD") + begin + if result + yield block(file) + else + raise "We couldn't create a CCS from the git archive. Is git available?" + end + ensure + temp_file.close + temp_file.unlink end - - # returns passes a url or io to the block - def retrieve_ccs(&block) - temp_file = Tempfile.new - result = Kernel.system("git archive --format=tar.gz -o #{temp_file.path} HEAD") - begin - if (result) - yield block(file) - else - raise "We couldn't create a CCS from the git archive. Is git available?" - end - ensure - temp_file.close - temp_file.unlink - end - end -end \ No newline at end of file + end +end diff --git a/gems/bess/lib/houdini/engine.rb b/gems/bess/lib/houdini/engine.rb index ddb499f412..144b92f89d 100644 --- a/gems/bess/lib/houdini/engine.rb +++ b/gems/bess/lib/houdini/engine.rb @@ -14,7 +14,7 @@ class Engine < ::Rails::Engine config.houdini = ActiveSupport::OrderedOptions.new - config.houdini.core_classes = {supporter: 'Supporter', nonprofit: 'Nonprofit'} + config.houdini.core_classes = {supporter: "Supporter", nonprofit: "Nonprofit"} config.houdini.general = ActiveSupport::OrderedOptions.new config.houdini.general.name = "Houdini Project" @@ -32,8 +32,8 @@ class Engine < ::Rails::Engine config.houdini.payment_providers = ActiveSupport::OrderedOptions.new config.houdini.payment_providers.stripe = ActiveSupport::OrderedOptions.new - config.houdini.payment_providers.stripe.public_key = ENV['STRIPE_API_PUBLIC'] - config.houdini.payment_providers.stripe.private_key = ENV['STRIPE_API_KEY'] + config.houdini.payment_providers.stripe.public_key = ENV["STRIPE_API_PUBLIC"] + config.houdini.payment_providers.stripe.private_key = ENV["STRIPE_API_KEY"] config.houdini.payment_providers.stripe.connect = false config.houdini.payment_providers.stripe.proprietary_v2_js = false @@ -43,7 +43,7 @@ class Engine < ::Rails::Engine config.houdini.default_bp.id = 1 config.houdini.page_editor = ActiveSupport::OrderedOptions.new - config.houdini.page_editor.editor = 'quill' + config.houdini.page_editor.editor = "quill" config.houdini.source_tokens = ActiveSupport::OrderedOptions.new config.houdini.source_tokens.max_uses = 1 @@ -54,8 +54,6 @@ class Engine < ::Rails::Engine config.houdini.show_state_field = true - - config.houdini.nonprofits_must_be_vetted = false config.houdini.terms_and_privacy = ActiveSupport::OrderedOptions.new @@ -68,13 +66,12 @@ class Engine < ::Rails::Engine config.houdini.listeners = [] - initializer 'houdini.set_configuration', before: 'houdini.finish_configuration' do |app| + initializer "houdini.set_configuration", before: "houdini.finish_configuration" do |app| app.config.to_prepare do Houdini.core_classes = app.config.houdini.core_classes - - Houdini.button_host = app.config.houdini.button_host || - ActionMailer::Base.default_url_options[:host] + Houdini.button_host = app.config.houdini.button_host || + ActionMailer::Base.default_url_options[:host] Houdini.payment_providers = Houdini::PaymentProvider::Registry.new(app.config.houdini.payment_providers).build_all @@ -83,7 +80,7 @@ class Engine < ::Rails::Engine ccs = app.config.houdini.ccs options = app.config.houdini.ccs_options || {} - Houdini.ccs = Houdini::Ccs.build(ccs, + Houdini.ccs = Houdini::Ccs.build(ccs, **options) Houdini.maintenance = Houdini::Maintenance.new(app.config.houdini.maintenance.to_h) @@ -102,7 +99,7 @@ class Engine < ::Rails::Engine end end - initializer 'houdini.finish_configuration', before: 'factory_bot.set_fixture_replacement' do |app| + initializer "houdini.finish_configuration", before: "factory_bot.set_fixture_replacement" do |app| # nothing to do, we just want to make sure we have proper initializer order end diff --git a/gems/bess/lib/houdini/engine_initializers.rb b/gems/bess/lib/houdini/engine_initializers.rb index 36baf960bd..1a644ebaef 100644 --- a/gems/bess/lib/houdini/engine_initializers.rb +++ b/gems/bess/lib/houdini/engine_initializers.rb @@ -5,12 +5,12 @@ # loads all of the engine initializer modules for Houdini module Houdini::EngineInitializers - extend ActiveSupport::Concern - extend ActiveSupport::Autoload - initializer_path = File.expand_path(File.join(File.dirname(__FILE__), 'engine_initializers')) - initializers = Dir.glob("#{initializer_path}/*").to_a - initializers.each do |file| - autoload File.basename(file, '.rb').camelize.to_sym - include "Houdini::EngineInitializers::#{File.basename(file, '.rb').camelize}".constantize - end + extend ActiveSupport::Concern + extend ActiveSupport::Autoload + initializer_path = File.expand_path(File.join(File.dirname(__FILE__), "engine_initializers")) + initializers = Dir.glob("#{initializer_path}/*").to_a + initializers.each do |file| + autoload File.basename(file, ".rb").camelize.to_sym + include "Houdini::EngineInitializers::#{File.basename(file, ".rb").camelize}".constantize + end end diff --git a/gems/bess/lib/houdini/engine_initializers/hoster.rb b/gems/bess/lib/houdini/engine_initializers/hoster.rb index 6eadfdbad9..7d3814ad0e 100644 --- a/gems/bess/lib/houdini/engine_initializers/hoster.rb +++ b/gems/bess/lib/houdini/engine_initializers/hoster.rb @@ -4,21 +4,21 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # an engine initializer for information about the hoster module Houdini::EngineInitializers::Hoster - extend ActiveSupport::Concern - included do - initializer 'houdini.hoster.set_configs', - before: 'houdini.finish_configs' do |app| - app.config.to_prepare do - options = app.config.houdini.hoster + extend ActiveSupport::Concern + included do + initializer "houdini.hoster.set_configs", + before: "houdini.finish_configs" do |app| + app.config.to_prepare do + options = app.config.houdini.hoster - options.support_email ||= ActionMailer::Base.default[:from] - options.main_admin_email ||= ActionMailer::Base.default[:from] + options.support_email ||= ActionMailer::Base.default[:from] + options.main_admin_email ||= ActionMailer::Base.default[:from] - options.each { |k, v| Houdini::Hoster.send("#{k}=", v) } - end - end + options.each { |k, v| Houdini::Hoster.send("#{k}=", v) } + end + end - config.houdini.hoster = ActiveSupport::OrderedOptions.new - config.houdini.hoster.terms_and_privacy = ActiveSupport::OrderedOptions.new - end + config.houdini.hoster = ActiveSupport::OrderedOptions.new + config.houdini.hoster.terms_and_privacy = ActiveSupport::OrderedOptions.new + end end diff --git a/gems/bess/lib/houdini/engine_initializers/intl.rb b/gems/bess/lib/houdini/engine_initializers/intl.rb index bffd2cd5f1..98924d9371 100644 --- a/gems/bess/lib/houdini/engine_initializers/intl.rb +++ b/gems/bess/lib/houdini/engine_initializers/intl.rb @@ -4,27 +4,27 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # engine initializer for everything international module Houdini::EngineInitializers::Intl - extend ActiveSupport::Concern - included do - initializer 'houdini.intl.set_configs', - before: 'houdini.finish_configs' do |app| - app.config.to_prepare do - Houdini.intl = Houdini::Intl.new(app.config.houdini.intl.to_h) - Houdini.intl.all_countries ||= ISO3166::Country.all.map(&:alpha2) - Houdini.intl.all_currencies ||= Money::Currency.table - if Houdini.intl.available_locales.map(&:to_s) - .none? { |l| l == Houdini.intl.language.to_s } - raise("The language #{Houdini.intl.language} is not listed \ - in the provided locales: #{Houdini.intl.available_locales.join(', ')}") - end - end - end + extend ActiveSupport::Concern + included do + initializer "houdini.intl.set_configs", + before: "houdini.finish_configs" do |app| + app.config.to_prepare do + Houdini.intl = Houdini::Intl.new(app.config.houdini.intl.to_h) + Houdini.intl.all_countries ||= ISO3166::Country.all.map(&:alpha2) + Houdini.intl.all_currencies ||= Money::Currency.table + if Houdini.intl.available_locales.map(&:to_s) + .none? { |l| l == Houdini.intl.language.to_s } + raise("The language #{Houdini.intl.language} is not listed \ + in the provided locales: #{Houdini.intl.available_locales.join(", ")}") + end + end + end - config.houdini.intl = ActiveSupport::OrderedOptions.new - config.houdini.intl.language = :en - config.houdini.intl.available_locales = %i[en de es fr it nl pl ro] - config.houdini.intl.all_countries = nil - config.houdini.intl.currencies = ['usd'] - config.houdini.intl.all_currencies = nil - end + config.houdini.intl = ActiveSupport::OrderedOptions.new + config.houdini.intl.language = :en + config.houdini.intl.available_locales = %i[en de es fr it nl pl ro] + config.houdini.intl.all_countries = nil + config.houdini.intl.currencies = ["usd"] + config.houdini.intl.all_currencies = nil + end end diff --git a/gems/bess/lib/houdini/event_publisher.rb b/gems/bess/lib/houdini/event_publisher.rb index 9524a0cb13..227a6d1dd0 100644 --- a/gems/bess/lib/houdini/event_publisher.rb +++ b/gems/bess/lib/houdini/event_publisher.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'wisper' -require 'wisper/activejob' +require "wisper" +require "wisper/activejob" ### # @description: An event publisher in Houdini for calling listening to async events or responding to them @@ -16,7 +16,7 @@ # # Listener classes have the methods with the name of every event they want to listen to # as class methods. As an example the if the listener class SupporterListener wanted to run -# some code when the `supporter_create`, or `supporter_merge` event was announced, +# some code when the `supporter_create`, or `supporter_merge` event was announced, # Supporter Listener would look like so: # # class SupporterListener @@ -28,40 +28,40 @@ # # run some code # end # end -# +# # Currently, all listeners are called asynchronously using ActiveJob. This may change soonish. ### class Houdini::EventPublisher - include Wisper::Publisher + include Wisper::Publisher - ### - # @description: announce a new event to all of the listeners listening for `event_type` - # @param event_type {symbol}: the type of event being announced. - # @param args {array}: the arguments to be passed to the event listeners. - ### - def announce(event_type, *args) - broadcast(event_type, *args) - end + ### + # @description: announce a new event to all of the listeners listening for `event_type` + # @param event_type {symbol}: the type of event being announced. + # @param args {array}: the arguments to be passed to the event listeners. + ### + def announce(event_type, *args) + broadcast(event_type, *args) + end - ### - # @description: asynchronously listen for an event to occur - # Normally, you don't call this directly, you'll push an listener class to the - # Rails.application.config.houdini.listeners array in an initializer - # @param listener {Class}: the listener class - ### - def subscribe_async(listener, options = {}) - subscribe(listener, options.merge(async: true)) - end + ### + # @description: asynchronously listen for an event to occur + # Normally, you don't call this directly, you'll push an listener class to the + # Rails.application.config.houdini.listeners array in an initializer + # @param listener {Class}: the listener class + ### + def subscribe_async(listener, options = {}) + subscribe(listener, options.merge(async: true)) + end - ### - # @description: having an array of listeners - # Normally, you don't call this directly, you'll push a set of listener classes - # to Rails.application.config.houdini.listeners array in an initializer - # @param listeners {Array}: an array of listener classes - ### - def subscribe_all(listeners, options = {}) - listeners.each do |listener| - subscribe(listener, options.merge(async: true)) - end - end -end \ No newline at end of file + ### + # @description: having an array of listeners + # Normally, you don't call this directly, you'll push a set of listener classes + # to Rails.application.config.houdini.listeners array in an initializer + # @param listeners {Array}: an array of listener classes + ### + def subscribe_all(listeners, options = {}) + listeners.each do |listener| + subscribe(listener, options.merge(async: true)) + end + end +end diff --git a/gems/bess/lib/houdini/hoster.rb b/gems/bess/lib/houdini/hoster.rb index d7224d3c01..10a0fdedac 100644 --- a/gems/bess/lib/houdini/hoster.rb +++ b/gems/bess/lib/houdini/hoster.rb @@ -3,30 +3,30 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Houdini::Hoster - # (required) - the legal name of the hoster - mattr_accessor :legal_name + # (required) - the legal name of the hoster + mattr_accessor :legal_name - # (optional but STRONGLY RECOMMENDED) - the email used for receiving emails - # and notifications which deal with contacting the admin - mattr_accessor :main_admin_email + # (optional but STRONGLY RECOMMENDED) - the email used for receiving emails + # and notifications which deal with contacting the admin + mattr_accessor :main_admin_email - mattr_writer :casual_name + mattr_writer :casual_name - ## (optional, defaults to legal_name) - a more casual name of the website As an example - ## if your hoster was HoudiniCo LLC, you might use HoudiniCo or - ## CustomHoudiniInstance here. We use this for possessive nouns and similar. - def self.casual_name - @@casual_name || Houdini::Hoster.legal_name - end + ## (optional, defaults to legal_name) - a more casual name of the website As an example + ## if your hoster was HoudiniCo LLC, you might use HoudiniCo or + ## CustomHoudiniInstance here. We use this for possessive nouns and similar. + def self.casual_name + @@casual_name || Houdini::Hoster.legal_name + end - # has casual_name been set? - def self.casual_name? - @@casual_name.present? - end + # has casual_name been set? + def self.casual_name? + @@casual_name.present? + end - # (optional) - the email address for contacting support - mattr_accessor :support_email + # (optional) - the email address for contacting support + mattr_accessor :support_email - # terms_and_privacy - mattr_accessor :terms_and_privacy + # terms_and_privacy + mattr_accessor :terms_and_privacy end diff --git a/gems/bess/lib/houdini/intl.rb b/gems/bess/lib/houdini/intl.rb index ff17204037..5a4ce49b3f 100644 --- a/gems/bess/lib/houdini/intl.rb +++ b/gems/bess/lib/houdini/intl.rb @@ -1,10 +1,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::Intl - include ActiveModel::AttributeAssignment - attr_accessor :currency, :available_locales, :language, :currencies, :all_currencies, :all_countries + include ActiveModel::AttributeAssignment + attr_accessor :currency, :available_locales, :language, :currencies, :all_currencies, :all_countries - def initialize(attributes={}) - assign_attributes(attributes) if attributes - end -end \ No newline at end of file + def initialize(attributes = {}) + assign_attributes(attributes) if attributes + end +end diff --git a/gems/bess/lib/houdini/maintenance.rb b/gems/bess/lib/houdini/maintenance.rb index de4547bba4..6c2f152bac 100644 --- a/gems/bess/lib/houdini/maintenance.rb +++ b/gems/bess/lib/houdini/maintenance.rb @@ -1,10 +1,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::Maintenance - include ActiveModel::AttributeAssignment - attr_accessor :active, :token, :page + include ActiveModel::AttributeAssignment + attr_accessor :active, :token, :page - def initialize(attributes={}) - assign_attributes(attributes) if attributes - end -end \ No newline at end of file + def initialize(attributes = {}) + assign_attributes(attributes) if attributes + end +end diff --git a/gems/bess/lib/houdini/payment_provider.rb b/gems/bess/lib/houdini/payment_provider.rb index f092fe860e..671e127ba0 100644 --- a/gems/bess/lib/houdini/payment_provider.rb +++ b/gems/bess/lib/houdini/payment_provider.rb @@ -1,22 +1,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module Houdini::PaymentProvider - extend ActiveSupport::Autoload + extend ActiveSupport::Autoload - autoload :Registry - autoload :StripeProvider + autoload :Registry + autoload :StripeProvider - PROVIDER = 'Provider' - private_constant :PROVIDER + PROVIDER = "Provider" + private_constant :PROVIDER - # based on ActiveJob's configuration - class << self - def build(name, options={}) - lookup(name).new(options) - end + # based on ActiveJob's configuration + class << self + def build(name, options = {}) + lookup(name).new(options) + end - def lookup(name) - const_get(name.to_s.camelize << PROVIDER) - end - end -end \ No newline at end of file + def lookup(name) + const_get(name.to_s.camelize << PROVIDER) + end + end +end diff --git a/gems/bess/lib/houdini/payment_provider/registry.rb b/gems/bess/lib/houdini/payment_provider/registry.rb index ad42e34c9a..8e4dadddd7 100644 --- a/gems/bess/lib/houdini/payment_provider/registry.rb +++ b/gems/bess/lib/houdini/payment_provider/registry.rb @@ -3,26 +3,27 @@ require 'ostruct' class Houdini::PaymentProvider::Registry - def initialize(configurations) - @configurations = configurations.deep_dup - @providers = OpenStruct.new - end - - def build_all - configurations.each do |key, options={}| - resolve(key) - providers[key] = Houdini::PaymentProvider.build(key, options) - end + def initialize(configurations) + @configurations = configurations.deep_dup + @providers = OpenStruct.new + end - providers + def build_all + configurations.each do |key, options = {}| + resolve(key) + providers[key] = Houdini::PaymentProvider.build(key, options) end - private - attr_reader :configurations, :providers - def resolve(class_name) - require "houdini/payment_provider/#{class_name.to_s.underscore}_provider" - Houdini::PaymentProvider.const_get(:"#{class_name.to_s.camelize}Provider") - rescue LoadError - raise "Missing provider for #{class_name.inspect}" - end -end \ No newline at end of file + providers + end + + private + + attr_reader :configurations, :providers + def resolve(class_name) + require "houdini/payment_provider/#{class_name.to_s.underscore}_provider" + Houdini::PaymentProvider.const_get(:"#{class_name.to_s.camelize}Provider") + rescue LoadError + raise "Missing provider for #{class_name.inspect}" + end +end diff --git a/gems/bess/lib/houdini/payment_provider/stripe_provider.rb b/gems/bess/lib/houdini/payment_provider/stripe_provider.rb index f058c7eee4..d3767e36eb 100644 --- a/gems/bess/lib/houdini/payment_provider/stripe_provider.rb +++ b/gems/bess/lib/houdini/payment_provider/stripe_provider.rb @@ -1,13 +1,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::PaymentProvider::StripeProvider - include ActiveModel::AttributeAssignment + include ActiveModel::AttributeAssignment - attr_accessor :private_key, :public_key, :connect, :proprietary_v2_js - def initialize(attributes={}) - # attributes will always be from OrderedOptions so we'll make this .to_h for now - assign_attributes(attributes.to_h) - require 'stripe' - Stripe.api_key = private_key - end -end \ No newline at end of file + attr_accessor :private_key, :public_key, :connect, :proprietary_v2_js + def initialize(attributes = {}) + # attributes will always be from OrderedOptions so we'll make this .to_h for now + assign_attributes(attributes.to_h) + require "stripe" + Stripe.api_key = private_key + end +end diff --git a/gems/bess/lib/houdini/webhook_adapter.rb b/gems/bess/lib/houdini/webhook_adapter.rb index acb1b97e74..9e6ecb4737 100644 --- a/gems/bess/lib/houdini/webhook_adapter.rb +++ b/gems/bess/lib/houdini/webhook_adapter.rb @@ -20,12 +20,11 @@ def transmit(payload) ) end - ADAPTER = 'Adapter' + ADAPTER = "Adapter" private_constant :ADAPTER # based on ActiveJob's configuration class << self - def build(name, options) lookup(name).new(**options) end diff --git a/gems/bess/spec/lib/houdini/maintenance_spec.rb b/gems/bess/spec/lib/houdini/maintenance_spec.rb index ef476e90ae..41f7ee0e3c 100644 --- a/gems/bess/spec/lib/houdini/maintenance_spec.rb +++ b/gems/bess/spec/lib/houdini/maintenance_spec.rb @@ -2,20 +2,20 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Houdini::Maintenance do - PAGE = 'https://something.c' - TOKEN = "TOKEN" - it 'sets active to false as default' do - m = Houdini::Maintenance.new - expect(m.active).to be_falsy - end + PAGE = "https://something.c" + TOKEN = "TOKEN" + it "sets active to false as default" do + m = Houdini::Maintenance.new + expect(m.active).to be_falsy + end - it 'accepts proper items' do - m = Houdini::Maintenance.new(active:true, page:PAGE, token: TOKEN) - expect(m.active).to eq true - expect(m.page).to eq PAGE - expect(m.token).to eq TOKEN - end -end \ No newline at end of file + it "accepts proper items" do + m = Houdini::Maintenance.new(active: true, page: PAGE, token: TOKEN) + expect(m.active).to eq true + expect(m.page).to eq PAGE + expect(m.token).to eq TOKEN + end +end diff --git a/gems/bess/spec/rails_helper.rb b/gems/bess/spec/rails_helper.rb index 186f6ce0ba..4d82c62865 100644 --- a/gems/bess/spec/rails_helper.rb +++ b/gems/bess/spec/rails_helper.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true # This file is copied to spec/ when you run 'rails generate rspec:install' -require 'spec_helper' -ENV['RAILS_ENV'] ||= 'test' +require "spec_helper" +ENV["RAILS_ENV"] ||= "test" # require File.expand_path('../config/environment', __dir__) # Prevent database truncation if the environment is production -abort('The Rails environment is running in production mode!') if Rails.env.production? -require 'rspec/rails' +abort("The Rails environment is running in production mode!") if Rails.env.production? +require "rspec/rails" # Add additional requires below this line. Rails is not loaded until this point! # Requires supporting ruby files with custom matchers and macros, etc, in @@ -25,33 +25,33 @@ # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } RSpec.configure do |config| - # Remove this line to enable support for ActiveRecord - config.use_active_record = false + # Remove this line to enable support for ActiveRecord + config.use_active_record = false - # If you enable ActiveRecord support you should unncomment these lines, - # note if you'd prefer not to run each example within a transaction, you - # should set use_transactional_fixtures to false. - # - # config.fixture_path = "#{::Rails.root}/spec/fixtures" - # config.use_transactional_fixtures = true + # If you enable ActiveRecord support you should unncomment these lines, + # note if you'd prefer not to run each example within a transaction, you + # should set use_transactional_fixtures to false. + # + # config.fixture_path = "#{::Rails.root}/spec/fixtures" + # config.use_transactional_fixtures = true - # RSpec Rails can automatically mix in different behaviours to your tests - # based on their file location, for example enabling you to call `get` and - # `post` in specs under `spec/controllers`. - # - # You can disable this behaviour by removing the line below, and instead - # explicitly tag your specs with their type, e.g.: - # - # RSpec.describe UsersController, type: :controller do - # # ... - # end - # - # The different available types are documented in the features, such as in - # https://relishapp.com/rspec/rspec-rails/docs - config.infer_spec_type_from_file_location! + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, type: :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! - # Filter lines from Rails gems in backtraces. - config.filter_rails_from_backtrace! - # arbitrary gems may also be filtered via: - # config.filter_gems_from_backtrace("gem name") + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") end diff --git a/gems/bess/spec/spec_helper.rb b/gems/bess/spec/spec_helper.rb index 7ea89285d0..0ff1966b7d 100644 --- a/gems/bess/spec/spec_helper.rb +++ b/gems/bess/spec/spec_helper.rb @@ -14,11 +14,11 @@ # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration -ENGINE_ROOT = File.expand_path('..', __dir__) -ENGINE_PATH = File.expand_path('../lib/houdini/engine', __dir__) +ENGINE_ROOT = File.expand_path("..", __dir__) +ENGINE_PATH = File.expand_path("../lib/houdini/engine", __dir__) # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) require "rails" require "active_model/railtie" @@ -26,7 +26,6 @@ require "action_view/railtie" Bundler.require :default, :development, :test - RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest @@ -58,53 +57,51 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = "doc" - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = "doc" + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed end diff --git a/gems/houdini_full_contact/app/jobs/houdini/full_contact/application_job.rb b/gems/houdini_full_contact/app/jobs/houdini/full_contact/application_job.rb index a7f39dd62e..05667029d1 100644 --- a/gems/houdini_full_contact/app/jobs/houdini/full_contact/application_job.rb +++ b/gems/houdini_full_contact/app/jobs/houdini/full_contact/application_job.rb @@ -3,4 +3,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::FullContact::ApplicationJob < ActiveJob::Base -end \ No newline at end of file +end diff --git a/gems/houdini_full_contact/app/jobs/houdini/full_contact/full_contact_job.rb b/gems/houdini_full_contact/app/jobs/houdini/full_contact/full_contact_job.rb index 47b2538252..a5676f139f 100644 --- a/gems/houdini_full_contact/app/jobs/houdini/full_contact/full_contact_job.rb +++ b/gems/houdini_full_contact/app/jobs/houdini/full_contact/full_contact_job.rb @@ -3,11 +3,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::FullContact::FullContactJob < Houdini::FullContact::ApplicationJob - queue_as :full_contact_queue + queue_as :full_contact_queue - retry_on Exception, wait: ->(executions) { executions **2.195 }, attempts: Houdini::FullContact.max_attempts || 1 + retry_on Exception, wait: ->(executions) { executions**2.195 }, attempts: Houdini::FullContact.max_attempts || 1 - def perform(supporter) - Houdini::FullContact::InsertInfos.single(supporter) - end -end \ No newline at end of file + def perform(supporter) + Houdini::FullContact::InsertInfos.single(supporter) + end +end diff --git a/gems/houdini_full_contact/app/listeners/houdini/full_contact/full_contact_listener.rb b/gems/houdini_full_contact/app/listeners/houdini/full_contact/full_contact_listener.rb index 3b485964ee..cdbf2128d5 100644 --- a/gems/houdini_full_contact/app/listeners/houdini/full_contact/full_contact_listener.rb +++ b/gems/houdini_full_contact/app/listeners/houdini/full_contact/full_contact_listener.rb @@ -3,11 +3,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Houdini::FullContact::FullContactListener - def name - self.class.name - end + def name + self.class.name + end - def self.supporter_create(supporter) - FullContactJob.perform_later(supporter) - end -end \ No newline at end of file + def self.supporter_create(supporter) + FullContactJob.perform_later(supporter) + end +end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/application_record.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/application_record.rb index 45ab6fb2f1..7ca4b2403f 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/application_record.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/application_record.rb @@ -2,5 +2,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::ApplicationRecord < ActiveRecord::Base - self.abstract_class = true -end \ No newline at end of file + self.abstract_class = true +end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/info.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/info.rb index d6b9990aa7..9c18404c39 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/info.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/info.rb @@ -2,12 +2,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::Info < ApplicationRecord - self.table_name = 'full_contact_infos' + self.table_name = "full_contact_infos" - has_many :photos, foreign_key: 'full_contact_info_id' - has_many :social_profiles, foreign_key: 'full_contact_info_id' - has_many :orgs, foreign_key: 'full_contact_info_id' - has_many :topics, foreign_key: 'full_contact_info_id' + has_many :photos, foreign_key: "full_contact_info_id" + has_many :social_profiles, foreign_key: "full_contact_info_id" + has_many :orgs, foreign_key: "full_contact_info_id" + has_many :topics, foreign_key: "full_contact_info_id" belongs_to :supporter, class_name: Houdini.core_classes.fetch(:supporter).to_s end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/job.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/job.rb index d23d605d9b..68627fcbe3 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/job.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/job.rb @@ -2,6 +2,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::Job < ApplicationRecord - self.table_name = 'full_contact_jobs' - belongs_to :supporter, class_name: Houdini.core_classes.fetch(:supporter) -end \ No newline at end of file + self.table_name = "full_contact_jobs" + belongs_to :supporter, class_name: Houdini.core_classes.fetch(:supporter) +end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/org.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/org.rb index 31f426b0e4..86e335a102 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/org.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/org.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::Org < ApplicationRecord - self.table_name = 'full_contact_orgs' + self.table_name = "full_contact_orgs" - belongs_to :info, foreign_key: 'full_contact_info_id' + belongs_to :info, foreign_key: "full_contact_info_id" end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/photo.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/photo.rb index ce32bdf9e3..e2bcff1af3 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/photo.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/photo.rb @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::Photo < ApplicationRecord - self.table_name = 'full_contact_photos' + self.table_name = "full_contact_photos" - belongs_to :info, foreign_key: 'full_contact_info_id' + belongs_to :info, foreign_key: "full_contact_info_id" validates_presence_of :info end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/social_profile.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/social_profile.rb index 1d4b2cce51..c23b741ae3 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/social_profile.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/social_profile.rb @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::SocialProfile < ApplicationRecord - self.table_name = 'full_contact_social_profiles' + self.table_name = "full_contact_social_profiles" - belongs_to :info, foreign_key: 'full_contact_info_id' + belongs_to :info, foreign_key: "full_contact_info_id" validates_presence_of :info end diff --git a/gems/houdini_full_contact/app/models/houdini/full_contact/topic.rb b/gems/houdini_full_contact/app/models/houdini/full_contact/topic.rb index 377a6fc0fe..c3944e3c41 100644 --- a/gems/houdini_full_contact/app/models/houdini/full_contact/topic.rb +++ b/gems/houdini_full_contact/app/models/houdini/full_contact/topic.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::FullContact::Topic < ApplicationRecord - self.table_name = 'full_contact_topics' + self.table_name = "full_contact_topics" - belongs_to :info, foreign_key: 'full_contact_info_id' + belongs_to :info, foreign_key: "full_contact_info_id" end diff --git a/gems/houdini_full_contact/bin/rails b/gems/houdini_full_contact/bin/rails index 41fb84d1bd..31398918a4 100755 --- a/gems/houdini_full_contact/bin/rails +++ b/gems/houdini_full_contact/bin/rails @@ -2,11 +2,11 @@ # This command will automatically be run when you run "rails" with Rails gems # installed from the root of your application. -ENGINE_ROOT = File.expand_path('..', __dir__) -ENGINE_PATH = File.expand_path('../lib/houdini/full_contact/engine', __dir__) +ENGINE_ROOT = File.expand_path("..", __dir__) +ENGINE_PATH = File.expand_path("../lib/houdini/full_contact/engine", __dir__) # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) require "rails" diff --git a/gems/houdini_full_contact/config/initializers/houdini_event_publisher.rb b/gems/houdini_full_contact/config/initializers/houdini_event_publisher.rb index b9a7831516..7824e305bd 100644 --- a/gems/houdini_full_contact/config/initializers/houdini_event_publisher.rb +++ b/gems/houdini_full_contact/config/initializers/houdini_event_publisher.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Rails.application.config.houdini.listeners << Houdini::FullContact::FullContactListener \ No newline at end of file +Rails.application.config.houdini.listeners << Houdini::FullContact::FullContactListener diff --git a/gems/houdini_full_contact/db/migrate/20200611182909_create_full_contact.rb b/gems/houdini_full_contact/db/migrate/20200611182909_create_full_contact.rb index 86c28e975e..bdd2d0975e 100644 --- a/gems/houdini_full_contact/db/migrate/20200611182909_create_full_contact.rb +++ b/gems/houdini_full_contact/db/migrate/20200611182909_create_full_contact.rb @@ -16,7 +16,7 @@ def change t.text :websites t.timestamps end - + create_table :full_contact_topics do |t| t.references :full_contact_infos t.string :provider @@ -26,12 +26,12 @@ def change create_table :full_contact_social_profiles do |t| t.references :full_contact_infos - t.string :type_id - t.string :username - t.string :uid - t.text :bio + t.string :type_id + t.string :username + t.string :uid + t.text :bio t.string :url - t.integer :followers + t.integer :followers t.integer :following t.timestamps end diff --git a/gems/houdini_full_contact/houdini_full_contact.gemspec b/gems/houdini_full_contact/houdini_full_contact.gemspec index 8b0a37270f..2a3729ae99 100644 --- a/gems/houdini_full_contact/houdini_full_contact.gemspec +++ b/gems/houdini_full_contact/houdini_full_contact.gemspec @@ -1,14 +1,14 @@ require_relative "lib/houdini_full_contact/version" Gem::Specification.new do |spec| - spec.name = "houdini_full_contact" - spec.version = HoudiniFullContact::VERSION - spec.authors = [""] - spec.email = ["eric@commitchange.com"] + spec.name = "houdini_full_contact" + spec.version = HoudiniFullContact::VERSION + spec.authors = [""] + spec.email = ["eric@commitchange.com"] # spec.homepage = "TODO" - spec.summary = " Summary of FullContact." + spec.summary = " Summary of FullContact." # spec.description = "TODO: Description of FullContact." - spec.license = "AGPL-3.0-or-later WITH WTO-Additional-Permission-3.0-or-later" + spec.license = "AGPL-3.0-or-later WITH WTO-Additional-Permission-3.0-or-later" # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' # to allow pushing to a single host or delete this section to allow pushing to any host. diff --git a/gems/houdini_full_contact/lib/houdini.rb b/gems/houdini_full_contact/lib/houdini.rb index cb84bf3db8..a40d517871 100644 --- a/gems/houdini_full_contact/lib/houdini.rb +++ b/gems/houdini_full_contact/lib/houdini.rb @@ -4,4 +4,4 @@ require "houdini/full_contact" module Houdini -end \ No newline at end of file +end diff --git a/gems/houdini_full_contact/lib/houdini/full_contact.rb b/gems/houdini_full_contact/lib/houdini/full_contact.rb index 8d7c4cfb5b..56781b24ed 100644 --- a/gems/houdini_full_contact/lib/houdini/full_contact.rb +++ b/gems/houdini_full_contact/lib/houdini/full_contact.rb @@ -1,9 +1,9 @@ require "houdini/full_contact/engine" module Houdini::FullContact - extend ActiveSupport::Autoload + extend ActiveSupport::Autoload - autoload :InsertInfos + autoload :InsertInfos - mattr_accessor :api_key, :max_attempts -end \ No newline at end of file + mattr_accessor :api_key, :max_attempts +end diff --git a/gems/houdini_full_contact/lib/houdini/full_contact/engine.rb b/gems/houdini_full_contact/lib/houdini/full_contact/engine.rb index ce76e8c508..4dc85eb3e4 100644 --- a/gems/houdini_full_contact/lib/houdini/full_contact/engine.rb +++ b/gems/houdini_full_contact/lib/houdini/full_contact/engine.rb @@ -9,16 +9,16 @@ class Engine < ::Rails::Engine config.houdini.full_contact = ActiveSupport::OrderedOptions.new config.houdini.full_contact.max_attempts = 5 - initializer 'houdini.full_contact.supporter_extension' do - ActiveSupport.on_load(:houdini_supporter) do - self.has_many :full_contact_infos, class_name: 'Houdini::FullContact::Info' + initializer "houdini.full_contact.supporter_extension" do + ActiveSupport.on_load(:houdini_supporter) do + has_many :full_contact_infos, class_name: "Houdini::FullContact::Info" end end - initializer 'houdini.full_contact.configs' do + initializer "houdini.full_contact.configs" do config.before_initialize do |app| - Houdini::FullContact.api_key = app.config.houdini.full_contact.api_key || - ENV.fetch('FULL_CONTACT_KEY') + Houdini::FullContact.api_key = app.config.houdini.full_contact.api_key || + ENV.fetch("FULL_CONTACT_KEY") Houdini::FullContact.max_attempts = app.config.houdini.full_contact.max_attempts end end diff --git a/gems/houdini_full_contact/lib/houdini/full_contact/insert_infos.rb b/gems/houdini_full_contact/lib/houdini/full_contact/insert_infos.rb index 9512e65a85..596ac62a3a 100644 --- a/gems/houdini_full_contact/lib/houdini/full_contact/insert_infos.rb +++ b/gems/houdini_full_contact/lib/houdini/full_contact/insert_infos.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require 'qx' -require 'rest-client' +require "qx" +require "rest-client" module Houdini::FullContact::InsertInfos # Fetch and persist a single full contact record for a single supporter # return an exception if 404 or something else went poop @@ -12,14 +12,14 @@ def self.single(supporter) begin response = RestClient.post("https://api.fullcontact.com/v3/person.enrich", { - "email" => supporter.email, + "email" => supporter.email }.to_json, { :authorization => "Bearer #{Houdini::FullContact.api_key}", "Reporting-Key" => supporter.nonprofit_id }) - result = response.parsed_body - rescue RestClient::NotFound => e + result = response.parsed_body + rescue RestClient::NotFound # this means there's no information about this contact so there's nothing to do. # We just return and end @@ -27,99 +27,104 @@ def self.single(supporter) return end - location = result['location'] && result['details']['locations'] && result['details']['locations'][0] + location = result["location"] && result["details"]["locations"] && result["details"]["locations"][0] existing = supporter.full_contact_infos.last info_data = { - full_name: result['fullName'], - gender: result['gender'], - city: location && location['city'], - state_code: location && location['regionCode'], - country: location && location['countryCode'], - age_range: result['ageRange'], - location_general: result['location'], - websites: ((result['details'] && result['details']['urls']) || []).map{|h| h['value']}.join(','), + full_name: result["fullName"], + gender: result["gender"], + city: location && location["city"], + state_code: location && location["regionCode"], + country: location && location["countryCode"], + age_range: result["ageRange"], + location_general: result["location"], + websites: ((result["details"] && result["details"]["urls"]) || []).map { |h| h["value"] }.join(","), supporter_id: supporter.id } return { - 'full_contact_info' => full_contact_info, - 'full_contact_photos' => full_contact_photos, - 'full_contact_social_profiles' => full_contact_social_profiles, - 'full_contact_orgs' => full_contact_orgs + "full_contact_info" => full_contact_info, + "full_contact_photos" => full_contact_photos, + "full_contact_social_profiles" => full_contact_social_profiles, + "full_contact_orgs" => full_contact_orgs } - if existing - full_contact_info = Qx.update(:full_contact_infos) + full_contact_info = if existing + Qx.update(:full_contact_infos) .set(info_data) .timestamps - .where(id: existing['id']) - .returning('*') + .where(id: existing["id"]) + .returning("*") .execute.first else - full_contact_info = Qx.insert_into(:full_contact_infos) + Qx.insert_into(:full_contact_infos) .values(info_data) - .returning('*') + .returning("*") .timestamps .execute.first end - if result['details']['photos'].present? - photo_data = result['details']['photos'].map{|h| {type_id: h['label'], url: h['value']}} + if result["details"]["photos"].present? + photo_data = result["details"]["photos"].map { |h| {type_id: h["label"], url: h["value"]} } Qx.delete_from("full_contact_photos") - .where(full_contact_info_id: full_contact_info['id']) + .where(full_contact_info_id: full_contact_info["id"]) .execute full_contact_photos = Qx.insert_into(:full_contact_photos) .values(photo_data) - .common_values(full_contact_info_id: full_contact_info['id']) + .common_values(full_contact_info_id: full_contact_info["id"]) .timestamps .returning("*") .execute end - if result['details']['profiles'].present? - profile_data = result['details']['profiles'].map{|k,v| {type_id: v['service'], username: v['username'], uid: v['userid'], bio: v['bio'], url: v['url'], followers: v['followers'], following: v['following']} } + if result["details"]["profiles"].present? + profile_data = result["details"]["profiles"].map { |k, v| {type_id: v["service"], username: v["username"], uid: v["userid"], bio: v["bio"], url: v["url"], followers: v["followers"], following: v["following"]} } Qx.delete_from("full_contact_social_profiles") - .where(full_contact_info_id: full_contact_info['id']) + .where(full_contact_info_id: full_contact_info["id"]) .execute full_contact_social_profiles = Qx.insert_into(:full_contact_social_profiles) .values(profile_data) - .common_values(full_contact_info_id: full_contact_info['id']) + .common_values(full_contact_info_id: full_contact_info["id"]) .timestamps .returning("*") .execute end - if result['details'].present? && result['details']['employment'].present? - Qx.delete_from('full_contact_orgs') - .where(full_contact_info_id: full_contact_info['id']) + if result["details"].present? && result["details"]["employment"].present? + Qx.delete_from("full_contact_orgs") + .where(full_contact_info_id: full_contact_info["id"]) .execute - org_data = result['details']['employment'].map{|h| - start_date = nil - end_date = nil - start_date = h['start'] && [h['start']['year'], h['start']['month'], h['start']['day']].select(&:present?).join('-') - end_date = h['end'] && [h['end']['year'], h['end']['month'], h['end']['day']].select(&:present?).join('-') + org_data = result["details"]["employment"].map { |h| + start_date = h["start"] && [h["start"]["year"], h["start"]["month"], h["start"]["day"]].select(&:present?).join("-") + end_date = h["end"] && [h["end"]["year"], h["end"]["month"], h["end"]["day"]].select(&:present?).join("-") { - name: h['name'], + name: h["name"], start_date: start_date, end_date: end_date, - title: h['title'], - current: h['current'] - } } - .map{|h| h[:end_date] = Format::Date.parse_partial_str(h[:end_date]); h} - .map{|h| h[:start_date] = Format::Date.parse_partial_str(h[:start_date]); h} + title: h["title"], + current: h["current"] + } + } + .map { |h| + h[:end_date] = Format::Date.parse_partial_str(h[:end_date]) + h + } + .map { |h| + h[:start_date] = Format::Date.parse_partial_str(h[:start_date]) + h + } full_contact_orgs = Qx.insert_into(:full_contact_orgs) .values(org_data) - .common_values(full_contact_info_id: full_contact_info['id']) + .common_values(full_contact_info_id: full_contact_info["id"]) .timestamps - .returning('*') + .returning("*") .execute end - return { - 'full_contact_info' => full_contact_info, - 'full_contact_photos' => full_contact_photos, - 'full_contact_social_profiles' => full_contact_social_profiles, - 'full_contact_orgs' => full_contact_orgs + { + "full_contact_info" => full_contact_info, + "full_contact_photos" => full_contact_photos, + "full_contact_social_profiles" => full_contact_social_profiles, + "full_contact_orgs" => full_contact_orgs } end diff --git a/gems/houdini_full_contact/lib/houdini_full_contact.rb b/gems/houdini_full_contact/lib/houdini_full_contact.rb index 4c462ceded..d4c3d5f6c5 100644 --- a/gems/houdini_full_contact/lib/houdini_full_contact.rb +++ b/gems/houdini_full_contact/lib/houdini_full_contact.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require_relative "./houdini" +require_relative "houdini" diff --git a/gems/houdini_full_contact/lib/houdini_full_contact/version.rb b/gems/houdini_full_contact/lib/houdini_full_contact/version.rb index beb8545397..9066d5ab90 100644 --- a/gems/houdini_full_contact/lib/houdini_full_contact/version.rb +++ b/gems/houdini_full_contact/lib/houdini_full_contact/version.rb @@ -2,5 +2,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module HoudiniFullContact - VERSION = '0.1.0' -end \ No newline at end of file + VERSION = "0.1.0" +end diff --git a/gems/houdini_upgrade/bin/rails b/gems/houdini_upgrade/bin/rails index eb7cc6c711..bc2d3fa723 100755 --- a/gems/houdini_upgrade/bin/rails +++ b/gems/houdini_upgrade/bin/rails @@ -2,11 +2,11 @@ # This command will automatically be run when you run "rails" with Rails gems # installed from the root of your application. -ENGINE_ROOT = File.expand_path('..', __dir__) -ENGINE_PATH = File.expand_path('../lib/houdini_upgrade/engine', __dir__) +ENGINE_ROOT = File.expand_path("..", __dir__) +ENGINE_PATH = File.expand_path("../lib/houdini_upgrade/engine", __dir__) # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) require "rails" diff --git a/gems/houdini_upgrade/db/migrate/20191105200033_remove_billing_plan_tiers.rb b/gems/houdini_upgrade/db/migrate/20191105200033_remove_billing_plan_tiers.rb index 3eae436b1e..4ece9ced29 100644 --- a/gems/houdini_upgrade/db/migrate/20191105200033_remove_billing_plan_tiers.rb +++ b/gems/houdini_upgrade/db/migrate/20191105200033_remove_billing_plan_tiers.rb @@ -4,4 +4,4 @@ class RemoveBillingPlanTiers < ActiveRecord::Migration[5.2] def change remove_column :billing_plans, :tier, :integer end -end \ No newline at end of file +end diff --git a/gems/houdini_upgrade/db/migrate/20210204013426_remove_long_and_lat.rb b/gems/houdini_upgrade/db/migrate/20210204013426_remove_long_and_lat.rb index 76925b7219..c05dafaeb4 100644 --- a/gems/houdini_upgrade/db/migrate/20210204013426_remove_long_and_lat.rb +++ b/gems/houdini_upgrade/db/migrate/20210204013426_remove_long_and_lat.rb @@ -4,9 +4,9 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class RemoveLongAndLat < ActiveRecord::Migration[6.1] def change - [:users, :events, :nonprofits, :supporters].each do |i| + [:users, :events, :nonprofits, :supporters].each do |i| remove_column i, :longitude, "double precision" - remove_column i, :latitude, "double precision" + remove_column i, :latitude, "double precision" end end end diff --git a/gems/houdini_upgrade/houdini_upgrade.gemspec b/gems/houdini_upgrade/houdini_upgrade.gemspec index 556949af2f..f9198fa731 100644 --- a/gems/houdini_upgrade/houdini_upgrade.gemspec +++ b/gems/houdini_upgrade/houdini_upgrade.gemspec @@ -1,14 +1,14 @@ require_relative "lib/houdini_upgrade/version" Gem::Specification.new do |spec| - spec.name = "houdini_upgrade" - spec.version = HoudiniUpgrade::VERSION - spec.authors = ["The Houdini Project"] - spec.email = [""] - spec.homepage = "https://houdiniproject.org" - spec.summary = "" + spec.name = "houdini_upgrade" + spec.version = HoudiniUpgrade::VERSION + spec.authors = ["The Houdini Project"] + spec.email = [""] + spec.homepage = "https://houdiniproject.org" + spec.summary = "" spec.description = "" - spec.license = "AGPL-3.0-or-later WITH WTO-AP-3.0-or-later" + spec.license = "AGPL-3.0-or-later WITH WTO-AP-3.0-or-later" # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' # to allow pushing to a single host or delete this section to allow pushing to any host. diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/cw_to_activestorage_generator.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/cw_to_activestorage_generator.rb index 4cc00b2f45..3eb77d56d9 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/cw_to_activestorage_generator.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/cw_to_activestorage_generator.rb @@ -1,19 +1,19 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class CwToActivestorageGenerator < Rails::Generators::Base - source_root File.expand_path('templates', __dir__) + source_root File.expand_path("templates", __dir__) class_option :aws_bucket, type: :string, required: true class_option :aws_region, type: :string, required: false class_option :aws_assethost, type: :string, required: false - + def add_carrierwave_gems gem "carrierwave", "~> 1" gem "carrierwave-aws" end def copy_uploaders - if (!File.exists?('app/uploaders')) - directory 'uploaders', 'app/uploaders' + if !File.exist?("app/uploaders") + directory "uploaders", "app/uploaders" end end @@ -21,24 +21,24 @@ def include_uploaders file_and_search = [ ["campaign.rb", "class Campaign < ApplicationRecord"], ["profile.rb", "class Profile < ApplicationRecord"], - ['nonprofit.rb', "class Nonprofit < ApplicationRecord"], - ['image_attachment.rb', "class ImageAttachment < ApplicationRecord"], - ['event.rb', "class Event < ApplicationRecord"] + ["nonprofit.rb", "class Nonprofit < ApplicationRecord"], + ["image_attachment.rb", "class ImageAttachment < ApplicationRecord"], + ["event.rb", "class Event < ApplicationRecord"] ] file_and_search - .select{|filename, _| !File.read("app/models/#{filename}").include?('###MIGRATION_FIELDS_BEGIN')} + .select { |filename, _| !File.read("app/models/#{filename}").include?("###MIGRATION_FIELDS_BEGIN") } .each do |filename, find_string| - gsub_file("app/models/#{filename}",find_string ) do |match| - match << "\n" - match << File.read(Pathname(File.expand_path('templates', __dir__, )) + 'models' + "#{filename}") - end + gsub_file("app/models/#{filename}", find_string) do |match| + match << "\n" + match << File.read(Pathname(File.expand_path("templates", __dir__)) + "models" + "#{filename}") + end end end def create_column_migration_file - if (Dir.glob("db/migrate/*_rename_uploader_columns.houdini_upgrade.rb").none?) - copy_file "migrate/rename_uploader_columns.rb", - "db/migrate/#{(DateTime.now.utc + 1.second).strftime('%Y%m%d%H%M%S')}_rename_uploader_columns.houdini_upgrade.rb" + if Dir.glob("db/migrate/*_rename_uploader_columns.houdini_upgrade.rb").none? + copy_file "migrate/rename_uploader_columns.rb", + "db/migrate/#{(DateTime.now.utc + 1.second).strftime("%Y%m%d%H%M%S")}_rename_uploader_columns.houdini_upgrade.rb" end end @@ -46,6 +46,6 @@ def add_carrierwave_template @aws_bucket = options[:aws_bucket] @aws_region = options[:aws_region] @aws_assethost = options[:aws_assethost] || "https://#{@aws_bucket}.s3.amazonaws.com" - template 'initializers/carrierwave.rb', 'config/initializers/carrierwave.rb' + template "initializers/carrierwave.rb", "config/initializers/carrierwave.rb" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/migrate/rename_uploader_columns.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/migrate/rename_uploader_columns.rb index 6049e339f7..db9027d0b4 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/migrate/rename_uploader_columns.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/migrate/rename_uploader_columns.rb @@ -1,12 +1,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class RenameUploaderColumns < ActiveRecord::Migration[5.2] - def change - require "houdini_upgrade" - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| - table.fields.each do |field| - rename_column table.name, field.name, field.migrated_name - end - end + def change + require "houdini_upgrade" + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| + table.fields.each do |field| + rename_column table.name, field.name, field.migrated_name + end end -end \ No newline at end of file + end +end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/campaign.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/campaign.rb index ce91277f1d..668e6754b1 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/campaign.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/campaign.rb @@ -1,5 +1,5 @@ -###MIGRATION_FIELDS_BEGIN +# ##MIGRATION_FIELDS_BEGIN mount_uploader :main_image_temp, CampaignMainImageUploader mount_uploader :background_image_temp, CampaignBackgroundImageUploader mount_uploader :banner_image_temp, CampaignBannerImageUploader -###MIGRATION_FIELDS_END \ No newline at end of file +# ##MIGRATION_FIELDS_END diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/event.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/event.rb index 5d39c7281b..c68936e238 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/event.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/event.rb @@ -1,4 +1,4 @@ -###MIGRATION_FIELDS_BEGIN +# ##MIGRATION_FIELDS_BEGIN mount_uploader :main_image_temp, EventMainImageUploader mount_uploader :background_image_temp, EventBackgroundImageUploader -###MIGRATION_FIELDS_END \ No newline at end of file +# ##MIGRATION_FIELDS_END diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/image_attachment.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/image_attachment.rb index 561ab5f3bb..d35b2f37fa 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/image_attachment.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/image_attachment.rb @@ -1,3 +1,3 @@ -###MIGRATION_FIELDS_BEGIN +# ##MIGRATION_FIELDS_BEGIN mount_uploader :file_temp, ImageAttachmentUploader -###MIGRATION_FIELDS_END \ No newline at end of file +# ##MIGRATION_FIELDS_END diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/nonprofit.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/nonprofit.rb index c3fe1c4681..3b0b87a16d 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/nonprofit.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/nonprofit.rb @@ -1,7 +1,7 @@ -###MIGRATION_FIELDS_BEGIN +# ##MIGRATION_FIELDS_BEGIN mount_uploader :main_image_temp, NonprofitUploader mount_uploader :second_image_temp, NonprofitUploader mount_uploader :third_image_temp, NonprofitUploader mount_uploader :background_image_temp, NonprofitBackgroundUploader mount_uploader :logo_temp, NonprofitLogoUploader -###MIGRATION_FIELDS_END \ No newline at end of file +# ##MIGRATION_FIELDS_END diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/profile.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/profile.rb index 31bee3d27b..b28e979373 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/profile.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/models/profile.rb @@ -1,3 +1,3 @@ -###MIGRATION_FIELDS_BEGIN +# ##MIGRATION_FIELDS_BEGIN mount_uploader :picture_temp, ProfileUploader -###MIGRATION_FIELDS_END \ No newline at end of file +# ##MIGRATION_FIELDS_END diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_background_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_background_uploader.rb index 7bf6dd2568..a8b1594c1c 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_background_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_background_uploader.rb @@ -50,6 +50,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_uploader.rb index 7362f61483..53d556923b 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/article_uploader.rb @@ -50,6 +50,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_background_image_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_background_image_uploader.rb index f7eea1feab..65248aece5 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_background_image_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_background_image_uploader.rb @@ -21,6 +21,6 @@ def extension_white_list end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_banner_image_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_banner_image_uploader.rb index 5ba607874a..ccba74130e 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_banner_image_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_banner_image_uploader.rb @@ -14,6 +14,6 @@ def extension_white_list end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_main_image_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_main_image_uploader.rb index f355058dd3..07d1a9bd32 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_main_image_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/campaign_main_image_uploader.rb @@ -52,6 +52,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_background_image_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_background_image_uploader.rb index 59742957bd..de41f3d603 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_background_image_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_background_image_uploader.rb @@ -21,7 +21,7 @@ def store_dir def default_url # For Rails 3.1+ asset pipeline compatibility: Image::DefaultCampaignUrl - end + end # Process files as they are uploaded: # process :scale => [200, 300] @@ -48,6 +48,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_main_image_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_main_image_uploader.rb index 156a66edcc..16e0a27f52 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_main_image_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/event_main_image_uploader.rb @@ -21,7 +21,7 @@ def store_dir def default_url # For Rails 3.1+ asset pipeline compatibility: Image::DefaultProfileUrl - end + end # Process files as they are uploaded: # process :scale => [200, 300] @@ -52,6 +52,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/image_attachment_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/image_attachment_uploader.rb index 00cb864f56..6cb3862aee 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/image_attachment_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/image_attachment_uploader.rb @@ -23,7 +23,7 @@ def store_dir def default_url # For Rails 3.1+ asset pipeline compatibility: Image::DefaultProfileUrl - end + end # Process files as they are uploaded: # process :scale => [200, 300] @@ -60,6 +60,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_background_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_background_uploader.rb index ba8eeeea85..415f638858 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_background_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_background_uploader.rb @@ -24,7 +24,7 @@ def store_dir def default_url # For Rails 3.1+ asset pipeline compatibility: Image::DefaultNonprofitUrl - end + end # Process files as they are uploaded: # process :scale => [200, 300] @@ -51,6 +51,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_logo_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_logo_uploader.rb index d361a81320..d7882b4d75 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_logo_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_logo_uploader.rb @@ -47,6 +47,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_uploader.rb index b95b568a8c..0e168102d0 100755 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/nonprofit_uploader.rb @@ -57,6 +57,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/profile_uploader.rb b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/profile_uploader.rb index 0718527135..95608bc72b 100644 --- a/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/profile_uploader.rb +++ b/gems/houdini_upgrade/lib/generators/cw_to_activestorage/templates/uploaders/profile_uploader.rb @@ -56,6 +56,6 @@ def extension_white_list # end def cache_dir - "#{Rails.root}/tmp/uploads" + "#{Rails.root.join("tmp/uploads")}" end end diff --git a/gems/houdini_upgrade/lib/houdini_upgrade.rb b/gems/houdini_upgrade/lib/houdini_upgrade.rb index 05e117b865..27ace2a607 100644 --- a/gems/houdini_upgrade/lib/houdini_upgrade.rb +++ b/gems/houdini_upgrade/lib/houdini_upgrade.rb @@ -5,16 +5,16 @@ require "houdini_upgrade/engine" module HoudiniUpgrade - require 'houdini_upgrade/table_to_migrate' + require "houdini_upgrade/table_to_migrate" UPLOADERS_TO_MIGRATE = [ - TableToMigrate.new(:nonprofits, [:main_image, - :second_image, - :third_image, - :background_image, + TableToMigrate.new(:nonprofits, [:main_image, + :second_image, + :third_image, + :background_image, :logo]), TableToMigrate.new(:campaigns, [ - :main_image, - :background_image, + :main_image, + :background_image, :banner_image ]), TableToMigrate.new(:events, [ diff --git a/gems/houdini_upgrade/lib/houdini_upgrade/column_to_migrate.rb b/gems/houdini_upgrade/lib/houdini_upgrade/column_to_migrate.rb index e1eac3a073..215071c456 100644 --- a/gems/houdini_upgrade/lib/houdini_upgrade/column_to_migrate.rb +++ b/gems/houdini_upgrade/lib/houdini_upgrade/column_to_migrate.rb @@ -3,14 +3,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module HoudiniUpgrade - class ColumnToMigrate - attr_reader :name - def initialize(original_column_name) - @name = original_column_name.to_s - end + class ColumnToMigrate + attr_reader :name + def initialize(original_column_name) + @name = original_column_name.to_s + end - def migrated_name - @name + "_temp" - end + def migrated_name + @name + "_temp" end -end \ No newline at end of file + end +end diff --git a/gems/houdini_upgrade/lib/houdini_upgrade/table_to_migrate.rb b/gems/houdini_upgrade/lib/houdini_upgrade/table_to_migrate.rb index e5a777c528..16f796e693 100644 --- a/gems/houdini_upgrade/lib/houdini_upgrade/table_to_migrate.rb +++ b/gems/houdini_upgrade/lib/houdini_upgrade/table_to_migrate.rb @@ -2,25 +2,25 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative "./column_to_migrate" +require_relative "column_to_migrate" module HoudiniUpgrade - class TableToMigrate - attr_reader :fields, :name - def initialize(original_table_name, original_field_names) - @name = original_table_name.to_s - @fields = original_field_names.map{|i| ColumnToMigrate.new(i)} - end + class TableToMigrate + attr_reader :fields, :name + def initialize(original_table_name, original_field_names) + @name = original_table_name.to_s + @fields = original_field_names.map { |i| ColumnToMigrate.new(i) } + end - def class_name - @name.classify - end + def class_name + @name.classify + end - def backup_table - @name + "_uploader_backups" - end + def backup_table + @name + "_uploader_backups" + end - def foreign_key - @name + "_id" - end + def foreign_key + @name + "_id" end -end \ No newline at end of file + end +end diff --git a/gems/houdini_upgrade/lib/houdini_upgrade/version.rb b/gems/houdini_upgrade/lib/houdini_upgrade/version.rb index 7bf00b34c3..c3c9e2b598 100644 --- a/gems/houdini_upgrade/lib/houdini_upgrade/version.rb +++ b/gems/houdini_upgrade/lib/houdini_upgrade/version.rb @@ -3,5 +3,5 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module HoudiniUpgrade - VERSION = '0.1.0' + VERSION = "0.1.0" end diff --git a/gems/houdini_upgrade/lib/tasks/houdini_upgrade_tasks.rake b/gems/houdini_upgrade/lib/tasks/houdini_upgrade_tasks.rake index 25132ce9a2..67952b59d0 100644 --- a/gems/houdini_upgrade/lib/tasks/houdini_upgrade_tasks.rake +++ b/gems/houdini_upgrade/lib/tasks/houdini_upgrade_tasks.rake @@ -6,8 +6,8 @@ class ProgressBar attr_reader :total, :counter def initialize(total, description) - @description = description - @total = total + @description = description + @total = total @counter = 1 end @@ -16,7 +16,7 @@ class ProgressBar @counter += 1 end - def print_out + def print_out complete = sprintf("%#.2f%%", ((@counter.to_f / @total.to_f) * 100)) print "\r\e[0K#{@description} #{@counter}/#{@total} (#{complete})" end @@ -27,26 +27,26 @@ class ProgressBar end end - namespace :houdini_upgrade do +namespace :houdini_upgrade do Rake::Task["install:migrations"].clear_comments - desc <<-RUBY -Run houdini upgrade to v2 -DESC: - This task automates some of the process of upgrading to Houdini v2. It does - the following: - * installs and runs database migrations - * migrates images from Carrierwave on AWS to your default ActiveStorage service - -USAGE: bin/rails houdini_upgrade:run[aws_bucket,aws_region] - -TASK ARGUMENTS: - aws_bucket (required): the name of your AWS bucket where all your carrierwave images are hosted - aws_region (required): AWS region of your AWS bucket. Carrierwave won\'t work - without it. - aws_assethost: protocol and domain where your AWS bucket contents can be - accessed. For example, this could be through Cloudfront - shorter_test: a testing only argument which cuts down the number of images we copy -RUBY + desc <<~RUBY + Run houdini upgrade to v2 + DESC: + This task automates some of the process of upgrading to Houdini v2. It does + the following: + * installs and runs database migrations + * migrates images from Carrierwave on AWS to your default ActiveStorage service + + USAGE: bin/rails houdini_upgrade:run[aws_bucket,aws_region] + + TASK ARGUMENTS: + aws_bucket (required): the name of your AWS bucket where all your carrierwave images are hosted + aws_region (required): AWS region of your AWS bucket. Carrierwave won't work + without it. + aws_assethost: protocol and domain where your AWS bucket contents can be + accessed. For example, this could be through Cloudfront + shorter_test: a testing only argument which cuts down the number of images we copy + RUBY task :run, [:aws_bucket, :aws_region, :aws_assethost, :shorter_test] do |t, args| if args[:aws_bucket].blank? || args[:aws_region].blank? puts "You must set aws_bucket and aws_region for houdini_upgrade:run like:" @@ -56,9 +56,9 @@ RUBY puts "visit `docs/houdini_upgrade.md`" else Rake::Task["houdini_upgrade:install:migrations"].invoke - sh 'rails active_storage:install' + sh "rails active_storage:install" Rake::Task["houdini_upgrade:cw_to_activestorage"].invoke(*args) - sh 'bundle' + sh "bundle" Rake::Task["db:migrate"].invoke migrate_upload_command = "rails houdini_upgrade:migrate_uploads" if args[:shorter_test] @@ -68,15 +68,15 @@ RUBY Rake::Task["houdini_upgrade:create_backup_uploader_migration"].invoke sh "rails db:migrate" Rake::Task["houdini_upgrade:cleanup_upgrade_files"].invoke - sh 'bundle' + sh "bundle" end end task :cw_to_activestorage, [:aws_bucket, :aws_region, :aws_assethost] do |t, args| tail = ["--aws-bucket=#{args[:aws_bucket]}", "--aws-region=#{args[:aws_region]}"] - + tail.push("--aws-assethost=#{args[:aws_assethost]}") if args[:aws_assethost] - sh "rails generate cw_to_activestorage #{tail.join(' ')}" + sh "rails generate cw_to_activestorage #{tail.join(" ")}" end desc "Migrate your CarrierWave uploads to activestorage" @@ -87,7 +87,7 @@ RUBY # find activerecord descendents HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| klass = table.class_name.constantize - items_to_migrate = klass.where(table.fields.map{|i| i.migrated_name + " IS NOT NULL"}.join(" OR ")) + items_to_migrate = klass.where(table.fields.map { |i| i.migrated_name + " IS NOT NULL" }.join(" OR ")) if args[:shorter_test] items_to_migrate = items_to_migrate.limit(10) end @@ -95,7 +95,6 @@ RUBY items_to_migrate .find_each do |record| table.fields.each do |field| - if record.send(field.migrated_name + "?") results << process(upload_url: record.send(field.migrated_name).url.gsub(/\/#{field.migrated_name}\//, "/#{field.name}/"), attachment_name: field.name, record: record) end @@ -104,17 +103,17 @@ RUBY end end - copied = results.select{|i| i[:success]}.map{|i| i[:value]} - errors = results.select{|i| !i[:success]}.map{|i| i[:value]} + copied = results.select { |i| i[:success] }.map { |i| i[:value] } + errors = results.select { |i| !i[:success] }.map { |i| i[:value] } - CSV.open("#{DateTime.now.utc.strftime('%Y%m%d%H%M%S')}_copied.csv", 'wb') do |csv| - csv << ['Class Name', 'Id', "UploaderName", "FileToOpen"] - copied.each {|row| csv << row} + CSV.open("#{DateTime.now.utc.strftime("%Y%m%d%H%M%S")}_copied.csv", "wb") do |csv| + csv << ["Class Name", "Id", "UploaderName", "FileToOpen"] + copied.each { |row| csv << row } end - CSV.open("#{DateTime.now.utc.strftime('%Y%m%d%H%M%S')}_errored.csv", 'wb') do |csv| - csv << ['Class Name', 'Id', "UploaderName", "FileToOpen", "Error"] - errors.each {|row| csv << row} + CSV.open("#{DateTime.now.utc.strftime("%Y%m%d%H%M%S")}_errored.csv", "wb") do |csv| + csv << ["Class Name", "Id", "UploaderName", "FileToOpen", "Error"] + errors.each { |row| csv << row } end puts "Copied: #{copied.count}" @@ -126,48 +125,48 @@ RUBY begin if args[:upload_url] filename = File.basename(URI.parse(args[:upload_url]).to_s) - file_to_open = args[:upload_url].start_with?('/') ? "." + args[:upload_url] : args[:upload_url] - - if (!args[:simulate]) - attachment_relation = args[:record].send("#{args[:attachment_name].to_s}") - attachment_relation.attach(io: open(file_to_open), filename: filename) + file_to_open = args[:upload_url].start_with?("/") ? "." + args[:upload_url] : args[:upload_url] + + if !args[:simulate] + attachment_relation = args[:record].send("#{args[:attachment_name]}") + attachment_relation.attach(io: open(file_to_open), filename: filename) end - return {success: true, value: [args[:record].class.name, args[:record].id, args[:attachment_name],file_to_open]} + return {success: true, value: [args[:record].class.name, args[:record].id, args[:attachment_name], file_to_open]} end - return nil + nil rescue => e - return {success: false, value: [args[:record].class.name, args[:record].id, args[:attachment_name], file_to_open, e]} + {success: false, value: [args[:record].class.name, args[:record].id, args[:attachment_name], file_to_open, e]} end end task :create_backup_uploader_migration do - if (Dir.glob("db/migrate/*_backup_uploader_columns.houdini_upgrade.rb").none?) - FileUtils.cp __dir__ + "/templates/backup_uploader_columns.rb", - "db/migrate/#{(DateTime.now.utc + 1.second).strftime('%Y%m%d%H%M%S')}_backup_uploader_columns.houdini_upgrade.rb" + if Dir.glob("db/migrate/*_backup_uploader_columns.houdini_upgrade.rb").none? + FileUtils.cp __dir__ + "/templates/backup_uploader_columns.rb", + "db/migrate/#{(DateTime.now.utc + 1.second).strftime("%Y%m%d%H%M%S")}_backup_uploader_columns.houdini_upgrade.rb" end end task :delete_uploader_backup_tables_migration do - if (Dir.glob("db/migrate/*_backup_uploader_columns.houdini_upgrade.rb").none?) - FileUtils.cp __dir + "/templates/delete_uploader_backup_tables.rb", - "db/migrate/#{(DateTime.now.utc + 1.second).strftime('%Y%m%d%H%M%S')}_delete_uploader_backup_tables.houdini_upgrade.rb" + if Dir.glob("db/migrate/*_backup_uploader_columns.houdini_upgrade.rb").none? + FileUtils.cp __dir + "/templates/delete_uploader_backup_tables.rb", + "db/migrate/#{(DateTime.now.utc + 1.second).strftime("%Y%m%d%H%M%S")}_delete_uploader_backup_tables.houdini_upgrade.rb" end end task :cleanup_upgrade_files do - FileUtils.rm_r "app/uploaders" if (File.exists?("app/uploaders")) - FileUtils.rm "config/initializers/carrierwave.rb" if (File.exists?("config/initializers/carrierwave.rb")) - gemfile_lines = File.readlines("Gemfile").select{|i| !i.include?("gem 'carrierwave'") && !i.include?("gem 'carrierwave-aws'")} - File.write('Gemfile', gemfile_lines.join()) + FileUtils.rm_r "app/uploaders" if File.exist?("app/uploaders") + FileUtils.rm "config/initializers/carrierwave.rb" if File.exist?("config/initializers/carrierwave.rb") + gemfile_lines = File.readlines("Gemfile").select { |i| !i.include?("gem 'carrierwave'") && !i.include?("gem 'carrierwave-aws'") } + File.write("Gemfile", gemfile_lines.join) cleanup_model_files end def cleanup_model_files - filename_roots = HoudiniUpgrade::UPLOADERS_TO_MIGRATE.map{|i| i.name.singularize} + filename_roots = HoudiniUpgrade::UPLOADERS_TO_MIGRATE.map { |i| i.name.singularize } filename_roots.each do |f| filename = "app/models/#{f}.rb" file_contents = File.read(filename) - file_contents = file_contents.sub(/\n\#\#\#MIGRATION_FIELDS_BEGIN(.*)\#\#\#MIGRATION_FIELDS_END/mx, '') + file_contents = file_contents.sub(/\n\#\#\#MIGRATION_FIELDS_BEGIN(.*)\#\#\#MIGRATION_FIELDS_END/mx, "") File.write(filename, file_contents) end end diff --git a/gems/houdini_upgrade/lib/tasks/templates/backup_uploader_columns.rb b/gems/houdini_upgrade/lib/tasks/templates/backup_uploader_columns.rb index 3bdec1794a..019ed49fd1 100644 --- a/gems/houdini_upgrade/lib/tasks/templates/backup_uploader_columns.rb +++ b/gems/houdini_upgrade/lib/tasks/templates/backup_uploader_columns.rb @@ -1,52 +1,51 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class BackupUploaderColumns < ActiveRecord::Migration[5.2] - def up - # copy all - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |uploader_table| - create_table uploader_table.backup_table do |table| - table.references uploader_table.name, foreign_key: true, index: { name: "idx_#{uploader_table.backup_table}_on_fk"} - uploader_table.fields.each do |f| - table.string f.migrated_name - end - end - end - - # copy all - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| - execute <<-SQL - INSERT INTO #{table.backup_table} (#{table.foreign_key}, #{table.fields.map(&:migrated_name).join(', ')}) - ( SELECT id, #{table.fields.map(&:migrated_name).join(', ')} FROM #{table.name}) - SQL + def up + # copy all + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |uploader_table| + create_table uploader_table.backup_table do |table| + table.references uploader_table.name, foreign_key: true, index: {name: "idx_#{uploader_table.backup_table}_on_fk"} + uploader_table.fields.each do |f| + table.string f.migrated_name end + end + end - # delete columns - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| - table.fields.each do |f| - remove_column table.name, f.migrated_name - end - end + # copy all + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| + execute <<-SQL + INSERT INTO #{table.backup_table} (#{table.foreign_key}, #{table.fields.map(&:migrated_name).join(", ")}) + ( SELECT id, #{table.fields.map(&:migrated_name).join(", ")} FROM #{table.name}) + SQL end - def down - ## readd columns - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| - table.fields.each do |f| - add_column table.name, f.migrated_name, :string - end - end + # delete columns + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| + table.fields.each do |f| + remove_column table.name, f.migrated_name + end + end + end + + def down + ## readd columns + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| + table.fields.each do |f| + add_column table.name, f.migrated_name, :string + end + end - # copy all - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| - execute <<-SQL - UPDATE #{table.name} SET (#{table.fields.map(&:migrated_name).join(', ')}) = ( - SELECT #{table.fields.map{|f| table.backup_table + "." + f.migrated_name}.join(', ')} FROM #{table.backup_table} + # copy all + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each do |table| + execute <<-SQL + UPDATE #{table.name} SET (#{table.fields.map(&:migrated_name).join(", ")}) = ( + SELECT #{table.fields.map { |f| table.backup_table + "." + f.migrated_name }.join(", ")} FROM #{table.backup_table} WHERE #{table.backup_table}.#{table.foreign_key} = #{table.name}.id ) - SQL - end - # delete tables - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each{ |entity, _| drop_table entity.backup_table} - + SQL end -end \ No newline at end of file + # delete tables + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each { |entity, _| drop_table entity.backup_table } + end +end diff --git a/gems/houdini_upgrade/lib/tasks/templates/delete_uploader_backup_tables.rb b/gems/houdini_upgrade/lib/tasks/templates/delete_uploader_backup_tables.rb index 474f73d0ab..865cc49d92 100644 --- a/gems/houdini_upgrade/lib/tasks/templates/delete_uploader_backup_tables.rb +++ b/gems/houdini_upgrade/lib/tasks/templates/delete_uploader_backup_tables.rb @@ -1,8 +1,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class DeleteUploaderBackupTables < ActiveRecord::Migration[5.2] - def up - # delete tables - HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each{ |table| drop_table table.backup_table} - end -end \ No newline at end of file + def up + # delete tables + HoudiniUpgrade::UPLOADERS_TO_MIGRATE.each { |table| drop_table table.backup_table } + end +end diff --git a/gems/ruby-param-validation/Rakefile b/gems/ruby-param-validation/Rakefile index dc5d58182f..7ffc607d53 100644 --- a/gems/ruby-param-validation/Rakefile +++ b/gems/ruby-param-validation/Rakefile @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'rake/testtask' +require "rake/testtask" Rake::TestTask.new do |t| - t.libs << 'test' - t.test_files = FileList['test/test*.rb', 'test/*test.rb'] + t.libs << "test" + t.test_files = FileList["test/test*.rb", "test/*test.rb"] end -desc 'Run tests' +desc "Run tests" task default: :test diff --git a/gems/ruby-param-validation/lib/param_validation.rb b/gems/ruby-param-validation/lib/param_validation.rb index 2835763dd9..2d7bdc2b1c 100644 --- a/gems/ruby-param-validation/lib/param_validation.rb +++ b/gems/ruby-param-validation/lib/param_validation.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'json' -require 'chronic' +require "json" +require "chronic" class ParamValidation # Given a hash of data and a validation hash, check all the validations, raising an Error on the first invalid key @@ -9,7 +9,7 @@ class ParamValidation def initialize(data, validations) errors = [] validations.each do |key, validators| - val = key === :root ? data : (data[key] || data[key.to_s] || data[key.to_sym]) + val = (key === :root) ? data : (data[key] || data[key.to_s] || data[key.to_sym]) next if validators[:required].nil? && val.nil? validators.each do |name, arg| @@ -20,7 +20,7 @@ def initialize(data, validations) is_valid = @@validators[name].call(val, arg, data) msg_proc = @@messages[name] msg ||= @@messages[name].call(key: key, data: data, val: val, arg: arg) if msg_proc - errors.push(msg: msg, data: { key: key, val: val, name: name, msg: msg }) unless is_valid + errors.push(msg: msg, data: {key: key, val: val, name: name, msg: msg}) unless is_valid end end if errors.length == 1 @@ -65,80 +65,80 @@ def self.add_structure_validator(name, &block) not_blank: ->(val, _arg, _data) { val.is_a?(String) && !val.empty? }, not_included_in: lambda { |val, arg, _data| begin - !arg.include?(val) - rescue StandardError + !arg.include?(val) + rescue false - end + end }, included_in: lambda { |val, arg, _data| begin - arg.include?(val) - rescue StandardError + arg.include?(val) + rescue false - end + end }, format: lambda { |val, arg, _data| begin - val =~ arg - rescue StandardError + val =~ arg + rescue false - end + end }, is_integer: ->(val, _arg, _data) { val.is_a?(Integer) || val =~ /\A[+-]?\d+\Z/ }, is_float: lambda { |val, _arg, _data| val.is_a?(Float) || (begin - !!Float(val) - rescue StandardError - false - end) + !!Float(val) + rescue + false + end) }, min_length: lambda { |val, arg, _data| begin - val.length >= arg - rescue StandardError + val.length >= arg + rescue false - end + end }, max_length: lambda { |val, arg, _data| begin - val.length <= arg - rescue StandardError + val.length <= arg + rescue false - end + end }, length_range: lambda { |val, arg, _data| begin - arg.cover?(val.length) - rescue StandardError + arg.cover?(val.length) + rescue false - end + end }, length_equals: ->(val, arg, _data) { val.length == arg }, - is_reference: ->(val, _arg, _data) { (val.is_a?(Integer) && val >= 0) || val =~ /\A\d+\Z/ || val == '' }, + is_reference: ->(val, _arg, _data) { (val.is_a?(Integer) && val >= 0) || val =~ /\A\d+\Z/ || val == "" }, equals: ->(val, arg, _data) { val == arg }, min: lambda { |val, arg, _data| begin - val >= arg - rescue StandardError + val >= arg + rescue false - end + end }, max: lambda { |val, arg, _data| begin - val <= arg - rescue StandardError + val <= arg + rescue false - end + end }, is_array: ->(val, _arg, _data) { val.is_a?(Array) }, is_hash: ->(val, _arg, _data) { val.is_a?(Hash) }, is_json: ->(val, _arg, _data) { ParamValidation.is_valid_json?(val) }, in_range: lambda { |val, arg, _data| begin - arg.cover?(val) - rescue StandardError + arg.cover?(val) + rescue false - end + end }, is_a: ->(val, arg, _data) { arg.is_a?(Enumerable) ? arg.any? { |i| val.is_a?(i) } : val.is_a?(arg) }, can_be_date: ->(val, _arg, _data) { val.is_a?(Date) || val.is_a?(DateTime) || Chronic.parse(val) }, @@ -149,8 +149,8 @@ def self.add_structure_validator(name, &block) required: ->(h) { "#{h[:key]} is required" }, absent: ->(h) { "#{h[:key]} must not be present" }, not_blank: ->(h) { "#{h[:key]} must not be blank" }, - not_included_in: ->(h) { "#{h[:key]} must not be included in #{h[:arg].join(', ')}" }, - included_in: ->(h) { "#{h[:key]} must be one of #{h[:arg].join(', ')}" }, + not_included_in: ->(h) { "#{h[:key]} must not be included in #{h[:arg].join(", ")}" }, + included_in: ->(h) { "#{h[:key]} must be one of #{h[:arg].join(", ")}" }, format: ->(h) { "#{h[:key]} doesn't have the right format" }, is_integer: ->(h) { "#{h[:key]} should be an integer" }, is_float: ->(h) { "#{h[:key]} should be a float" }, @@ -165,16 +165,16 @@ def self.add_structure_validator(name, &block) in_range: ->(h) { "#{h[:key]} should be within #{h[:arg]}" }, is_json: ->(h) { "#{h[:key]} should be valid JSON" }, is_hash: ->(h) { "#{h[:key]} should be a hash" }, - is_a: ->(h) { "#{h[:key]} should be of the type(s): #{h[:arg].is_a?(Enumerable) ? h[:arg].join(', ') : h[:arg]}" }, + is_a: ->(h) { "#{h[:key]} should be of the type(s): #{h[:arg].is_a?(Enumerable) ? h[:arg].join(", ") : h[:arg]}" }, can_be_date: ->(h) { "#{h[:key]} should be a datetime or be parsable as one" }, - array_of_hashes: ->(_h) { 'Please pass in an array of hashes' } + array_of_hashes: ->(_h) { "Please pass in an array of hashes" } } # small utility for testing json validity def self.is_valid_json?(str) JSON.parse(str) true - rescue StandardError => e + rescue false end diff --git a/gems/ruby-param-validation/param_validation.gemspec b/gems/ruby-param-validation/param_validation.gemspec index 751a4c8fe7..5e69d5feac 100644 --- a/gems/ruby-param-validation/param_validation.gemspec +++ b/gems/ruby-param-validation/param_validation.gemspec @@ -1,16 +1,15 @@ # frozen_string_literal: true Gem::Specification.new do |s| - s.name = 'param_validation' - s.version = '0.0.2' - s.date = '2017-07-21' - s.summary = 'Simple hash validator' - s.description = 'A hash validator that throws exceptions, with a lot of customization options' - s.authors = ['Jay R Bolton'] - s.email = 'jayrbolton@gmail.com' - s.files = 'lib/param_validation.rb' - s.homepage = 'https://github.com/jayrbolton/ruby-param-validation' - s.license = 'MIT' + s.name = "param_validation" + s.version = "0.0.2" + s.summary = "Simple hash validator" + s.description = "A hash validator that throws exceptions, with a lot of customization options" + s.authors = ["Jay R Bolton"] + s.email = "jayrbolton@gmail.com" + s.files = "lib/param_validation.rb" + s.homepage = "https://github.com/jayrbolton/ruby-param-validation" + s.license = "MIT" - s.add_runtime_dependency 'chronic' + s.add_runtime_dependency "chronic" end diff --git a/gems/ruby-param-validation/test/param_validation_test.rb b/gems/ruby-param-validation/test/param_validation_test.rb index cafe843520..cf03599ecb 100644 --- a/gems/ruby-param-validation/test/param_validation_test.rb +++ b/gems/ruby-param-validation/test/param_validation_test.rb @@ -1,219 +1,220 @@ # frozen_string_literal: true -require './lib/param_validation.rb' -require 'minitest/autorun' +require "./lib/param_validation" +require "minitest/autorun" class ParamValidationTest < Minitest::Test - def setup; end + def setup + end def test_required - begin; ParamValidation.new({}, x: { required: true }) + begin; ParamValidation.new({}, x: {required: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end # If a key is not required, then don't run the tests on it def test_not_required_and_absent_then_tests_do_not_run - ParamValidation.new({}, x: { max: 100 }) + ParamValidation.new({}, x: {max: 100}) assert true end def test_not_blank_fail - begin; ParamValidation.new({ x: '' }, x: { not_blank: true }) + begin; ParamValidation.new({x: ""}, x: {not_blank: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_not_blank_fail_nil - begin; ParamValidation.new({ x: nil }, x: { not_blank: true, required: true }) + begin; ParamValidation.new({x: nil}, x: {not_blank: true, required: true}) rescue ParamValidation::ValidationError => e; e; end assert(e.data.one? { |i| i[:name] == :not_blank && i[:key] == :x }) assert(e.data.one? { |i| i[:name] == :required && i[:key] == :x }) end def test_not_blank_succeed - ParamValidation.new({ x: 'x' }, x: { not_blank: true }) + ParamValidation.new({x: "x"}, x: {not_blank: true}) assert true end def test_require_no_err - begin; ParamValidation.new({ x: 1 }, x: { required: true }) + begin; ParamValidation.new({x: 1}, x: {required: true}) rescue ParamValidation::ValidationError => e; end assert e.nil? end def test_absent - begin; ParamValidation.new({ x: 1 }, x: { absent: true }) + begin; ParamValidation.new({x: 1}, x: {absent: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_not_included_in - begin; ParamValidation.new({ x: 1 }, x: { not_included_in: [1] }) + begin; ParamValidation.new({x: 1}, x: {not_included_in: [1]}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_included_in - begin; ParamValidation.new({ x: 1 }, x: { included_in: [2] }) + begin; ParamValidation.new({x: 1}, x: {included_in: [2]}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_format - begin; ParamValidation.new({ x: 'x' }, x: { format: /y/ }) + begin; ParamValidation.new({x: "x"}, x: {format: /y/}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_reference_string - begin; ParamValidation.new({ x: '-0' }, x: { is_reference: true }) + begin; ParamValidation.new({x: "-0"}, x: {is_reference: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_reference_negative_integer - begin; ParamValidation.new({ x: -1 }, x: { is_reference: true }) + begin; ParamValidation.new({x: -1}, x: {is_reference: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_reference_passes - ParamValidation.new({ x: '0' }, x: { is_reference: true }) - ParamValidation.new({ x: 1 }, x: { is_reference: true }) - ParamValidation.new({ x: '' }, x: { is_reference: true }) + ParamValidation.new({x: "0"}, x: {is_reference: true}) + ParamValidation.new({x: 1}, x: {is_reference: true}) + ParamValidation.new({x: ""}, x: {is_reference: true}) pass end def test_is_integer - begin; ParamValidation.new({ x: 'x' }, x: { is_integer: true }) + begin; ParamValidation.new({x: "x"}, x: {is_integer: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_float - begin; ParamValidation.new({ x: 'x' }, x: { is_float: true }) + begin; ParamValidation.new({x: "x"}, x: {is_float: true}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_min_length - begin; ParamValidation.new({ x: [] }, x: { min_length: 2 }) + begin; ParamValidation.new({x: []}, x: {min_length: 2}) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_max_length - begin; ParamValidation.new({ x: [1, 2, 3] }, x: { max_length: 2 }) + begin; ParamValidation.new({x: [1, 2, 3]}, x: {max_length: 2}) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end def test_length_range - begin; ParamValidation.new({ x: [1, 2, 3, 4] }, x: { length_range: 1..3 }) + begin; ParamValidation.new({x: [1, 2, 3, 4]}, x: {length_range: 1..3}) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end def test_length_equals - begin; ParamValidation.new({ x: [1, 2] }, x: { length_equals: 1 }) + begin; ParamValidation.new({x: [1, 2]}, x: {length_equals: 1}) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end def test_min - begin; ParamValidation.new({ x: 1 }, x: { min: 2 }) + begin; ParamValidation.new({x: 1}, x: {min: 2}) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end def test_max - begin; ParamValidation.new({ x: 4 }, x: { max: 2 }) + begin; ParamValidation.new({x: 4}, x: {max: 2}) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:name], :max end def test_in_range - begin; ParamValidation.new({ x: 1 }, x: { in_range: 2..4 }) + begin; ParamValidation.new({x: 1}, x: {in_range: 2..4}) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:val], 1 end def test_equals - begin; ParamValidation.new({ x: 1 }, x: { equals: 2 }) + begin; ParamValidation.new({x: 1}, x: {equals: 2}) rescue ParamValidation::ValidationError => e; e; end - assert_equal 'x should equal 2', e.to_s + assert_equal "x should equal 2", e.to_s end def test_root_array_of_hashes - begin; ParamValidation.new({ x: 1 }, root: { array_of_hashes: { x: { required: true } } }) + begin; ParamValidation.new({x: 1}, root: {array_of_hashes: {x: {required: true}}}) rescue ParamValidation::ValidationError => e; e; end - assert_equal 'Please pass in an array of hashes', e.to_s + assert_equal "Please pass in an array of hashes", e.to_s end def test_root_array_of_hashes_with_nesting_ok - v = ParamValidation.new([{ 'x' => 1 }, { x: 1 }], root: { array_of_hashes: { x: { is_integer: true } } }) + v = ParamValidation.new([{"x" => 1}, {x: 1}], root: {array_of_hashes: {x: {is_integer: true}}}) assert_equal v, v # test that it does not raise end def test_root_array_of_hashes_with_nesting - begin; ParamValidation.new([{ x: 1 }, { x: 'hi' }], root: { array_of_hashes: { x: { is_integer: true } } }) + begin; ParamValidation.new([{x: 1}, {x: "hi"}], root: {array_of_hashes: {x: {is_integer: true}}}) rescue ParamValidation::ValidationError => e; e; end - assert_equal 'x should be an integer', e.to_s + assert_equal "x should be an integer", e.to_s end def test_is_json_with_string - begin; ParamValidation.new({ x: '[[[[[[[' }, x: { is_json: true }) + begin; ParamValidation.new({x: "[[[[[[["}, x: {is_json: true}) rescue ParamValidation::ValidationError => e; e; end - assert_equal 'x should be valid JSON', e.to_s + assert_equal "x should be valid JSON", e.to_s end def test_is_json_without_string - begin; ParamValidation.new({ x: {} }, x: { is_json: true }) + begin; ParamValidation.new({x: {}}, x: {is_json: true}) rescue ParamValidation::ValidationError => e; e; end - assert_equal 'x should be valid JSON', e.to_s + assert_equal "x should be valid JSON", e.to_s end def test_is_a_single - ParamValidation.new({ x: 5.6 }, x: { is_a: Float }) + ParamValidation.new({x: 5.6}, x: {is_a: Float}) begin - ParamValidation.new({ x: 5.6 }, x: { is_a: Integer }) + ParamValidation.new({x: 5.6}, x: {is_a: Integer}) rescue ParamValidation::ValidationError => e e end - assert_equal 'x should be of the type(s): Integer', e.to_s + assert_equal "x should be of the type(s): Integer", e.to_s end def test_is_a_multiple - ParamValidation.new({ x: 5.6 }, x: { is_a: [Integer, Float] }) + ParamValidation.new({x: 5.6}, x: {is_a: [Integer, Float]}) begin - ParamValidation.new({ x: 5.6 }, x: { is_a: [Integer, Array] }) + ParamValidation.new({x: 5.6}, x: {is_a: [Integer, Array]}) rescue ParamValidation::ValidationError => e e end - assert_equal 'x should be of the type(s): Integer, Array', e.to_s + assert_equal "x should be of the type(s): Integer, Array", e.to_s end def test_can_be_date - ParamValidation.new({ x: Date.new }, x: { can_be_date: true }) - ParamValidation.new({ x: DateTime.new }, x: { can_be_date: true }) - ParamValidation.new({ x: '2017-05-15T12:00:00.000Z' }, x: { can_be_date: true }) - ParamValidation.new({ x: '2017-05-15' }, x: { can_be_date: true }) + ParamValidation.new({x: Date.new}, x: {can_be_date: true}) + ParamValidation.new({x: DateTime.new}, x: {can_be_date: true}) + ParamValidation.new({x: "2017-05-15T12:00:00.000Z"}, x: {can_be_date: true}) + ParamValidation.new({x: "2017-05-15"}, x: {can_be_date: true}) begin - ParamValidation.new({ x: 'not_a _date' }, x: { can_be_date: true }) + ParamValidation.new({x: "not_a _date"}, x: {can_be_date: true}) rescue ParamValidation::ValidationError => e e end - assert_equal 'x should be a datetime or be parsable as one', e.to_s + assert_equal "x should be a datetime or be parsable as one", e.to_s end def test_add_validator ParamValidation.add_validator(:dollars) { |val, _arg, _data| val =~ /^\d+(\.\d\d)?$/ } begin - ParamValidation.new({ x: 'hi' }, x: { dollars: true }) + ParamValidation.new({x: "hi"}, x: {dollars: true}) rescue ParamValidation::ValidationError => e e end @@ -224,12 +225,13 @@ def test_set_message ParamValidation.add_validator(:dollars) { |val, _arg, _data| val =~ /^\d+(\.\d\d)?$/ } ParamValidation.set_message(:dollars) { |h| "#{h[:key]} must be a dollar amount" } begin - ParamValidation.new({ x: 'hi' }, x: { dollars: true }) + ParamValidation.new({x: "hi"}, x: {dollars: true}) rescue ParamValidation::ValidationError => e e end - assert_equal 'x must be a dollar amount', e.to_s + assert_equal "x must be a dollar amount", e.to_s end - def test_custom_validator; end + def test_custom_validator + end end diff --git a/gems/ruby-qx/lib/qx.rb b/gems/ruby-qx/lib/qx.rb index f5ee40e192..6141421db2 100644 --- a/gems/ruby-qx/lib/qx.rb +++ b/gems/ruby-qx/lib/qx.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require 'active_record' -require 'colorize' +require "active_record" +require "colorize" class Qx ## @@ -19,7 +19,6 @@ def self.config(h) # Qx.new, only used internally def initialize(tree) @tree = tree - self end def self.transaction(&block) @@ -29,27 +28,27 @@ def self.transaction(&block) end def self.parse_select(expr) - str = 'SELECT' + str = "SELECT" if expr[:DISTINCT_ON] - str += " DISTINCT ON (#{expr[:DISTINCT_ON].map(&:to_s).join(', ')})" + str += " DISTINCT ON (#{expr[:DISTINCT_ON].map(&:to_s).join(", ")})" elsif expr[:DISTINCT] - str += ' DISTINCT' + str += " DISTINCT" end - str += ' ' + expr[:SELECT].map { |expr| expr.is_a?(Qx) ? expr.parse : expr }.join(', ') - throw ArgumentError.new('FROM clause is missing for SELECT') unless expr[:FROM] - str += ' FROM ' + expr[:FROM] + str += " " + expr[:SELECT].map { |expr| expr.is_a?(Qx) ? expr.parse : expr }.join(", ") + throw ArgumentError.new("FROM clause is missing for SELECT") unless expr[:FROM] + str += " FROM " + expr[:FROM] str += expr[:JOIN].map { |from, cond| " JOIN #{from} ON #{cond}" }.join if expr[:JOIN] str += expr[:LEFT_JOIN].map { |from, cond| " LEFT JOIN #{from} ON #{cond}" }.join if expr[:LEFT_JOIN] str += expr[:LEFT_OUTER_JOIN].map { |from, cond| " LEFT OUTER JOIN #{from} ON #{cond}" }.join if expr[:LEFT_OUTER_JOIN] str += expr[:JOIN_LATERAL].map { |i| " JOIN LATERAL (#{i[:select_statement]}) #{i[:join_name]} ON #{i[:success_condition]}" }.join if expr[:JOIN_LATERAL] str += expr[:LEFT_JOIN_LATERAL].map { |i| " LEFT JOIN LATERAL (#{i[:select_statement]}) #{i[:join_name]} ON #{i[:success_condition]}" }.join if expr[:LEFT_JOIN_LATERAL] - str += ' WHERE ' + expr[:WHERE].map { |w| "(#{w})" }.join(' AND ') if expr[:WHERE] - str += ' GROUP BY ' + expr[:GROUP_BY].join(', ') if expr[:GROUP_BY] - str += ' HAVING ' + expr[:HAVING].map { |h| "(#{h})" }.join(' AND ') if expr[:HAVING] - str += ' ORDER BY ' + expr[:ORDER_BY].map { |col, order| col + (order ? ' ' + order : '') }.join(', ') if expr[:ORDER_BY] - str += ' LIMIT ' + expr[:LIMIT] if expr[:LIMIT] - str += ' OFFSET ' + expr[:OFFSET] if expr[:OFFSET] + str += " WHERE " + expr[:WHERE].map { |w| "(#{w})" }.join(" AND ") if expr[:WHERE] + str += " GROUP BY " + expr[:GROUP_BY].join(", ") if expr[:GROUP_BY] + str += " HAVING " + expr[:HAVING].map { |h| "(#{h})" }.join(" AND ") if expr[:HAVING] + str += " ORDER BY " + expr[:ORDER_BY].map { |col, order| col + (order ? " " + order : "") }.join(", ") if expr[:ORDER_BY] + str += " LIMIT " + expr[:LIMIT] if expr[:LIMIT] + str += " OFFSET " + expr[:OFFSET] if expr[:OFFSET] str = "(#{str}) AS #{expr[:AS]}" if expr[:AS] str = "EXPLAIN #{str}" if expr[:EXPLAIN] str @@ -61,47 +60,47 @@ def self.parse(expr) if expr.is_a?(String) return expr # already parsed elsif expr.is_a?(Array) - return expr.join(',') + return expr.join(",") elsif expr[:INSERT_INTO] - str = "INSERT INTO #{expr[:INSERT_INTO]} (#{expr[:INSERT_COLUMNS].join(', ')})" - throw ArgumentError.new('VALUES (or SELECT) clause is missing for INSERT INTO') unless expr[:VALUES] || expr[:SELECT] + str = "INSERT INTO #{expr[:INSERT_INTO]} (#{expr[:INSERT_COLUMNS].join(", ")})" + throw ArgumentError.new("VALUES (or SELECT) clause is missing for INSERT INTO") unless expr[:VALUES] || expr[:SELECT] throw ArgumentError.new("For safety, you can't use SELECT without insert columns for an INSERT INTO") if !expr[:INSERT_COLUMNS] && expr[:SELECT] - if expr[:SELECT] - str += ' ' + parse_select(expr) + str += if expr[:SELECT] + " " + parse_select(expr) else - str += " VALUES #{expr[:VALUES].map { |vals| "(#{vals.join(', ')})" }.join(', ')}" + " VALUES #{expr[:VALUES].map { |vals| "(#{vals.join(", ")})" }.join(", ")}" end if expr[:ON_CONFLICT] - str += ' ON CONFLICT' + str += " ON CONFLICT" if expr[:CONFLICT_COLUMNS] - str += " (#{expr[:CONFLICT_COLUMNS].join(', ')})" + str += " (#{expr[:CONFLICT_COLUMNS].join(", ")})" elsif expr[:ON_CONSTRAINT] str += " ON CONSTRAINT #{expr[:ON_CONSTRAINT]}" end - str += ' DO NOTHING' unless expr[:CONFLICT_UPSERT] + str += " DO NOTHING" unless expr[:CONFLICT_UPSERT] if expr[:CONFLICT_UPSERT] - set_str = expr[:INSERT_COLUMNS].reject { |i| i == 'created_at' }.map { |i| "#{i} = EXCLUDED.#{i}" } - str += " DO UPDATE SET #{set_str.join(', ')}" + set_str = expr[:INSERT_COLUMNS].reject { |i| i == "created_at" }.map { |i| "#{i} = EXCLUDED.#{i}" } + str += " DO UPDATE SET #{set_str.join(", ")}" end end - str += ' RETURNING ' + expr[:RETURNING].join(', ') if expr[:RETURNING] + str += " RETURNING " + expr[:RETURNING].join(", ") if expr[:RETURNING] elsif expr[:SELECT] str = parse_select(expr) elsif expr[:DELETE_FROM] - str = 'DELETE FROM ' + expr[:DELETE_FROM] - throw ArgumentError.new('WHERE clause is missing for DELETE FROM') unless expr[:WHERE] - str += ' WHERE ' + expr[:WHERE].map { |w| "(#{w})" }.join(' AND ') - str += ' RETURNING ' + expr[:RETURNING].join(', ') if expr[:RETURNING] + str = "DELETE FROM " + expr[:DELETE_FROM] + throw ArgumentError.new("WHERE clause is missing for DELETE FROM") unless expr[:WHERE] + str += " WHERE " + expr[:WHERE].map { |w| "(#{w})" }.join(" AND ") + str += " RETURNING " + expr[:RETURNING].join(", ") if expr[:RETURNING] elsif expr[:UPDATE] - str = 'UPDATE ' + expr[:UPDATE] - throw ArgumentError.new('SET clause is missing for UPDATE') unless expr[:SET] - throw ArgumentError.new('WHERE clause is missing for UPDATE') unless expr[:WHERE] - str += ' SET ' + expr[:SET] - str += ' FROM ' + expr[:FROM] if expr[:FROM] - str += ' WHERE ' + expr[:WHERE].map { |w| "(#{w})" }.join(' AND ') - str += ' ' + expr[:ON_CONFLICT] if expr[:ON_CONFLICT] - str += ' RETURNING ' + expr[:RETURNING].join(', ') if expr[:RETURNING] + str = "UPDATE " + expr[:UPDATE] + throw ArgumentError.new("SET clause is missing for UPDATE") unless expr[:SET] + throw ArgumentError.new("WHERE clause is missing for UPDATE") unless expr[:WHERE] + str += " SET " + expr[:SET] + str += " FROM " + expr[:FROM] if expr[:FROM] + str += " WHERE " + expr[:WHERE].map { |w| "(#{w})" }.join(" AND ") + str += " " + expr[:ON_CONFLICT] if expr[:ON_CONFLICT] + str += " RETURNING " + expr[:RETURNING].join(", ") if expr[:RETURNING] end str @@ -114,10 +113,10 @@ def parse # Qx.select("id").from("supporters").execute def execute(options = {}) - expr = Qx.parse(@tree).to_s.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') + expr = Qx.parse(@tree).to_s.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "") Qx.execute_raw(expr, options) end - alias ex execute + alias_method :ex, :execute # Can pass in an expression string or another Qx object # Qx.execute("SELECT id FROM table_name", {format: 'csv'}) @@ -139,7 +138,7 @@ def self.execute_raw(expr, options = {}) end result = ActiveRecord::Base.connection.execute(expr) result.map_types!(@@type_map) if @@type_map - if options[:format] == 'csv' + if options[:format] == "csv" data = result.map(&:values) data.unshift((result.first || {}).keys) else @@ -151,7 +150,7 @@ def self.execute_raw(expr, options = {}) end def self.execute_file(path, data = {}, options = {}) - Qx.execute_raw(Qx.interpolate_expr(File.open(path, 'r').read, data), options) + Qx.execute_raw(Qx.interpolate_expr(File.read(path), data), options) end # helpers for JSON conversion @@ -249,7 +248,6 @@ def group_by(*cols) end def order_by(*cols) - orders = /(asc)|(desc)( nulls (first)|(last))?/i # Sanitize out invalid order keywords @tree[:ORDER_BY] = cols.map { |col, order| [col.to_s, order.to_s.downcase.strip.match?(order.to_s.downcase) ? order.to_s.upcase : nil] } self @@ -316,13 +314,13 @@ def add_left_outer_join(*joins) def join_lateral(join_name, select_statement, success_condition = true) @tree[:JOIN_LATERAL] ||= [] - @tree[:JOIN_LATERAL].concat([{ join_name: join_name, select_statement: select_statement, success_condition: success_condition }]) + @tree[:JOIN_LATERAL].concat([{join_name: join_name, select_statement: select_statement, success_condition: success_condition}]) self end def left_join_lateral(join_name, select_statement, success_condition = true) @tree[:LEFT_JOIN_LATERAL] ||= [] - @tree[:LEFT_JOIN_LATERAL].concat([{ join_name: join_name, select_statement: select_statement, success_condition: success_condition }]) + @tree[:LEFT_JOIN_LATERAL].concat([{join_name: join_name, select_statement: select_statement, success_condition: success_condition}]) self end @@ -369,7 +367,7 @@ def ts end self end - alias timestamps ts + alias_method :timestamps, :ts def returning(*cols) @tree[:RETURNING] = cols.map { |c| Qx.quote_ident(c) } @@ -379,7 +377,7 @@ def returning(*cols) # Vals can be a raw SQL string or a hash of data def set(vals) if vals.is_a? Hash - vals = vals.map { |key, val| "#{Qx.quote_ident(key)} = #{Qx.quote(val)}" }.join(', ') + vals = vals.map { |key, val| "#{Qx.quote_ident(key)} = #{Qx.quote(val)}" }.join(", ") end @tree[:SET] = vals.to_s self @@ -401,7 +399,7 @@ def on_constraint(constraint) end def upsert(on_index, columns = nil) - @tree[:CONFLICT_UPSERT] = { index: on_index, cols: columns } + @tree[:CONFLICT_UPSERT] = {index: on_index, cols: columns} self end @@ -413,14 +411,13 @@ def explain # -- Helpers! def self.fetch(table_name, data, options = {}) - expr = Qx.select('*').from(table_name) - if data.is_a?(Hash) - expr = data.reduce(expr) { |acc, pair| acc.and_where("#{pair.first} IN ($vals)", vals: Array(pair.last)) } + expr = Qx.select("*").from(table_name) + expr = if data.is_a?(Hash) + data.reduce(expr) { |acc, pair| acc.and_where("#{pair.first} IN ($vals)", vals: Array(pair.last)) } else - expr = expr.where('id IN ($ids)', ids: Array(data)) + expr.where("id IN ($ids)", ids: Array(data)) end - result = expr.execute(options) - result + expr.execute(options) end # Given a Qx expression, add a LIMIT and OFFSET for pagination @@ -433,11 +430,10 @@ def pp str = parse # Colorize some tokens # TODO indent by paren levels - str = str - .gsub(/(FROM|WHERE|VALUES|SET|SELECT|UPDATE|INSERT INTO|DELETE FROM)/) { Regexp.last_match(1).to_s.blue.bold } - .gsub(/(\(|\))/) { Regexp.last_match(1).to_s.cyan } - .gsub('$Q$', "'") str + .gsub(/(FROM|WHERE|VALUES|SET|SELECT|UPDATE|INSERT INTO|DELETE FROM)/) { Regexp.last_match(1).to_s.blue.bold } + .gsub(/(\(|\))/) { Regexp.last_match(1).to_s.cyan } + .gsub("$Q$", "'") end # -- utils @@ -447,9 +443,9 @@ def pp # Safely interpolate some data into a SQL expression def self.interpolate_expr(expr, data = {}) expr.to_s.gsub(/\$\w+/) do |match| - val = data[match.gsub(/[ \$]*/, '').to_sym] + val = data[match.gsub(/[ \$]*/, "").to_sym] vals = val.is_a?(Array) ? val : [val] - vals.map { |x| Qx.quote(x) }.join(', ') + vals.map { |x| Qx.quote(x) }.join(", ") end end @@ -465,11 +461,11 @@ def self.quote(val) elsif val.is_a?(Time) "'" + val.to_s + "'" # single-quoted times for a little better readability elsif val.nil? - 'NULL' + "NULL" elsif !!val == val # is a boolean val ? "'t'" : "'f'" else - '$Q$' + val.to_s + '$Q$' + "$Q$" + val.to_s + "$Q$" end end @@ -478,13 +474,13 @@ def self.quote_ident(expr) if expr.is_a?(Qx) Qx.parse(expr.tree) else - expr.to_s.split('.').map { |s| s == '*' ? s : "\"#{s}\"" }.join('.') + expr.to_s.split(".").map { |s| (s == "*") ? s : "\"#{s}\"" }.join(".") end end # Remove a clause from the sql tree def remove_clause(name) - name = name.to_s.upcase.tr(' ', '_').to_sym + name = name.to_s.upcase.tr(" ", "_").to_sym @tree.delete(name) self end @@ -509,7 +505,7 @@ def self.get_join_param(js) def self.parse_wheres(clauses) clauses.map do |expr, data| if expr.is_a?(Hash) - expr.map { |key, val| "#{Qx.quote_ident(key)} IN (#{Qx.quote(val)})" }.join(' AND ') + expr.map { |key, val| "#{Qx.quote_ident(key)} IN (#{Qx.quote(val)})" }.join(" AND ") else Qx.interpolate_expr(expr, data) end diff --git a/gems/ruby-qx/qx.gemspec b/gems/ruby-qx/qx.gemspec index 195b126b95..660ae18f31 100644 --- a/gems/ruby-qx/qx.gemspec +++ b/gems/ruby-qx/qx.gemspec @@ -1,17 +1,16 @@ # frozen_string_literal: true Gem::Specification.new do |s| - s.name = 'qx' - s.version = '0.1.1' - s.date = '2016-12-05' - s.summary = 'SQL expression builder' - s.description = 'A expression builder for SQL expressions with Postgresql support' - s.authors = ['Jay R Bolton'] - s.email = 'jayrbolton@gmail.com' - s.files = 'lib/qx.rb' - s.homepage = 'https://github.com/jayrbolton/qx' - s.license = 'MIT' - s.add_runtime_dependency 'activerecord', '>= 3.0' - s.add_runtime_dependency 'colorize', '~> 0.8' - s.add_development_dependency 'minitest', '~> 5.9' + s.name = "qx" + s.version = "0.1.1" + s.summary = "SQL expression builder" + s.description = "A expression builder for SQL expressions with Postgresql support" + s.authors = ["Jay R Bolton"] + s.email = "jayrbolton@gmail.com" + s.files = "lib/qx.rb" + s.homepage = "https://github.com/jayrbolton/qx" + s.license = "MIT" + s.add_runtime_dependency "activerecord", ">= 3.0" + s.add_runtime_dependency "colorize", "~> 0.8" + s.add_development_dependency "minitest", "~> 5.9" end diff --git a/gems/ruby-qx/test/UpsertTest.rb b/gems/ruby-qx/test/UpsertTest.rb index 909d2fb759..e37734359d 100644 --- a/gems/ruby-qx/test/UpsertTest.rb +++ b/gems/ruby-qx/test/UpsertTest.rb @@ -1,16 +1,17 @@ # frozen_string_literal: true -require './lib/qx.rb' +require "./lib/qx" -require 'minitest/autorun' +require "minitest/autorun" class UpsertTest < Minitest::Test - def setup; end + def setup + end def test_upsert - table = 'x' - column1 = 'a' - column2 = 'b' - idx = 'idx_something_more' + table = "x" + column1 = "a" + column2 = "b" + idx = "idx_something_more" result = Qx.insert_into(table).values(column1: column1, column2: column2).on_conflict.upsert(idx).parse diff --git a/gems/ruby-qx/test/qx_test.rb b/gems/ruby-qx/test/qx_test.rb index 71c497aefe..a319bd254a 100644 --- a/gems/ruby-qx/test/qx_test.rb +++ b/gems/ruby-qx/test/qx_test.rb @@ -1,126 +1,127 @@ # frozen_string_literal: true -require './lib/qx.rb' -require 'pg' -require 'minitest/autorun' -require 'pry' +require "./lib/qx" +require "pg" +require "minitest/autorun" +require "pry" -ActiveRecord::Base.establish_connection('postgres://admin:password@localhost/qx_test') +ActiveRecord::Base.establish_connection("postgres://admin:password@localhost/qx_test") tm = PG::BasicTypeMapForResults.new(ActiveRecord::Base.connection.raw_connection) Qx.config(type_map: tm) # Execute test schema -Qx.execute_file('./test/test_schema.sql') +Qx.execute_file("./test/test_schema.sql") class QxTest < Minitest::Test - def setup; end + def setup + end # Let's just test that the schema was executed def test_execute_file - email = 'uzzzr@example.com' - result = Qx.execute_file('./test/test_insert_user.sql', email: email, id: 1).last + email = "uzzzr@example.com" + result = Qx.execute_file("./test/test_insert_user.sql", email: email, id: 1).last Qx.delete_from(:users).where(id: 1).ex - assert_equal email, result['email'] + assert_equal email, result["email"] end def test_select_from - parsed = Qx.select(:id, 'name').from(:table_name).parse + parsed = Qx.select(:id, "name").from(:table_name).parse assert_equal parsed, %(SELECT id, name FROM table_name) end def test_select_distinct_on - parsed = Qx.select(:id, 'name').distinct_on(:distinct_col1, :distinct_col2).from(:table_name).parse + parsed = Qx.select(:id, "name").distinct_on(:distinct_col1, :distinct_col2).from(:table_name).parse assert_equal parsed, %(SELECT DISTINCT ON (distinct_col1, distinct_col2) id, name FROM table_name) end def test_select_distinct - parsed = Qx.select(:id, 'name').distinct.from(:table_name).parse + parsed = Qx.select(:id, "name").distinct.from(:table_name).parse assert_equal parsed, %(SELECT DISTINCT id, name FROM table_name) end def test_select_as - parsed = Qx.select(:id, 'name').from(:table_name).as(:alias).parse + parsed = Qx.select(:id, "name").from(:table_name).as(:alias).parse assert_equal parsed, %((SELECT id, name FROM table_name) AS "alias") end def test_select_where - parsed = Qx.select(:id, 'name').from(:table_name).where('x = $y OR a = $b', y: 1, b: 2).parse + parsed = Qx.select(:id, "name").from(:table_name).where("x = $y OR a = $b", y: 1, b: 2).parse assert_equal parsed, %(SELECT id, name FROM table_name WHERE (x = 1 OR a = 2)) end def test_select_where_hash_array - parsed = Qx.select(:id, 'name').from(:table_name).where([x: 1], ['y = $n', { n: 2 }]).parse + parsed = Qx.select(:id, "name").from(:table_name).where([x: 1], ["y = $n", {n: 2}]).parse assert_equal parsed, %(SELECT id, name FROM table_name WHERE ("x" IN (1)) AND (y = 2)) end def test_select_and_where - parsed = Qx.select(:id, 'name').from(:table_name).where('x = $y', y: 1).and_where('a = $b', b: 2).parse + parsed = Qx.select(:id, "name").from(:table_name).where("x = $y", y: 1).and_where("a = $b", b: 2).parse assert_equal parsed, %(SELECT id, name FROM table_name WHERE (x = 1) AND (a = 2)) end def test_select_and_where_hash - parsed = Qx.select(:id, 'name').from(:table_name).where('x = $y', y: 1).and_where(a: 2).parse + parsed = Qx.select(:id, "name").from(:table_name).where("x = $y", y: 1).and_where(a: 2).parse assert_equal parsed, %(SELECT id, name FROM table_name WHERE (x = 1) AND ("a" IN (2))) end def test_select_and_group_by - parsed = Qx.select(:id, 'name').from(:table_name).group_by('col1', 'col2').parse + parsed = Qx.select(:id, "name").from(:table_name).group_by("col1", "col2").parse assert_equal parsed, %(SELECT id, name FROM table_name GROUP BY col1, col2) end def test_select_and_order_by - parsed = Qx.select(:id, 'name').from(:table_name).order_by('col1', ['col2', 'DESC NULLS LAST']).parse + parsed = Qx.select(:id, "name").from(:table_name).order_by("col1", ["col2", "DESC NULLS LAST"]).parse assert_equal parsed, %(SELECT id, name FROM table_name ORDER BY col1 , col2 DESC NULLS LAST) end def test_select_having - parsed = Qx.select(:id, 'name').from(:table_name).having('COUNT(col1) > $n', n: 1).parse + parsed = Qx.select(:id, "name").from(:table_name).having("COUNT(col1) > $n", n: 1).parse assert_equal parsed, %(SELECT id, name FROM table_name HAVING (COUNT(col1) > 1)) end def test_select_and_having - parsed = Qx.select(:id, 'name').from(:table_name).having('COUNT(col1) > $n', n: 1).and_having('SUM(col2) > $m', m: 2).parse + parsed = Qx.select(:id, "name").from(:table_name).having("COUNT(col1) > $n", n: 1).and_having("SUM(col2) > $m", m: 2).parse assert_equal parsed, %(SELECT id, name FROM table_name HAVING (COUNT(col1) > 1) AND (SUM(col2) > 2)) end def test_select_limit - parsed = Qx.select(:id, 'name').from(:table_name).limit(10).parse + parsed = Qx.select(:id, "name").from(:table_name).limit(10).parse assert_equal parsed, %(SELECT id, name FROM table_name LIMIT 10) end def test_select_offset - parsed = Qx.select(:id, 'name').from(:table_name).offset(10).parse + parsed = Qx.select(:id, "name").from(:table_name).offset(10).parse assert_equal parsed, %(SELECT id, name FROM table_name OFFSET 10) end def test_select_join - parsed = Qx.select(:id, 'name').from(:table_name).join(['assoc1', 'assoc1.table_name_id=table_name.id']).parse + parsed = Qx.select(:id, "name").from(:table_name).join(["assoc1", "assoc1.table_name_id=table_name.id"]).parse assert_equal parsed, %(SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id) end def test_select_add_join - parsed = Qx.select(:id, 'name').from(:table_name).join('assoc1', 'assoc1.table_name_id=table_name.id') - .add_join(['assoc2', 'assoc2.table_name_id=table_name.id']).parse + parsed = Qx.select(:id, "name").from(:table_name).join("assoc1", "assoc1.table_name_id=table_name.id") + .add_join(["assoc2", "assoc2.table_name_id=table_name.id"]).parse assert_equal parsed, %(SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id JOIN assoc2 ON assoc2.table_name_id=table_name.id) end def test_select_left_join - parsed = Qx.select(:id, 'name').from(:table_name).left_join(['assoc1', 'assoc1.table_name_id=table_name.id']).parse + parsed = Qx.select(:id, "name").from(:table_name).left_join(["assoc1", "assoc1.table_name_id=table_name.id"]).parse assert_equal parsed, %(SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id) end def test_select_add_left_join - parsed = Qx.select(:id, 'name').from(:table_name).left_join('assoc1', 'assoc1.table_name_id=table_name.id') - .add_left_join(['assoc2', 'assoc2.table_name_id=table_name.id']).parse + parsed = Qx.select(:id, "name").from(:table_name).left_join("assoc1", "assoc1.table_name_id=table_name.id") + .add_left_join(["assoc2", "assoc2.table_name_id=table_name.id"]).parse assert_equal parsed, %(SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id LEFT JOIN assoc2 ON assoc2.table_name_id=table_name.id) end def test_select_where_subquery - parsed = Qx.select(:id, 'name').from(:table_name).where('id IN ($ids)', ids: Qx.select('id').from('assoc')).parse + parsed = Qx.select(:id, "name").from(:table_name).where("id IN ($ids)", ids: Qx.select("id").from("assoc")).parse assert_equal parsed, %(SELECT id, name FROM table_name WHERE (id IN (SELECT id FROM assoc))) end def test_select_join_subquery - parsed = Qx.select(:id).from(:table).join([Qx.select(:id).from(:assoc).as(:assoc), 'assoc.table_id=table.id']).parse + parsed = Qx.select(:id).from(:table).join([Qx.select(:id).from(:assoc).as(:assoc), "assoc.table_id=table.id"]).parse assert_equal parsed, %(SELECT id FROM table JOIN (SELECT id FROM assoc) AS "assoc" ON assoc.table_id=table.id) end @@ -131,18 +132,18 @@ def test_select_from_subquery def test_select_integration parsed = Qx.select(:id) - .from(:table) - .join([Qx.select(:id).from(:assoc).as(:assoc), 'assoc.table_id=table.id']) - .left_join(['lefty', 'lefty.table_id=table.id']) - .where('x = $n', n: 1) - .and_where('y = $n', n: 1) - .group_by(:x) - .order_by(:y) - .having('COUNT(x) > $n', n: 1) - .and_having('COUNT(y) > $n', n: 1) - .limit(10) - .offset(10) - .parse + .from(:table) + .join([Qx.select(:id).from(:assoc).as(:assoc), "assoc.table_id=table.id"]) + .left_join(["lefty", "lefty.table_id=table.id"]) + .where("x = $n", n: 1) + .and_where("y = $n", n: 1) + .group_by(:x) + .order_by(:y) + .having("COUNT(x) > $n", n: 1) + .and_having("COUNT(y) > $n", n: 1) + .limit(10) + .offset(10) + .parse assert_equal parsed, %(SELECT id FROM table JOIN (SELECT id FROM assoc) AS "assoc" ON assoc.table_id=table.id LEFT JOIN lefty ON lefty.table_id=table.id WHERE (x = 1) AND (y = 1) GROUP BY x HAVING (COUNT(x) > 1) AND (COUNT(y) > 1) ORDER BY y LIMIT 10 OFFSET 10) end @@ -152,17 +153,17 @@ def test_insert_into_values_hash end def test_insert_into_values_hash_array - parsed = Qx.insert_into(:table_name).values([{ x: 1 }, { x: 2 }]).parse + parsed = Qx.insert_into(:table_name).values([{x: 1}, {x: 2}]).parse assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1), (2)) end def test_insert_into_values_csv_style - parsed = Qx.insert_into(:table_name).values([['x'], [1], [2]]).parse + parsed = Qx.insert_into(:table_name).values([["x"], [1], [2]]).parse assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1), (2)) end def test_insert_into_values_common_values - parsed = Qx.insert_into(:table_name).values([{ x: 'bye' }, { x: 'hi' }]).common_values(z: 1).parse + parsed = Qx.insert_into(:table_name).values([{x: "bye"}, {x: "hi"}]).common_values(z: 1).parse assert_equal parsed, %(INSERT INTO "table_name" ("x", "z") VALUES ($Q$bye$Q$, 1), ($Q$hi$Q$, 1)) end @@ -172,28 +173,28 @@ def test_insert_into_values_timestamps end def test_insert_into_values_returning - parsed = Qx.insert_into(:table_name).values(x: 1).returning('*').parse + parsed = Qx.insert_into(:table_name).values(x: 1).returning("*").parse assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1) RETURNING *) end def test_insert_into_select - parsed = Qx.insert_into(:table_name, ['hi']).select('hi').from(:table2).where('x=y').parse + parsed = Qx.insert_into(:table_name, ["hi"]).select("hi").from(:table2).where("x=y").parse assert_equal parsed, %(INSERT INTO "table_name" ("hi") SELECT hi FROM table2 WHERE (x=y)) end def test_update_set - parsed = Qx.update(:table_name).set(x: 1).where('y = 2').parse + parsed = Qx.update(:table_name).set(x: 1).where("y = 2").parse assert_equal parsed, %(UPDATE "table_name" SET "x" = 1 WHERE (y = 2)) end def test_update_timestamps now = Time.now.utc - parsed = Qx.update(:table_name).set(x: 1).where('y = 2').timestamps.parse + parsed = Qx.update(:table_name).set(x: 1).where("y = 2").timestamps.parse assert_equal parsed, %(UPDATE "table_name" SET "x" = 1, updated_at = '#{now}' WHERE (y = 2)) end def test_update_on_conflict - Qx.update(:table_name).set(x: 1).where('y = 2').on_conflict(:nothing).parse + Qx.update(:table_name).set(x: 1).where("y = 2").on_conflict(:nothing).parse assert_equal parsed, %(UPDATE "table_name" SET "x" = 1 WHERE (y = 2) ON CONFLICT DO NOTHING) end @@ -214,40 +215,40 @@ def test_pagination end def test_execute_string - result = Qx.execute('SELECT * FROM (VALUES ($x)) AS t', x: 'x') - assert_equal result, [{ 'column1' => 'x' }] + result = Qx.execute("SELECT * FROM (VALUES ($x)) AS t", x: "x") + assert_equal result, [{"column1" => "x"}] end def test_execute_format_csv - result = Qx.execute('SELECT * FROM (VALUES ($x)) AS t', { x: 'x' }, format: 'csv') - assert_equal result, [['column1'], ['x']] + result = Qx.execute("SELECT * FROM (VALUES ($x)) AS t", {x: "x"}, format: "csv") + assert_equal result, [["column1"], ["x"]] end def test_execute_on_instances - result = Qx.insert_into(:users).values(id: 1, email: 'uzr@example.com').execute - result = Qx.execute(Qx.select('*').from(:users).limit(1)) - assert_equal result, [{ 'id' => 1, 'email' => 'uzr@example.com' }] + Qx.insert_into(:users).values(id: 1, email: "uzr@example.com").execute + result = Qx.execute(Qx.select("*").from(:users).limit(1)) + assert_equal result, [{"id" => 1, "email" => "uzr@example.com"}] Qx.delete_from(:users).where(id: 1).execute end def test_explain - parsed = Qx.select('*').from('table_name').explain.parse + parsed = Qx.select("*").from("table_name").explain.parse assert_equal parsed, %(EXPLAIN SELECT * FROM table_name) end # Manually test this one for now def test_pp_select - pp = Qx.select('id, name').from('table_name').where(status: 'active').and_where(id: Qx.select('id').from('roles').where(name: 'admin')).pp + pp = Qx.select("id, name").from("table_name").where(status: "active").and_where(id: Qx.select("id").from("roles").where(name: "admin")).pp pp2 = Qx.insert_into(:table_name).values([x: 1, y: 2]).pp pp3 = Qx.update(:table_name).set(x: 1, y: 2).where(z: 1, a: 22).pp pp_delete = Qx.delete_from(:table_name).where(id: 123).pp - puts '' - puts '--- pretty print' + puts "" + puts "--- pretty print" puts pp puts pp2 puts pp3 puts pp_delete - puts '---' + puts "---" end def test_to_json @@ -257,26 +258,26 @@ def test_to_json def test_to_json_nested definitions = Qx.select(:part_of_speech, :body) - .from(:definitions) - .where('word_id=words.id') - .order_by('position ASC') - .to_json(:ds) - .as('definitions') + .from(:definitions) + .where("word_id=words.id") + .order_by("position ASC") + .to_json(:ds) + .as("definitions") parsed = Qx.select(:text, :pronunciation, definitions) - .from(:words) - .where("text='autumn'") - .to_json(:ws) - .parse + .from(:words) + .where("text='autumn'") + .to_json(:ws) + .parse assert_equal parsed, "SELECT array_to_json(array_agg(row_to_json(ws))) FROM (SELECT text, pronunciation, (SELECT array_to_json(array_agg(row_to_json(ds))) FROM (SELECT part_of_speech, body FROM definitions WHERE (word_id=words.id) ORDER BY position ASC ) AS \"ds\") AS \"definitions\" FROM words WHERE (text='autumn')) AS \"ws\"" end def test_copy_csv_execution - data = { 'id' => '1', 'email' => 'uzr@example.com' } - filename = '/tmp/qx-test.csv' + data = {"id" => "1", "email" => "uzr@example.com"} + filename = "/tmp/qx-test.csv" Qx.insert_into(:users).values(data).ex - copy = Qx.select('*').from('users').execute(copy_csv: filename) - contents = File.open(filename, 'r').read - csv_data = contents.split("\n").map { |l| l.split(',') } + Qx.select("*").from("users").execute(copy_csv: filename) + contents = File.read(filename) + csv_data = contents.split("\n").map { |l| l.split(",") } headers = csv_data.first row = csv_data.last assert_equal data.keys, headers @@ -284,8 +285,8 @@ def test_copy_csv_execution end def test_remove_clause - expr = Qx.select('*').from('table').limit(1) - expr = expr.remove_clause('limit') - assert_equal 'SELECT * FROM table', expr.parse + expr = Qx.select("*").from("table").limit(1) + expr = expr.remove_clause("limit") + assert_equal "SELECT * FROM table", expr.parse end end diff --git a/lib/generators/libmodule/libmodule_generator.rb b/lib/generators/libmodule/libmodule_generator.rb index 57d45c8527..dea7725829 100644 --- a/lib/generators/libmodule/libmodule_generator.rb +++ b/lib/generators/libmodule/libmodule_generator.rb @@ -4,9 +4,9 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class LibmoduleGenerator < Rails::Generators::NamedBase argument :mod_type, type: :string - source_root File.expand_path('templates', __dir__) + source_root File.expand_path("templates", __dir__) def copy_file_to_lib - template 'libmodule_template.erb', "lib/#{mod_type.underscore}/#{mod_type.underscore}_#{name.underscore}.rb" - template 'libmodule_spec_template.erb', "spec/lib/#{mod_type.underscore}/#{mod_type.underscore}_#{name.underscore}_spec.rb" + template "libmodule_template.erb", "lib/#{mod_type.underscore}/#{mod_type.underscore}_#{name.underscore}.rb" + template "libmodule_spec_template.erb", "spec/lib/#{mod_type.underscore}/#{mod_type.underscore}_#{name.underscore}_spec.rb" end end diff --git a/lib/generators/overrides.rb b/lib/generators/overrides.rb index c38d1f7586..5bd47a9169 100644 --- a/lib/generators/overrides.rb +++ b/lib/generators/overrides.rb @@ -2,4 +2,4 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative './overrides/rails/plugin/plugin_builder' \ No newline at end of file +require_relative "overrides/rails/plugin/plugin_builder" diff --git a/lib/generators/overrides/rails/plugin/plugin_builder.rb b/lib/generators/overrides/rails/plugin/plugin_builder.rb index 8760df058c..f24bd0afa9 100644 --- a/lib/generators/overrides/rails/plugin/plugin_builder.rb +++ b/lib/generators/overrides/rails/plugin/plugin_builder.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails/generators/rails/plugin/plugin_generator' +require "rails/generators/rails/plugin/plugin_generator" class PluginBuilder < Rails::PluginBuilder def license template "LICENSE" @@ -14,11 +14,10 @@ def license module Rails module Generators - class PluginGenerator + class PluginGenerator def source_paths [File.expand_path("templates", __dir__)] end end end end - diff --git a/lib/generators/ts/declaration/declaration_generator.rb b/lib/generators/ts/declaration/declaration_generator.rb index 119f3dc960..18f71ba09e 100644 --- a/lib/generators/ts/declaration/declaration_generator.rb +++ b/lib/generators/ts/declaration/declaration_generator.rb @@ -3,8 +3,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE class Ts::DeclarationGenerator < Rails::Generators::NamedBase - source_root File.expand_path('templates', __dir__) + source_root File.expand_path("templates", __dir__) def copy_template - template 'template.d.ts.erb', File.join('types', name, 'index.d.ts') + template "template.d.ts.erb", File.join("types", name, "index.d.ts") end end diff --git a/lib/tasks/health_report.rake b/lib/tasks/health_report.rake index 823f3ba05b..d1fa639938 100644 --- a/lib/tasks/health_report.rake +++ b/lib/tasks/health_report.rake @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -desc 'For sending an activity report email of what has been happening on the system' +desc "For sending an activity report email of what has been happening on the system" # Clear old activerecord sessions tables daily task send_health_report: :environment do diff --git a/lib/tasks/i18n_js.rake b/lib/tasks/i18n_js.rake index 0560e88978..4da9eb4e18 100644 --- a/lib/tasks/i18n_js.rake +++ b/lib/tasks/i18n_js.rake @@ -4,37 +4,37 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE def enhance_assets_precompile - # yarn:install was added in Rails 5.1 - Rake::Task['assets:precompile'].enhance(['i18n:js:export']) + # yarn:install was added in Rails 5.1 + Rake::Task["assets:precompile"].enhance(["i18n:js:export"]) end def enhance_webpacker_compile - Rake::Task['webpacker:compile'].enhance(['i18n:js:export']) + Rake::Task["webpacker:compile"].enhance(["i18n:js:export"]) end def enhance_webpacker_clean - Rake::Task['webpacker:clean'].enhance(['i18n:js:clean']) + Rake::Task["webpacker:clean"].enhance(["i18n:js:clean"]) end def enhance_assets_clean_and_clobber - Rake::Task['assets:clean'].enhance(['i18n:js:clean']) - Rake::Task['assets:clobber'].enhance(['i18n:js:clean']) + Rake::Task["assets:clean"].enhance(["i18n:js:clean"]) + Rake::Task["assets:clobber"].enhance(["i18n:js:clean"]) end -desc 'For generating the i18n-js exports at runtime. Overrides the built in i18n-js task' +desc "For generating the i18n-js exports at runtime. Overrides the built in i18n-js task" namespace :i18n do - namespace :js do - desc 'Export locales to Typescript' - task export: :environment do - GenerateLocales.generate - end - - desc 'Delete all of the generated Javascript locales files' - task clean: :environment do - locales_dir = Rails.root.join('app/javascript/i18n/locales') - FileUtils.rm_rf(locales_dir) - end - end + namespace :js do + desc "Export locales to Typescript" + task export: :environment do + GenerateLocales.generate + end + + desc "Delete all of the generated Javascript locales files" + task clean: :environment do + locales_dir = Rails.root.join("app/javascript/i18n/locales") + FileUtils.rm_rf(locales_dir) + end + end end enhance_assets_precompile diff --git a/lib/tasks/js.rake b/lib/tasks/js.rake index acf8c9c2c4..a8713a57df 100644 --- a/lib/tasks/js.rake +++ b/lib/tasks/js.rake @@ -2,16 +2,16 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -desc 'Javascript related tasks' +desc "Javascript related tasks" namespace :js do - desc 'generate all the pre-build Javascript' - task generate: ['js:routes:typescript', 'i18n:js:export'] - namespace :routes do - desc 'delete generated route files' - task clean: :environment do - js_dir = Rails.root.join('app/javascript') - FileUtils.rm_f js_dir.join('routes.js') - FileUtils.rm_f js_dir.join('routes.d.ts') - end - end + desc "generate all the pre-build Javascript" + task generate: ["js:routes:typescript", "i18n:js:export"] + namespace :routes do + desc "delete generated route files" + task clean: :environment do + js_dir = Rails.root.join("app/javascript") + FileUtils.rm_f js_dir.join("routes.js") + FileUtils.rm_f js_dir.join("routes.d.ts") + end + end end diff --git a/lib/tasks/js_routes.rake b/lib/tasks/js_routes.rake index 84e2254cf3..16581531da 100644 --- a/lib/tasks/js_routes.rake +++ b/lib/tasks/js_routes.rake @@ -7,7 +7,7 @@ # adds support for generating js routes as part of the assets:precompile task namespace :assets do - task precompile: 'js:routes' + task precompile: "js:routes" end # rubocop:enable Rake/Desc diff --git a/lib/tasks/legacy_scheduler.rake b/lib/tasks/legacy_scheduler.rake index 9d079f9037..9f08a9023e 100644 --- a/lib/tasks/legacy_scheduler.rake +++ b/lib/tasks/legacy_scheduler.rake @@ -3,11 +3,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -desc 'This task is deprecated and serve only as an alias for cron_job_runner' +desc "This task is deprecated and serve only as an alias for cron_job_runner" # This task exists only for legacy reasons, use cron_job_runner to run ScheduledJobs instead task :heroku_scheduled_job, [:name] => :environment do |_t, args| - job_name = args[:name] - Rake::Task['cron_job_runner'].invoke(job_name) + job_name = args[:name] + Rake::Task["cron_job_runner"].invoke(job_name) end diff --git a/lib/tasks/notice.rake b/lib/tasks/notice.rake index eff7096e6f..351fd0277f 100644 --- a/lib/tasks/notice.rake +++ b/lib/tasks/notice.rake @@ -3,52 +3,52 @@ # Create notice files for dependencies namespace :notice do - desc "generate NOTICE-ruby and NOTICE-js" - task :update => ['ruby:update', 'js:update'] - namespace :ruby do - require 'bundler' - require 'httparty' - def get_notice_ruby - parser = Bundler::LockfileParser.new(File.read(Rails.root.join("Gemfile.lock"))) - result = parser.specs.map do |spec| - "gem/rubygems/-/#{spec.name}/#{spec.version.to_s}" - end + desc "generate NOTICE-ruby and NOTICE-js" + task update: ["ruby:update", "js:update"] + namespace :ruby do + require "bundler" + require "httparty" + def get_notice_ruby + parser = Bundler::LockfileParser.new(File.read(Rails.root.join("Gemfile.lock"))) + result = parser.specs.map do |spec| + "gem/rubygems/-/#{spec.name}/#{spec.version}" + end - @options = { - :headers => { - 'Content-Type' => 'application/json', - 'Accept' => 'application/json' - }, - :timeout => 120 - } - result = HTTParty.post("https://api.clearlydefined.io/notices", @options.merge(body:JSON::generate({coordinates: result}))) - JSON::parse(result.body)['content'] - end + @options = { + headers: { + "Content-Type" => "application/json", + "Accept" => "application/json" + }, + timeout: 120 + } + result = HTTParty.post("https://api.clearlydefined.io/notices", @options.merge(body: JSON.generate({coordinates: result}))) + JSON.parse(result.body)["content"] + end + + desc "generating NOTICE-ruby from ClearlyDefined.io" + task :update do + result = get_notice_ruby + File.write("NOTICE-ruby", result) + end - desc "generating NOTICE-ruby from ClearlyDefined.io" - task :update do - result = get_notice_ruby - File.write('NOTICE-ruby', result) - end - - desc "checking whether NOTICE-ruby matches the one on ClearlyDefined.io" - task :verify do - result = get_notice_ruby - raise "NOTICE-ruby is not up to date. Run bin/rails notice:ruby:update to update the file." if result != File.read('NOTICE-ruby') - end + desc "checking whether NOTICE-ruby matches the one on ClearlyDefined.io" + task :verify do + result = get_notice_ruby + raise "NOTICE-ruby is not up to date. Run bin/rails notice:ruby:update to update the file." if result != File.read("NOTICE-ruby") end + end - namespace :js do - notice_cmd = "yarn notice:js" + namespace :js do + notice_cmd = "yarn notice:js" - desc "generating NOTICE-js from ClearlyDefined.io" - task :update do - raise "NOTICE-js could not be updated" unless system(notice_cmd + " -u") - end + desc "generating NOTICE-js from ClearlyDefined.io" + task :update do + raise "NOTICE-js could not be updated" unless system(notice_cmd + " -u") + end - desc "checking whether NOTICE-js matches the one on ClearlyDefined.io" - task :verify do - raise "NOTICE-js is not up to date. Run bin/rails notice:js:update to update the file" unless system(notice_cmd) - end + desc "checking whether NOTICE-js matches the one on ClearlyDefined.io" + task :verify do + raise "NOTICE-js is not up to date. Run bin/rails notice:js:update to update the file" unless system(notice_cmd) end -end \ No newline at end of file + end +end diff --git a/lib/tasks/scheduler.rake b/lib/tasks/scheduler.rake index 7710237603..449a3e9346 100644 --- a/lib/tasks/scheduler.rake +++ b/lib/tasks/scheduler.rake @@ -11,7 +11,7 @@ task :cron_job_runner, [:name] => :environment do |_t, args| # Fetch all the super admin emails so we can send a report enum = ScheduledJobs.send(job_name) - results = '' + results = "" enum.each do |lamb| result = lamb.call results += "Success: #{result}\n" @@ -21,6 +21,6 @@ task :cron_job_runner, [:name] => :environment do |_t, args| GenericMailer.admin_notice( subject: "Scheduled job results on #{Houdini.hoster.casual_name} for '#{job_name}'", - body: results.empty? ? 'No jobs to run today.' : results + body: results.empty? ? "No jobs to run today." : results ).deliver_later end diff --git a/lib/tasks/seed.rake b/lib/tasks/seed.rake index 9b042422d7..6bc925a445 100644 --- a/lib/tasks/seed.rake +++ b/lib/tasks/seed.rake @@ -6,8 +6,8 @@ namespace :seed do task np: :environment do ActiveRecord::Base.transaction do supers = Role.super_admins.includes(:user).map(&:user) - n = Nonprofit.register(supers.last, name: "Testify #{rand(0..100)}", city: 'Albuquerque', state_code: 'NM') - n.verification_status = 'verified' + n = Nonprofit.register(supers.last, name: "Testify #{rand(0..100)}", city: "Albuquerque", state_code: "NM") + n.verification_status = "verified" n.vetted = true n.create_billing_subscription(billing_plan: BillingPlan.where(tier: 2).last) n.save! diff --git a/spec/controllers/api/api_controller_spec.rb b/spec/controllers/api/api_controller_spec.rb index 776f3e8468..287ffe66b8 100644 --- a/spec/controllers/api/api_controller_spec.rb +++ b/spec/controllers/api/api_controller_spec.rb @@ -2,35 +2,35 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Api::ApiController do - it { - is_expected.to rescue_from(AuthenticationError).with(:unauthorized_rescue) - } + it { + is_expected.to rescue_from(AuthenticationError).with(:unauthorized_rescue) + } - describe 'rescues' do - render_views - describe 'AuthenticationError' do - controller(described_class) do - def index - raise AuthenticationError - end - end + describe "rescues" do + render_views + describe "AuthenticationError" do + controller(described_class) do + def index + raise AuthenticationError + end + end - before { get :index, format: :json } + before { get :index, format: :json } - it { - expect(response).to have_http_status(:unauthorized) - } + it { + expect(response).to have_http_status(:unauthorized) + } - context 'with result body' do - subject(:body) { response.parsed_body } + context "with result body" do + subject(:body) { response.parsed_body } - it { - is_expected.to match_json(message: 'AuthenticationError') - } - end - end - end + it { + is_expected.to match_json(message: "AuthenticationError") + } + end + end + end end diff --git a/spec/controllers/api/nonprofits_controller_spec.rb b/spec/controllers/api/nonprofits_controller_spec.rb index 2601eaa2f6..96f9e5a32a 100644 --- a/spec/controllers/api/nonprofits_controller_spec.rb +++ b/spec/controllers/api/nonprofits_controller_spec.rb @@ -2,64 +2,64 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Api::NonprofitsController, type: :request do - let(:user) { create(:user) } - let(:nonprofit_admin_role) do - role = user.roles.build(host: nonprofit, name: 'nonprofit_admin') - role.save! - role - end - let(:nonprofit) { create(:nm_justice) } + let(:user) { create(:user) } + let(:nonprofit_admin_role) do + role = user.roles.build(host: nonprofit, name: "nonprofit_admin") + role.save! + role + end + let(:nonprofit) { create(:nm_justice) } - describe 'get' do - end + describe "get" do + end - describe 'create' do - around do |example| - @old_bp = Houdini.default_bp - example.run - Houdini.default_bp = @old_bp - end + describe "create" do + around do |example| + @old_bp = Houdini.default_bp + example.run + Houdini.default_bp = @old_bp + end - it 'validates and returns correct errors' do - input = {} - post '/api/nonprofits', params: input, xhr: true - expect(response).to have_http_status :unprocessable_entity - expect( response.parsed_body['errors'].keys).to match_array %w[name city state_code slug user_id] - end + it "validates and returns correct errors" do + input = {} + post "/api/nonprofits", params: input, xhr: true + expect(response).to have_http_status :unprocessable_entity + expect(response.parsed_body["errors"].keys).to match_array %w[name city state_code slug user_id] + end - it 'succeeds' do - input = { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915, user_id: user.id, - phone: '920-555-5555' } - sign_in user - bp = force_create(:billing_plan) - Houdini.default_bp = bp.id + it "succeeds" do + input = {name: "n", state_code: "WI", city: "appleton", zip_code: 54_915, user_id: user.id, + phone: "920-555-5555"} + sign_in user + bp = force_create(:billing_plan) + Houdini.default_bp = bp.id - sign_in user + sign_in user - post '/api/nonprofits', params: input, xhr: true - expect(response).to have_http_status :created + post "/api/nonprofits", params: input, xhr: true + expect(response).to have_http_status :created - expected_np = { - name: 'n', - state_code: 'WI', - city: 'appleton', - zip_code: '54915', - state_code_slug: 'wi', - city_slug: 'appleton', - slug: 'n', - phone: '920-555-5555', - email: nil, - website: nil, - urls: { plain_url: 'http://www.example.com/nonprofits/1', slug_url: 'http://www.example.com/wi/appleton/n' } - }.with_indifferent_access + expected_np = { + name: "n", + state_code: "WI", + city: "appleton", + zip_code: "54915", + state_code_slug: "wi", + city_slug: "appleton", + slug: "n", + phone: "920-555-5555", + email: nil, + website: nil, + urls: {plain_url: "http://www.example.com/nonprofits/1", slug_url: "http://www.example.com/wi/appleton/n"} + }.with_indifferent_access - expect( response.parsed_body['id']).to be > 0 - expect( response.parsed_body.except('id')).to eq expected_np + expect(response.parsed_body["id"]).to be > 0 + expect(response.parsed_body.except("id")).to eq expected_np - expect(Nonprofit.find(1).billing_plan).to_not be_nil - end - end + expect(Nonprofit.find(1).billing_plan).to_not be_nil + end + end end diff --git a/spec/controllers/campaign_gift_options_spec.rb b/spec/controllers/campaign_gift_options_spec.rb index 7a0cfeebb1..56c3f1335c 100644 --- a/spec/controllers/campaign_gift_options_spec.rb +++ b/spec/controllers/campaign_gift_options_spec.rb @@ -2,36 +2,37 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe CampaignGiftOptionsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'reject unauthorized' do - describe 'create' do + describe "reject unauthorized" do + describe "create" do include_context :open_to_campaign_editor, :post, :create, nonprofit_id: :__our_np, campaign_id: :__our_campaign end - describe 'update' do - include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' + describe "update" do + include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end - describe 'destroy' do - include_context :open_to_campaign_editor, :delete, :destroy, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' + + describe "destroy" do + include_context :open_to_campaign_editor, :delete, :destroy, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end - describe 'update_order' do - include_context :open_to_campaign_editor, :put, :update_order, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' + describe "update_order" do + include_context :open_to_campaign_editor, :put, :update_order, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end end - describe 'accept all' do - describe 'index' do + describe "accept all" do + describe "index" do include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign end - describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' + describe "show" do + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end end end diff --git a/spec/controllers/campaign_gifts_spec.rb b/spec/controllers/campaign_gifts_spec.rb index 6cf9040905..e2a2d2eb0e 100644 --- a/spec/controllers/campaign_gifts_spec.rb +++ b/spec/controllers/campaign_gifts_spec.rb @@ -2,15 +2,15 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe CampaignGiftsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'accept all' do - describe 'create' do + describe "accept all" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, campaign_id: :__our_campaign end end diff --git a/spec/controllers/campaigns/campaign_gift_options_spec.rb b/spec/controllers/campaigns/campaign_gift_options_spec.rb index edeaf42fd8..29bfb47e71 100644 --- a/spec/controllers/campaigns/campaign_gift_options_spec.rb +++ b/spec/controllers/campaigns/campaign_gift_options_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Campaigns::CampaignGiftOptionsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'accept all' do - describe 'index' do + describe "accept all" do + describe "index" do include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign end end diff --git a/spec/controllers/campaigns/donations_spec.rb b/spec/controllers/campaigns/donations_spec.rb index b65ae4ad87..c17349c369 100644 --- a/spec/controllers/campaigns/donations_spec.rb +++ b/spec/controllers/campaigns/donations_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Campaigns::DonationsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'reject unauthorized' do - describe 'index' do + describe "reject unauthorized" do + describe "index" do include_context :open_to_campaign_editor, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign end end diff --git a/spec/controllers/campaigns/supporters_spec.rb b/spec/controllers/campaigns/supporters_spec.rb index 3f2bd7ef6c..2760de87b0 100644 --- a/spec/controllers/campaigns/supporters_spec.rb +++ b/spec/controllers/campaigns/supporters_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Campaigns::SupportersController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'reject unauthorized' do - describe 'index' do + describe "reject unauthorized" do + describe "index" do include_context :open_to_campaign_editor, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign, without_json_view: true end end diff --git a/spec/controllers/campaigns_controller_spec.rb b/spec/controllers/campaigns_controller_spec.rb index 17a0f3e211..83cb42d1ff 100644 --- a/spec/controllers/campaigns_controller_spec.rb +++ b/spec/controllers/campaigns_controller_spec.rb @@ -2,110 +2,110 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe CampaignsController do - describe 'authorization' do - include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do - include_context :open_to_confirmed_users, - :post, - :create, - nonprofit_id: :__our_np, - with_status: 200 # why? I don't know. - end - - describe 'name_and_id' do - include_context :open_to_confirmed_users, :get, :name_and_id, nonprofit_id: :__our_np - end - - describe 'duplicate' do - include_context :open_to_confirmed_users, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_campaign - end - - describe 'update' do - include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_campaign, - with_status: 200 - end - - describe 'soft_delete' do - include_context :open_to_campaign_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_campaign - end - end - - describe 'open to all' do - describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, without_json_view: true - end - - describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_campaign, without_json_view: true - end - - describe 'activities' do - include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_campaign - end - - describe 'metrics' do - include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_campaign - end - - describe 'timeline' do - include_context :open_to_all, :get, :timeline, nonprofit_id: :__our_np, id: :__our_campaign - end - - describe 'totals' do - include_context :open_to_all, :get, :totals, nonprofit_id: :__our_np, id: :__our_campaign - end - - describe 'peer_to_peer' do - include_context :open_to_all, :get, :peer_to_peer, nonprofit_id: :__our_np, without_json_view: true - end - end - end - - describe 'routes' do - it { - is_expected.to route( - :get, '/nonprofits/5/campaigns/4' - ).to( - controller: 'campaigns', action: 'show', nonprofit_id: '5', - id: '4' - ) - } - end - - describe 'index' do - render_views - let(:nonprofit) { force_create(:nm_justice, published: true) } - let(:campaign) { force_create(:campaign, nonprofit: nonprofit, name: 'simplename', goal_amount: 444) } - - before do - campaign - get(:index, params: { nonprofit_id: nonprofit.id, format: :json }) - end - - it 'has ok status' do - expect(response).to have_http_status(:ok) - end - - it 'has correct items' do - body = response.parsed_body - expect(body).to eq( - { - data: [ - { - id: campaign.id, - name: 'simplename', - total_raised: 0, - goal_amount: 444, - url: "http://test.host/nm/albuquerque/new-mexico-equality/campaigns/slug_#{campaign.id}" - } - ] - }.with_indifferent_access - ) - end - end + describe "authorization" do + include_context :shared_user_context + describe "rejects unauthorized users" do + describe "create" do + include_context :open_to_confirmed_users, + :post, + :create, + nonprofit_id: :__our_np, + with_status: 200 # why? I don't know. + end + + describe "name_and_id" do + include_context :open_to_confirmed_users, :get, :name_and_id, nonprofit_id: :__our_np + end + + describe "duplicate" do + include_context :open_to_confirmed_users, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_campaign + end + + describe "update" do + include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_campaign, + with_status: 200 + end + + describe "soft_delete" do + include_context :open_to_campaign_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_campaign + end + end + + describe "open to all" do + describe "index" do + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, without_json_view: true + end + + describe "show" do + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_campaign, without_json_view: true + end + + describe "activities" do + include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_campaign + end + + describe "metrics" do + include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_campaign + end + + describe "timeline" do + include_context :open_to_all, :get, :timeline, nonprofit_id: :__our_np, id: :__our_campaign + end + + describe "totals" do + include_context :open_to_all, :get, :totals, nonprofit_id: :__our_np, id: :__our_campaign + end + + describe "peer_to_peer" do + include_context :open_to_all, :get, :peer_to_peer, nonprofit_id: :__our_np, without_json_view: true + end + end + end + + describe "routes" do + it { + is_expected.to route( + :get, "/nonprofits/5/campaigns/4" + ).to( + controller: "campaigns", action: "show", nonprofit_id: "5", + id: "4" + ) + } + end + + describe "index" do + render_views + let(:nonprofit) { force_create(:nm_justice, published: true) } + let(:campaign) { force_create(:campaign, nonprofit: nonprofit, name: "simplename", goal_amount: 444) } + + before do + campaign + get(:index, params: {nonprofit_id: nonprofit.id, format: :json}) + end + + it "has ok status" do + expect(response).to have_http_status(:ok) + end + + it "has correct items" do + body = response.parsed_body + expect(body).to eq( + { + data: [ + { + id: campaign.id, + name: "simplename", + total_raised: 0, + goal_amount: 444, + url: "http://test.host/nm/albuquerque/new-mexico-equality/campaigns/slug_#{campaign.id}" + } + ] + }.with_indifferent_access + ) + end + end end diff --git a/spec/controllers/cards_spec.rb b/spec/controllers/cards_spec.rb index 43b025c1bc..bc122375ad 100644 --- a/spec/controllers/cards_spec.rb +++ b/spec/controllers/cards_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe CardsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'accept all' do - describe 'create' do + describe "accept all" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, with_status: 200 end end diff --git a/spec/controllers/concerns/api/transaction/current_spec.rb b/spec/controllers/concerns/api/transaction/current_spec.rb index d977122aac..29822509c2 100644 --- a/spec/controllers/concerns/api/transaction/current_spec.rb +++ b/spec/controllers/concerns/api/transaction/current_spec.rb @@ -2,34 +2,34 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -describe 'Controllers::Api::Transaction::Current' do - let(:transaction) { force_create(:transaction_for_donation) } - let(:nonprofit) { transaction.nonprofit } +describe "Controllers::Api::Transaction::Current" do + let(:transaction) { force_create(:transaction_for_donation) } + let(:nonprofit) { transaction.nonprofit } - controller(Api::ApiController) do - include Controllers::Api::Transaction::Current + controller(Api::ApiController) do + include Controllers::Api::Transaction::Current - def index - render json: { - transaction: current_transaction.id - } - end - end + def index + render json: { + transaction: current_transaction.id + } + end + end - it 'gets transaction if found' do - get :index, params: { nonprofit_id: nonprofit.id, transaction_id: transaction.id } - expect(response.parsed_body).to eq( - { - 'transaction' => transaction.id - } - ) - end + it "gets transaction if found" do + get :index, params: {nonprofit_id: nonprofit.id, transaction_id: transaction.id} + expect(response.parsed_body).to eq( + { + "transaction" => transaction.id + } + ) + end - it 'throw RecordNotFound if not found' do - expect do - get :index, params: { nonprofit_id: nonprofit.id, transaction_id: 124_124_905 } - end.to raise_error(ActiveRecord::RecordNotFound) - end + it "throw RecordNotFound if not found" do + expect do + get :index, params: {nonprofit_id: nonprofit.id, transaction_id: 124_124_905} + end.to raise_error(ActiveRecord::RecordNotFound) + end end diff --git a/spec/controllers/concerns/supporter/current_spec.rb b/spec/controllers/concerns/supporter/current_spec.rb index 83396f98f0..ee2059e1c3 100644 --- a/spec/controllers/concerns/supporter/current_spec.rb +++ b/spec/controllers/concerns/supporter/current_spec.rb @@ -2,46 +2,46 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -describe 'Controllers::Supporter::Current' do - let(:nonprofit) { force_create(:nm_justice) } - let(:supporter) { force_create(:supporter) } +describe "Controllers::Supporter::Current" do + let(:nonprofit) { force_create(:nm_justice) } + let(:supporter) { force_create(:supporter) } - controller(ApplicationController) do - include Controllers::User::Authorization - include Controllers::Supporter::Current + controller(ApplicationController) do + include Controllers::User::Authorization + include Controllers::Supporter::Current - def index - render json: { - supporter: "supporters: #{current_supporter.id}", - nonprofit: "nonprofit: #{current_nonprofit.id}" - } - end - end + def index + render json: { + supporter: "supporters: #{current_supporter.id}", + nonprofit: "nonprofit: #{current_nonprofit.id}" + } + end + end - it 'handles situations where we use id' do - nonprofit - supporter - get :index, params: { nonprofit_id: nonprofit.id, id: supporter.id } - expect(response.parsed_body).to eq( - { - 'supporter' => "supporters: #{supporter.id}", - 'nonprofit' => "nonprofit: #{nonprofit.id}" - } - ) - end + it "handles situations where we use id" do + nonprofit + supporter + get :index, params: {nonprofit_id: nonprofit.id, id: supporter.id} + expect(response.parsed_body).to eq( + { + "supporter" => "supporters: #{supporter.id}", + "nonprofit" => "nonprofit: #{nonprofit.id}" + } + ) + end - it 'handles situations where we use supporter_id' do - nonprofit - supporter + it "handles situations where we use supporter_id" do + nonprofit + supporter - get :index, params: { nonprofit_id: nonprofit.id, supporter_id: supporter.id, id: 1 } - expect(response.parsed_body).to eq( - { - 'supporter' => "supporters: #{supporter.id}", - 'nonprofit' => "nonprofit: #{nonprofit.id}" - } - ) - end + get :index, params: {nonprofit_id: nonprofit.id, supporter_id: supporter.id, id: 1} + expect(response.parsed_body).to eq( + { + "supporter" => "supporters: #{supporter.id}", + "nonprofit" => "nonprofit: #{nonprofit.id}" + } + ) + end end diff --git a/spec/controllers/direct_debit_details_spec.rb b/spec/controllers/direct_debit_details_spec.rb index 2c37d57b3b..38539c1107 100644 --- a/spec/controllers/direct_debit_details_spec.rb +++ b/spec/controllers/direct_debit_details_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe DirectDebitDetailsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'open to all' do - describe 'create' do + describe "open to all" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end diff --git a/spec/controllers/email_settings_spec.rb b/spec/controllers/email_settings_spec.rb index a783a88caa..e98aa02fad 100644 --- a/spec/controllers/email_settings_spec.rb +++ b/spec/controllers/email_settings_spec.rb @@ -2,18 +2,18 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe EmailSettingsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do + describe "rejects unauthorized users" do + describe "create" do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end - describe 'index' do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end end diff --git a/spec/controllers/emails_spec.rb b/spec/controllers/emails_spec.rb index f0be0737c8..ebf2e5a96a 100644 --- a/spec/controllers/emails_spec.rb +++ b/spec/controllers/emails_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe EmailsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do + describe "rejects unauthorized users" do + describe "create" do include_context :open_to_registered, :post, :create end end diff --git a/spec/controllers/event_discounts_spec.rb b/spec/controllers/event_discounts_spec.rb index 98d580e371..f96a848d76 100644 --- a/spec/controllers/event_discounts_spec.rb +++ b/spec/controllers/event_discounts_spec.rb @@ -2,29 +2,29 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe EventDiscountsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do + describe "rejects unauthorized users" do + describe "create" do include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event end - describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + describe "update" do + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: "2" end - describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + describe "destroy" do + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: "2" end end - describe 'open to all' do - describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + describe "open to all" do + describe "index" do + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event, id: "2" end end end diff --git a/spec/controllers/events_spec.rb b/spec/controllers/events_spec.rb index 41d6fda009..938bfe9136 100644 --- a/spec/controllers/events_spec.rb +++ b/spec/controllers/events_spec.rb @@ -2,50 +2,55 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe EventsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'create' do + describe "create" do include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, id: :__our_event end - describe 'update' do + + describe "update" do include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_event, with_status: 200 end - describe 'duplicate' do + + describe "duplicate" do include_context :open_to_event_editor, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_event end - describe 'soft_delete' do + + describe "soft_delete" do include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, event_id: :__our_event end - describe 'stats' do + + describe "stats" do include_context :open_to_event_editor, :get, :stats, nonprofit_id: :__our_np, id: :__our_event, without_json_view: true end - describe 'name_and_id' do + describe "name_and_id" do include_context :open_to_np_associate, :get, :name_and_id, nonprofit_id: :__our_np, with_status: 200 end end - describe 'open to all' do - describe 'index' do + describe "open to all" do + describe "index" do include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, without_json_view: true end - describe 'listings' do + describe "listings" do include_context :open_to_all, :get, :listings, nonprofit_id: :__our_np end - describe 'show' do + describe "show" do include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_event, without_json_view: true end - describe 'activities' do + describe "activities" do include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_event end - describe 'metrics' do + + describe "metrics" do include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_event end end diff --git a/spec/controllers/front_spec.rb b/spec/controllers/front_spec.rb index 36004e5e3b..0e0af805ee 100644 --- a/spec/controllers/front_spec.rb +++ b/spec/controllers/front_spec.rb @@ -2,33 +2,33 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe FrontController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'accept all' do - describe 'index' do + describe "accept all" do + describe "index" do include_context :open_to_all, :get, :index end end end - describe 'have nonprofit info' do + describe "have nonprofit info" do include_context :shared_user_context - it 'redirect to nonprofit admin' do + it "redirect to nonprofit admin" do sign_in user_as_np_admin get(:index) expect(response).to redirect_to dashboard_nonprofit_path(nonprofit) end - it 'redirect to nonprofit admin' do + it "redirect to nonprofit admin" do sign_in user_as_np_associate get(:index) expect(response).to redirect_to dashboard_nonprofit_path(nonprofit) end - it 'redirect to general user' do + it "redirect to general user" do nonprofit unauth_user.create_profile sign_in unauth_user diff --git a/spec/controllers/image_attachments_spec.rb b/spec/controllers/image_attachments_spec.rb index a3aad9ec01..56d54456b8 100644 --- a/spec/controllers/image_attachments_spec.rb +++ b/spec/controllers/image_attachments_spec.rb @@ -2,18 +2,18 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe ImageAttachmentsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do + describe "rejects unauthorized users" do + describe "create" do include_context :open_to_confirmed_users, :post, :create end - describe 'remove' do + describe "remove" do include_context :open_to_confirmed_users, :post, :remove end end diff --git a/spec/controllers/nonprofits/activities_spec.rb b/spec/controllers/nonprofits/activities_spec.rb index 226a82c32c..22c62d4df0 100644 --- a/spec/controllers/nonprofits/activities_spec.rb +++ b/spec/controllers/nonprofits/activities_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::ActivitiesController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'get' do + describe "rejects unauthorized users" do + describe "get" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1111 end end diff --git a/spec/controllers/nonprofits/bank_accounts_spec.rb b/spec/controllers/nonprofits/bank_accounts_spec.rb index df6c5a8e01..bd1af53cd0 100644 --- a/spec/controllers/nonprofits/bank_accounts_spec.rb +++ b/spec/controllers/nonprofits/bank_accounts_spec.rb @@ -2,33 +2,33 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::BankAccountsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'create' do + describe "rejects unauthenticated users" do + describe "create" do include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np end - describe 'confirmation' do + describe "confirmation" do include_context :open_to_np_admin, :get, :confirmation, nonprofit_id: :__our_np, without_json_view: true end - describe 'confirm' do + describe "confirm" do include_context :open_to_np_admin, :post, :confirm, nonprofit_id: :__our_np end - describe 'cancellation' do + describe "cancellation" do include_context :open_to_np_admin, :get, :cancellation, nonprofit_id: :__our_np, without_json_view: true end - describe 'cancel' do + describe "cancel" do include_context :open_to_np_admin, :post, :cancel, nonprofit_id: :__our_np end - describe 'resend_confirmation' do + describe "resend_confirmation" do include_context :open_to_np_admin, :post, :resend_confirmation, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/button_spec.rb b/spec/controllers/nonprofits/button_spec.rb index b7f023dc49..e3b28b00b2 100644 --- a/spec/controllers/nonprofits/button_spec.rb +++ b/spec/controllers/nonprofits/button_spec.rb @@ -2,25 +2,25 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::ButtonController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'send_code' do + describe "rejects unauthenticated users" do + describe "send_code" do include_context :open_to_registered, :get, :send_code, nonprofit_id: :__our_np end - describe 'basic' do + describe "basic" do include_context :open_to_registered, :get, :basic, nonprofit_id: :__our_np, without_json_view: true end - describe 'guided' do + describe "guided" do include_context :open_to_registered, :get, :guided, nonprofit_id: :__our_np, without_json_view: true end - describe 'advanced' do + describe "advanced" do include_context :open_to_registered, :get, :advanced, nonprofit_id: :__our_np, without_json_view: true end end diff --git a/spec/controllers/nonprofits/charges_spec.rb b/spec/controllers/nonprofits/charges_spec.rb index d0130065c8..b40e8592d4 100644 --- a/spec/controllers/nonprofits/charges_spec.rb +++ b/spec/controllers/nonprofits/charges_spec.rb @@ -2,13 +2,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::ChargesController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'get' do + describe "rejects unauthenticated users" do + describe "get" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/custom_field_definitions_spec.rb b/spec/controllers/nonprofits/custom_field_definitions_spec.rb index a36b8ccc04..d1b37fbb4a 100644 --- a/spec/controllers/nonprofits/custom_field_definitions_spec.rb +++ b/spec/controllers/nonprofits/custom_field_definitions_spec.rb @@ -2,22 +2,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::CustomFieldDefinitionsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'get custom field definitions' do + describe "rejects unauthenticated users" do + describe "get custom field definitions" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, without_json_view: true end - describe 'create' do + describe "create" do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end - describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + describe "destroy" do + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/nonprofits/custom_fields_joins_spec.rb b/spec/controllers/nonprofits/custom_fields_joins_spec.rb index ab6f42cd28..e7444a3213 100644 --- a/spec/controllers/nonprofits/custom_fields_joins_spec.rb +++ b/spec/controllers/nonprofits/custom_fields_joins_spec.rb @@ -2,22 +2,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::CustomFieldJoinsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'index' do + describe "rejects unauthenticated users" do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1, without_json_view: true end - describe 'modify' do - include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: '1' + describe "modify" do + include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: "1" end - describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1', supporter_id: 1 + describe "destroy" do + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1", supporter_id: 1 end end end diff --git a/spec/controllers/nonprofits/donations_spec.rb b/spec/controllers/nonprofits/donations_spec.rb index c492efa5de..8b66af85d7 100644 --- a/spec/controllers/nonprofits/donations_spec.rb +++ b/spec/controllers/nonprofits/donations_spec.rb @@ -2,39 +2,40 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' -require 'controllers/support/new_controller_user_context' -require 'support/contexts/shared_donation_charge_context' +require "rails_helper" +require "controllers/support/shared_user_context" +require "controllers/support/new_controller_user_context" +require "support/contexts/shared_donation_charge_context" describe Nonprofits::DonationsController, type: :controller do - describe 'rejects unauthenticated users' do - describe 'index' do + describe "rejects unauthenticated users" do + describe "index" do include_context :shared_user_context - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, id: '1' + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, id: "1" end - describe 'update' do + describe "update" do include_context :shared_user_context - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: "1" end end - describe 'accept all users' do - describe 'create' do + + describe "accept all users" do + describe "create" do include_context :open_to_all, :get, :create, nonprofit_id: :__our_np, with_status: 200 end - describe 'follow up' do - include_context :open_to_all, :put, :followup, nonprofit_id: :__our_np, id: '1' + describe "follow up" do + include_context :open_to_all, :put, :followup, nonprofit_id: :__our_np, id: "1" end end end -describe '.create_offsite', type: :request do - describe 'create_offsite' do +describe ".create_offsite", type: :request do + describe "create_offsite" do include_context :shared_donation_charge_context include_context :general_shared_user_context - require 'support/contexts/general_shared_user_context.rb' + require "support/contexts/general_shared_user_context" # it 'reject non-campaign editors (and np authorized folks)', :type => :request do # run_authorization_tests({method: :post, action: "/nonprofits/#{nonprofit.id}/donations/create_offsite", diff --git a/spec/controllers/nonprofits/email_lists_spec.rb b/spec/controllers/nonprofits/email_lists_spec.rb index 4eef269c80..d36c79ec84 100644 --- a/spec/controllers/nonprofits/email_lists_spec.rb +++ b/spec/controllers/nonprofits/email_lists_spec.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::EmailListsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'index' do + describe "rejects unauthenticated users" do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end - describe 'create' do + describe "create" do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/imports_spec.rb b/spec/controllers/nonprofits/imports_spec.rb index d0ca5b3589..7ab5bfcbf9 100644 --- a/spec/controllers/nonprofits/imports_spec.rb +++ b/spec/controllers/nonprofits/imports_spec.rb @@ -2,13 +2,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::ImportsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'create' do + describe "rejects unauthenticated users" do + describe "create" do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb b/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb index f1deafc875..33b3a9c2da 100644 --- a/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb +++ b/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::MiscellaneousNpInfosController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'show' do + describe "rejects unauthenticated users" do + describe "show" do include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np end - describe 'update' do + describe "update" do include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/nonprofit_keys_spec.rb b/spec/controllers/nonprofits/nonprofit_keys_spec.rb index 71e2da49af..e56100e8d3 100644 --- a/spec/controllers/nonprofits/nonprofit_keys_spec.rb +++ b/spec/controllers/nonprofits/nonprofit_keys_spec.rb @@ -2,21 +2,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::NonprofitKeysController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'index' do + describe "rejects unauthenticated users" do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end - describe 'mailchimp_login' do + describe "mailchimp_login" do include_context :open_to_np_associate, :get, :mailchimp_login, nonprofit_id: :__our_np end - describe 'mailchimp_landing' do + describe "mailchimp_landing" do include_context :open_to_np_associate, :get, :mailchimp_landing, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/payments_spec.rb b/spec/controllers/nonprofits/payments_spec.rb index e3d90eb530..ff482125de 100644 --- a/spec/controllers/nonprofits/payments_spec.rb +++ b/spec/controllers/nonprofits/payments_spec.rb @@ -2,30 +2,30 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::PaymentsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'get payments' do + describe "rejects unauthenticated users" do + describe "get payments" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, without_json_view: true end - describe 'export payments' do + describe "export payments" do include_context :open_to_np_associate, :get, :export, nonprofit_id: :__our_np end - describe 'show payments' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1', with_status: 200 + describe "show payments" do + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: "1", with_status: 200 end - describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' + describe "update" do + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: "1" end - describe 'destroy payment' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + describe "destroy payment" do + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/nonprofits/payouts_spec.rb b/spec/controllers/nonprofits/payouts_spec.rb index 7ecc12ab11..8cec84af74 100644 --- a/spec/controllers/nonprofits/payouts_spec.rb +++ b/spec/controllers/nonprofits/payouts_spec.rb @@ -2,22 +2,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::PayoutsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'create' do + describe "rejects unauthenticated users" do + describe "create" do include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np end - describe 'index' do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, without_json_view: true end - describe 'show' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' + describe "show" do + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/nonprofits/recurring_donations_spec.rb b/spec/controllers/nonprofits/recurring_donations_spec.rb index f0a7403c5c..cebac3c5c2 100644 --- a/spec/controllers/nonprofits/recurring_donations_spec.rb +++ b/spec/controllers/nonprofits/recurring_donations_spec.rb @@ -2,35 +2,35 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::RecurringDonationsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'index' do + describe "rejects unauthenticated users" do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, without_json_view: true end - describe 'export' do + describe "export" do include_context :open_to_np_associate, :post, :export, nonprofit_id: :__our_np end - describe 'show' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1', with_status: 200 + describe "show" do + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: "1", with_status: 200 end - describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + describe "destroy" do + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end - describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' + describe "update" do + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: "1" end end - describe 'open for all' do - describe 'create' do + describe "open for all" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/reports_spec.rb b/spec/controllers/nonprofits/reports_spec.rb index 9ccdd94553..183aa8e3ff 100644 --- a/spec/controllers/nonprofits/reports_spec.rb +++ b/spec/controllers/nonprofits/reports_spec.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::ReportsController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'end_of_year' do + describe "rejects unauthenticated users" do + describe "end_of_year" do include_context :open_to_np_associate, :get, :end_of_year, nonprofit_id: :__our_np end - describe 'end_of_year_custom' do + describe "end_of_year_custom" do include_context :open_to_np_associate, :get, :end_of_year_custom, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits/supporters_spec.rb b/spec/controllers/nonprofits/supporters_spec.rb index 4cfbb10333..8e22952f47 100644 --- a/spec/controllers/nonprofits/supporters_spec.rb +++ b/spec/controllers/nonprofits/supporters_spec.rb @@ -2,51 +2,51 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::SupportersController, type: :controller do include_context :shared_user_context - describe 'rejects unauthenticated users' do - describe 'index' do + describe "rejects unauthenticated users" do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, without_json_view: true end - describe 'index_metrics' do + describe "index_metrics" do include_context :open_to_np_associate, :get, :index_metrics, nonprofit_id: :__our_np end - describe 'show' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' + describe "show" do + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: "1" end - describe 'email_address' do - include_context :open_to_np_associate, :get, :email_address, nonprofit_id: :__our_np, id: '1' + describe "email_address" do + include_context :open_to_np_associate, :get, :email_address, nonprofit_id: :__our_np, id: "1" end - describe 'full_contact' do - include_context :open_to_np_associate, :get, :full_contact, nonprofit_id: :__our_np, id: '1' + describe "full_contact" do + include_context :open_to_np_associate, :get, :full_contact, nonprofit_id: :__our_np, id: "1" end - describe 'info_card' do - include_context :open_to_np_associate, :get, :info_card, nonprofit_id: :__our_np, id: '1' + describe "info_card" do + include_context :open_to_np_associate, :get, :info_card, nonprofit_id: :__our_np, id: "1" end - describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' + describe "update" do + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: "1" end - describe 'bulk_delete' do + describe "bulk_delete" do include_context :open_to_np_associate, :delete, :bulk_delete, nonprofit_id: :__our_np end - describe 'merge' do + describe "merge" do include_context :open_to_np_associate, :delete, :bulk_delete, nonprofit_id: :__our_np end end - describe 'accept all users' do - describe 'create' do + describe "accept all users" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, with_status: 200 end end diff --git a/spec/controllers/nonprofits/tag_definitions_spec.rb b/spec/controllers/nonprofits/tag_definitions_spec.rb index 7fd8c1d702..850d6381c4 100644 --- a/spec/controllers/nonprofits/tag_definitions_spec.rb +++ b/spec/controllers/nonprofits/tag_definitions_spec.rb @@ -2,23 +2,23 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::TagDefinitionsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'index' do + describe "rejects unauthorized users" do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, with_status: 200 end - describe 'create' do + describe "create" do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end - describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + describe "destroy" do + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/nonprofits/tag_joins_spec.rb b/spec/controllers/nonprofits/tag_joins_spec.rb index 68b82d100b..4e8c59b06c 100644 --- a/spec/controllers/nonprofits/tag_joins_spec.rb +++ b/spec/controllers/nonprofits/tag_joins_spec.rb @@ -2,22 +2,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::TagJoinsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'index' do + describe "index" do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1 end - describe 'modify' do - include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: '1' + describe "modify" do + include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: "1" end - describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1', supporter_id: 2 + describe "destroy" do + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1", supporter_id: 2 end end end diff --git a/spec/controllers/nonprofits/trackings_spec.rb b/spec/controllers/nonprofits/trackings_spec.rb index 8822c119a7..ca5d6d753b 100644 --- a/spec/controllers/nonprofits/trackings_spec.rb +++ b/spec/controllers/nonprofits/trackings_spec.rb @@ -2,13 +2,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe Nonprofits::TrackingsController, type: :controller do include_context :shared_user_context - describe 'open to all' do - describe 'create' do + describe "open to all" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end diff --git a/spec/controllers/nonprofits_spec.rb b/spec/controllers/nonprofits_spec.rb index 7291cc83f9..5066229ca9 100644 --- a/spec/controllers/nonprofits_spec.rb +++ b/spec/controllers/nonprofits_spec.rb @@ -2,91 +2,92 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe NonprofitsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'update' do + describe "rejects unauthorized users" do + describe "update" do include_context :open_to_np_associate, :put, :update, id: :__our_np end - describe 'dashboard' do + describe "dashboard" do include_context :open_to_np_associate, :get, :dashboard, id: :__our_np, without_json_view: true end - describe 'dashboard_metrics' do + describe "dashboard_metrics" do include_context :open_to_np_associate, :get, :dashboard_metrics, id: :__our_np end - describe 'verify_identity' do + describe "verify_identity" do include_context :open_to_np_associate, :put, :verify_identity, id: :__our_np end - describe 'recurring_donation_stats' do + describe "recurring_donation_stats" do include_context :open_to_np_associate, :get, :recurring_donation_stats, id: :__our_np end - describe 'profile_todos' do + describe "profile_todos" do include_context :open_to_np_associate, :get, :profile_todos, id: :__our_np end - describe 'dashboard_todos' do + describe "dashboard_todos" do include_context :open_to_np_associate, :get, :dashboard_todos, id: :__our_np end - describe 'payment_history' do + describe "payment_history" do include_context :open_to_np_associate, :get, :payment_history, id: :__our_np end - describe 'destroy' do + describe "destroy" do include_context :open_to_super_admin, :delete, :destroy, id: :__our_np end end - describe 'open to all' do - describe 'show' do + describe "open to all" do + describe "show" do include_context :open_to_all, :get, :show, id: :__our_np, without_json_view: true end - describe 'btn' do + describe "btn" do include_context :open_to_all, :get, :btn, id: :__our_np, without_json_view: true end - describe 'supporter_form' do + describe "supporter_form" do include_context :open_to_all, :get, :supporter_form, id: :__our_np, without_json_view: true end - describe 'custom_supporter' do + describe "custom_supporter" do include_context :open_to_all, :post, :custom_supporter, id: :__our_np end - describe 'donate' do + describe "donate" do include_context :open_to_all, :get, :donate, id: :__our_np, without_json_view: true end - describe 'search' do + describe "search" do include_context :open_to_all, :get, :search end end end - describe '#donate' do + describe "#donate" do let(:nonprofit) { force_create(:nm_justice) } - it 'allows being put into a frame by not setting X-Frame-Options header' do + + it "allows being put into a frame by not setting X-Frame-Options header" do get :donate, params: {id: nonprofit.id} - expect(response.headers).to_not include 'X-Frame-Options' + expect(response.headers).to_not include "X-Frame-Options" end - end - describe '#btn' do + describe "#btn" do let(:nonprofit) { force_create(:nm_justice) } - it 'allows being put into a frame by not setting X-Frame-Options header' do + + it "allows being put into a frame by not setting X-Frame-Options header" do get :btn, params: {id: nonprofit.id} - expect(response.headers).to_not include 'X-Frame-Options' + expect(response.headers).to_not include "X-Frame-Options" end end end diff --git a/spec/controllers/profiles_spec.rb b/spec/controllers/profiles_spec.rb index 59c29657c3..7926258de4 100644 --- a/spec/controllers/profiles_spec.rb +++ b/spec/controllers/profiles_spec.rb @@ -2,28 +2,28 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe ProfilesController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'update' do + describe "rejects unauthorized users" do + describe "update" do include_context :open_to_profile_owner, :put, :update, id: :__our_profile end - describe 'fundraisers' do + describe "fundraisers" do include_context :open_to_profile_owner, :get, :fundraisers, id: :__our_profile, without_json_view: true end - describe 'donations_history' do + describe "donations_history" do include_context :open_to_profile_owner, :get, :donations_history, id: :__our_profile, without_json_view: true end end - describe 'open to all' do - describe 'show' do + describe "open to all" do + describe "show" do include_context :open_to_all, :get, :show, id: :__our_np, without_json_view: true end end diff --git a/spec/controllers/recurring_donations_spec.rb b/spec/controllers/recurring_donations_spec.rb index 76f2c08612..cfd080762a 100644 --- a/spec/controllers/recurring_donations_spec.rb +++ b/spec/controllers/recurring_donations_spec.rb @@ -2,27 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe RecurringDonationsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'open to all (note: edit token is checked inside methods)' do - describe 'edit' do - include_context :open_to_all, :get, :edit, nonprofit_id: :__our_np, id: '1', without_json_view: true + describe "open to all (note: edit token is checked inside methods)" do + describe "edit" do + include_context :open_to_all, :get, :edit, nonprofit_id: :__our_np, id: "1", without_json_view: true end - describe 'destroy' do - include_context :open_to_all, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + describe "destroy" do + include_context :open_to_all, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end - describe 'update' do - include_context :open_to_all, :put, :update, nonprofit_id: :__our_np, id: '1' + describe "update" do + include_context :open_to_all, :put, :update, nonprofit_id: :__our_np, id: "1" end - describe 'update_amount' do - include_context :open_to_all, :put, :update_amount, nonprofit_id: :__our_np, id: '1' + describe "update_amount" do + include_context :open_to_all, :put, :update_amount, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/roles_spec.rb b/spec/controllers/roles_spec.rb index b09cdef18c..6fffcb1bb7 100644 --- a/spec/controllers/roles_spec.rb +++ b/spec/controllers/roles_spec.rb @@ -2,19 +2,19 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe RolesController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do + describe "rejects unauthorized users" do + describe "create" do include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np end - describe 'destroy' do - include_context :open_to_np_admin, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + describe "destroy" do + include_context :open_to_np_admin, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/settings_spec.rb b/spec/controllers/settings_spec.rb index 4103f93601..271145d03a 100644 --- a/spec/controllers/settings_spec.rb +++ b/spec/controllers/settings_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe SettingsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'index' do + describe "rejects unauthorized users" do + describe "index" do include_context :open_to_registered, :get, :index, nonprofit_id: :__our_np, without_json_view: true end end diff --git a/spec/controllers/static_controller_spec.rb b/spec/controllers/static_controller_spec.rb index c7504900a6..426243e9fc 100644 --- a/spec/controllers/static_controller_spec.rb +++ b/spec/controllers/static_controller_spec.rb @@ -2,32 +2,31 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe StaticController, type: :controller do - describe '.ccs' do - - describe 'local_tar_gz' do - before (:each) do - Houdini.ccs = Houdini::Ccs.build('local_tar_gz') + describe ".ccs" do + describe "local_tar_gz" do + before do + Houdini.ccs = Houdini::Ccs.build("local_tar_gz") end - it 'fails on git archive' do + it "fails on git archive" do expect(Kernel).to receive(:system).and_return(false) - get('ccs') + get("ccs") expect(response.status).to eq 500 end end - describe 'github' do - before (:each) do - Houdini.ccs = Houdini::Ccs.build('github', account: 'account', repo: 'repo') + describe "github" do + before do + Houdini.ccs = Houdini::Ccs.build("github", account: "account", repo: "repo") end - it 'setup github' do - expect(File).to receive(:read).with("#{Rails.root}/CCS_HASH").and_return("hash\n") - get('ccs') - expect(response).to redirect_to 'https://github.com/account/repo/tree/hash' + it "setup github" do + expect(File).to receive(:read).with("#{Rails.root.join("CCS_HASH")}").and_return("hash\n") + get("ccs") + expect(response).to redirect_to "https://github.com/account/repo/tree/hash" end end end diff --git a/spec/controllers/super_admins_spec.rb b/spec/controllers/super_admins_spec.rb index 1ad40c74c4..f5e114a7c3 100644 --- a/spec/controllers/super_admins_spec.rb +++ b/spec/controllers/super_admins_spec.rb @@ -2,26 +2,26 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe SuperAdminsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'search_nonprofits' do + describe "rejects unauthorized users" do + describe "search_nonprofits" do include_context :open_to_super_admin, :get, :search_nonprofits end - describe 'search_profiles' do + describe "search_profiles" do include_context :open_to_super_admin, :get, :search_profiles end - describe 'search_fullcontact' do + describe "search_fullcontact" do include_context :open_to_super_admin, :get, :search_fullcontact end - describe 'index' do + describe "index" do include_context :open_to_super_admin, :get, :index, without_json_view: true end end diff --git a/spec/controllers/support/new_controller_user_context.rb b/spec/controllers/support/new_controller_user_context.rb index 44c6bb8a54..3f3a133584 100644 --- a/spec/controllers/support/new_controller_user_context.rb +++ b/spec/controllers/support/new_controller_user_context.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'support/contexts/general_shared_user_context' +require "support/contexts/general_shared_user_context" RSpec.shared_context :new_controller_user_context do include_context :general_shared_user_context def sign_in(user_to_signin) - post_via_redirect 'users/sign_in', 'user[email]' => user_to_signin.email, 'user[password]' => user_to_signin.password, format: 'json' + post_via_redirect "users/sign_in", "user[email]" => user_to_signin.email, "user[password]" => user_to_signin.password, :format => "json" end def sign_out - send(:get, 'users/sign_out') + send(:get, "users/sign_out") end def send(method, *args) @@ -38,7 +38,7 @@ def accept(user_to_signin:, method:, action:, args:) # expect_any_instance_of(described_class).to receive(action).and_return(ActionController::TestResponse.new(200)) # expect_any_instance_of(described_class).to receive(:render).and_return(nil) send(method, action, args) - expect(response.status).to_not eq(302), "expected success for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}" + expect(response.status).to_not eq(302), "expected success for user: #{user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ":" : ""} #{new_user&.attributes}" sign_out end @@ -49,7 +49,7 @@ def reject(user_to_signin:, method:, action:, args:) end sign_in new_user if new_user send(method, action, args) - expect(response.status).to eq(302), "expected failure for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}" + expect(response.status).to eq(302), "expected failure for user: #{user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ":" : ""} #{new_user&.attributes}" sign_out end end diff --git a/spec/controllers/support/shared_user_context.rb b/spec/controllers/support/shared_user_context.rb index 309fb074f9..ba02161c79 100644 --- a/spec/controllers/support/shared_user_context.rb +++ b/spec/controllers/support/shared_user_context.rb @@ -32,7 +32,7 @@ __create(:campaign_editor, campaign) end - let(:confirmed_user) do + let(:confirmed_user) do force_create(:user, confirmed_at: Time.current) end @@ -72,7 +72,7 @@ def __create_associate(host) u end - def send(method, action, args={}) + def send(method, action, args = {}) case method when :get get(action, **args) @@ -87,7 +87,7 @@ def send(method, action, args={}) def accept(user_to_signin, method, action, *args) test_variables = collect_test_variables(args) - request.accept = 'application/json' unless test_variables[:without_json_view] + request.accept = "application/json" unless test_variables[:without_json_view] sign_in user_to_signin if user_to_signin # allows us to run the helpers but ignore what the controller action does @@ -112,19 +112,19 @@ def reject(user_to_signin, method, action, *args) alias_method :redirects_to, :reject def reduce_params(*args) - { params: args.reduce({}, :merge) } + {params: args.reduce({}, :merge)} end def collect_test_variables(*args) test_vars = {} args.collect do |items| - if items.kind_of?(Array) + if items.is_a?(Array) items.each do |k, v| - test_vars.merge!(k.slice(:without_json_view, :with_status)) if k.kind_of?(Hash) + test_vars.merge!(k.slice(:without_json_view, :with_status)) if k.is_a?(Hash) end end end - return test_vars + test_vars end def fix_args(*args) @@ -161,47 +161,47 @@ def fix_args(*args) let(:fixed_args) do fix_args(*args) end - it 'accepts no user' do + it "accepts no user" do accept(nil, method, action, *fixed_args) end - it 'accepts user with no roles' do + it "accepts user with no roles" do accept(unauth_user, method, action, *fixed_args) end - it 'accepts nonprofit admin' do + it "accepts nonprofit admin" do accept(user_as_np_admin, method, action, *fixed_args) end - it 'accepts nonprofit associate' do + it "accepts nonprofit associate" do accept(user_as_np_associate, method, action, *fixed_args) end - it 'accepts other admin' do + it "accepts other admin" do accept(user_as_other_np_admin, method, action, *fixed_args) end - it 'accepts other associate' do + it "accepts other associate" do accept(user_as_other_np_associate, method, action, *fixed_args) end - it 'accepts campaign editor' do + it "accepts campaign editor" do accept(campaign_editor, method, action, *fixed_args) end - it 'accept confirmed user' do + it "accept confirmed user" do accept(confirmed_user, method, action, *fixed_args) end - it 'accept event editor' do + it "accept event editor" do accept(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'accept profile user' do + it "accept profile user" do accept(user_with_profile, method, action, *fixed_args) end end @@ -212,47 +212,47 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'accepts nonprofit admin' do + it "accepts nonprofit admin" do accept(user_as_np_admin, method, action, *fixed_args) end - it 'accepts nonprofit associate' do + it "accepts nonprofit associate" do accept(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'rejects campaign editor' do + it "rejects campaign editor" do reject(campaign_editor, method, action, *fixed_args) end - it 'rejects confirmed user' do + it "rejects confirmed user" do reject(confirmed_user, method, action, *fixed_args) end - it 'reject event editor' do + it "reject event editor" do reject(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'rejects profile user' do + it "rejects profile user" do reject(user_with_profile, method, action, *fixed_args) end end @@ -263,46 +263,46 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'accepts nonprofit admin' do + it "accepts nonprofit admin" do accept(user_as_np_admin, method, action, *fixed_args) end - it 'rejects nonprofit associate' do + it "rejects nonprofit associate" do reject(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'rejects campaign editor' do + it "rejects campaign editor" do reject(campaign_editor, method, action, *fixed_args) end - it 'rejects confirmed user' do + it "rejects confirmed user" do reject(confirmed_user, method, action, *fixed_args) end - it 'reject event editor' do + it "reject event editor" do reject(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'rejects profile user' do + it "rejects profile user" do reject(user_with_profile, method, action, *fixed_args) end end @@ -313,46 +313,46 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'accepts user with no roles' do + it "accepts user with no roles" do accept(unauth_user, method, action, *fixed_args) end - it 'accepts nonprofit admin' do + it "accepts nonprofit admin" do accept(user_as_np_admin, method, action, *fixed_args) end - it 'accepts nonprofit associate' do + it "accepts nonprofit associate" do accept(user_as_np_associate, method, action, *fixed_args) end - it 'accepts other admin' do + it "accepts other admin" do accept(user_as_other_np_admin, method, action, *fixed_args) end - it 'accepts other associate' do + it "accepts other associate" do accept(user_as_other_np_associate, method, action, *fixed_args) end - it 'accepts campaign editor' do + it "accepts campaign editor" do accept(campaign_editor, method, action, *fixed_args) end - it 'accepts confirmed user' do + it "accepts confirmed user" do accept(confirmed_user, method, action, *fixed_args) end - it 'accept event editor' do + it "accept event editor" do accept(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'accept profile user' do + it "accept profile user" do accept(user_with_profile, method, action, *fixed_args) end end @@ -363,46 +363,46 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'accepts nonprofit admin' do + it "accepts nonprofit admin" do accept(user_as_np_admin, method, action, *fixed_args) end - it 'accepts nonprofit associate' do + it "accepts nonprofit associate" do accept(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'accepts campaign editor' do + it "accepts campaign editor" do accept(campaign_editor, method, action, *fixed_args) end - it 'rejects confirmed user' do + it "rejects confirmed user" do reject(confirmed_user, method, action, *fixed_args) end - it 'reject event editor' do + it "reject event editor" do reject(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'rejects profile user' do + it "rejects profile user" do reject(user_with_profile, method, action, *fixed_args) end end @@ -413,46 +413,46 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'reject nonprofit admin' do + it "reject nonprofit admin" do reject(user_as_np_admin, method, action, *fixed_args) end - it 'reject nonprofit associate' do + it "reject nonprofit associate" do reject(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'reject campaign editor' do + it "reject campaign editor" do reject(campaign_editor, method, action, *fixed_args) end - it 'accepts confirmed user' do + it "accepts confirmed user" do accept(confirmed_user, method, action, *fixed_args) end - it 'reject event editor' do + it "reject event editor" do reject(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'rejects profile user' do + it "rejects profile user" do reject(user_with_profile, method, action, *fixed_args) end end @@ -463,45 +463,45 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'accept nonprofit admin' do + it "accept nonprofit admin" do accept(user_as_np_admin, method, action, *fixed_args) end - it 'nonprofit associate' do + it "nonprofit associate" do accept(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'reject campaign editor' do + it "reject campaign editor" do reject(campaign_editor, method, action, *fixed_args) end - it 'reject confirmed user' do + it "reject confirmed user" do reject(confirmed_user, method, action, *fixed_args) end - it 'accept event editor' do + it "accept event editor" do accept(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'rejects profile user' do + it "rejects profile user" do reject(user_with_profile, method, action, *fixed_args) end end @@ -512,47 +512,47 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'rejects nonprofit admin' do + it "rejects nonprofit admin" do reject(user_as_np_admin, method, action, *fixed_args) end - it 'rejects nonprofit associate' do + it "rejects nonprofit associate" do reject(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'rejects campaign editor' do + it "rejects campaign editor" do reject(campaign_editor, method, action, *fixed_args) end - it 'rejects confirmed user' do + it "rejects confirmed user" do reject(confirmed_user, method, action, *fixed_args) end - it 'reject event editor' do + it "reject event editor" do reject(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'rejects profile user' do + it "rejects profile user" do reject(user_with_profile, method, action, *fixed_args) end end @@ -563,47 +563,47 @@ def fix_args(*args) fix_args(*args) end - it 'rejects no user' do + it "rejects no user" do reject(nil, method, action, *fixed_args) end - it 'rejects user with no roles' do + it "rejects user with no roles" do reject(unauth_user, method, action, *fixed_args) end - it 'rejects nonprofit admin' do + it "rejects nonprofit admin" do reject(user_as_np_admin, method, action, *fixed_args) end - it 'rejects nonprofit associate' do + it "rejects nonprofit associate" do reject(user_as_np_associate, method, action, *fixed_args) end - it 'rejects other admin' do + it "rejects other admin" do reject(user_as_other_np_admin, method, action, *fixed_args) end - it 'rejects other associate' do + it "rejects other associate" do reject(user_as_other_np_associate, method, action, *fixed_args) end - it 'rejects campaign editor' do + it "rejects campaign editor" do reject(campaign_editor, method, action, *fixed_args) end - it 'rejects confirmed user' do + it "rejects confirmed user" do reject(confirmed_user, method, action, *fixed_args) end - it 'reject event editor' do + it "reject event editor" do reject(event_editor, method, action, *fixed_args) end - it 'accepts super admin' do + it "accepts super admin" do accept(super_admin, method, action, *fixed_args) end - it 'accepts profile user' do + it "accepts profile user" do accept(user_with_profile, method, action, *fixed_args) end end diff --git a/spec/controllers/ticket_levels_spec.rb b/spec/controllers/ticket_levels_spec.rb index a26beef574..1791c49377 100644 --- a/spec/controllers/ticket_levels_spec.rb +++ b/spec/controllers/ticket_levels_spec.rb @@ -2,50 +2,53 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe TicketLevelsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'create' do - include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event, id: '1' + describe "rejects unauthorized users" do + describe "create" do + include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" end - describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: '1' + + describe "update" do + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" end - describe 'update_order' do + + describe "update_order" do include_context :open_to_event_editor, :put, :update_order, nonprofit_id: :__our_np, event_id: :__our_event end - describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: '1' + + describe "destroy" do + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" end end - describe 'open to all' do - describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + describe "open to all" do + describe "show" do + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, event_id: :__our_event, id: "2" end - describe 'index' do + describe "index" do include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event end end end - describe 'verify deleted doesnt get passed through on update' do + describe "verify deleted doesnt get passed through on update" do include_context :shared_user_context include_context :shared_donation_charge_context - let(:ticket_level_name) {"TICKET LEVEL"} - let(:order) { 3} - let(:free_amount) { 0} - let(:non_free_amount) {7500} - let(:ticket_limit) {4} - let(:description) {"Description"} + let(:ticket_level_name) { "TICKET LEVEL" } + let(:order) { 3 } + let(:free_amount) { 0 } + let(:non_free_amount) { 7500 } + let(:ticket_limit) { 4 } + let(:description) { "Description" } let(:ticket_level_2) { event.ticket_levels.create( - name: ticket_level_name, + name: ticket_level_name, limit: nil, admin_only: false, order: order, @@ -53,13 +56,14 @@ description: description ) } - it 'updates safely' do + + it "updates safely" do input = { nonprofit_id: nonprofit.id, event_id: event.id, id: ticket_level_2.id, ticket_level: { - name: ticket_level_name, + name: ticket_level_name, limit: nil, admin_only: false, order: order, @@ -71,7 +75,7 @@ sign_in user_as_np_admin put :update, params: input, xhr: true expect(response).to have_http_status :ok - + ticket_level_2.reload expect(ticket_level_2.deleted).to eq false expect(ticket_level_2.amount).to eq 0 diff --git a/spec/controllers/tickets_spec.rb b/spec/controllers/tickets_spec.rb index 1a6bbfbfde..0917e5c101 100644 --- a/spec/controllers/tickets_spec.rb +++ b/spec/controllers/tickets_spec.rb @@ -2,36 +2,36 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" describe TicketsController, type: :controller do - describe 'authorization' do + describe "authorization" do include_context :shared_user_context - describe 'rejects unauthorized users' do - describe 'index' do + describe "rejects unauthorized users" do + describe "index" do include_context :open_to_event_editor, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event, without_json_view: true end - describe 'update' do + describe "update" do include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end - describe 'destroy' do + describe "destroy" do include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end - describe 'delete_card_for_ticket' do + describe "delete_card_for_ticket" do include_context :open_to_np_associate, :post, :delete_card_for_ticket, nonprofit_id: :__our_np, event_id: :__our_event, id: 11_111 end end - describe 'open to all' do - describe 'create' do + describe "open to all" do + describe "create" do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event end - describe 'add_note' do + describe "add_note" do include_context :open_to_all, :put, :add_note, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end end diff --git a/spec/controllers/widget_controller_spec.rb b/spec/controllers/widget_controller_spec.rb index d781460c2d..a223946540 100644 --- a/spec/controllers/widget_controller_spec.rb +++ b/spec/controllers/widget_controller_spec.rb @@ -2,22 +2,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe WidgetController do - describe 'v2' do - it 'accepts requests without a CORS error' do - expect { get :v2, format: :js }.to_not raise_error - end + describe "v2" do + it "accepts requests without a CORS error" do + expect { get :v2, format: :js }.to_not raise_error + end - it 'has a cache-control header of 10 minutes' do - get :v2, format: :js - expect(response.headers['Cache-Control']).to include 'max-age=600' - end + it "has a cache-control header of 10 minutes" do + get :v2, format: :js + expect(response.headers["Cache-Control"]).to include "max-age=600" + end - it 'does redirect' do - get :v2, format: :js - expect(response.headers.has_key?('Location')).to be true - end - end + it "does redirect" do + get :v2, format: :js + expect(response.headers.has_key?("Location")).to be true + end + end end diff --git a/spec/factories/billing_plans.rb b/spec/factories/billing_plans.rb index 3acb972b88..b085f676db 100644 --- a/spec/factories/billing_plans.rb +++ b/spec/factories/billing_plans.rb @@ -5,7 +5,7 @@ FactoryBot.define do factory :billing_plan do amount { 0 } - name { 'Default Plan' } + name { "Default Plan" } trait :default do end end diff --git a/spec/factories/campaign_gift_options.rb b/spec/factories/campaign_gift_options.rb index a70582dc82..b040544728 100644 --- a/spec/factories/campaign_gift_options.rb +++ b/spec/factories/campaign_gift_options.rb @@ -3,36 +3,36 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :campaign_gift_option do - sequence(:name) { |i| "name_#{i}" } - campaign - amount_one_time { 200 } - end + factory :campaign_gift_option do + sequence(:name) { |i| "name_#{i}" } + campaign + amount_one_time { 200 } + end - factory :campaign_gift_option_with_campaign, class: 'CampaignGiftOption' do - campaign { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } - factory :campaign_gift_option_with_campaign_with_one_time_amount do - name { 'has one time amount' } - description { 'one time description' } - amount_one_time { 200 } - end + factory :campaign_gift_option_with_campaign, class: "CampaignGiftOption" do + campaign { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } + factory :campaign_gift_option_with_campaign_with_one_time_amount do + name { "has one time amount" } + description { "one time description" } + amount_one_time { 200 } + end - factory :campaign_gift_option_with_campaign_with_recurring_amount do - name { 'has recurring amount' } - description { 'a recurring description!' } - amount_recurring { 400 } - quantity { 4 } - end + factory :campaign_gift_option_with_campaign_with_recurring_amount do + name { "has recurring amount" } + description { "a recurring description!" } + amount_recurring { 400 } + quantity { 4 } + end - factory :campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount do - name { 'has both one time and recurring amount' } - description { 'one time AND recurring' } - amount_one_time { 300 } - amount_recurring { 500 } - quantity { 50 } - to_ship { true } - order { 5 } - hide_contributions { true } - end - end + factory :campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount do + name { "has both one time and recurring amount" } + description { "one time AND recurring" } + amount_one_time { 300 } + amount_recurring { 500 } + quantity { 50 } + to_ship { true } + order { 5 } + hide_contributions { true } + end + end end diff --git a/spec/factories/campaigns.rb b/spec/factories/campaigns.rb index 5138502f5a..a1f5a8da17 100644 --- a/spec/factories/campaigns.rb +++ b/spec/factories/campaigns.rb @@ -10,11 +10,10 @@ sequence(:slug) { |i| "slug_#{i}" } end - factory :fv_poverty_fighting_campaign, class: 'Campaign' do - name { "Fighting Poverty 2021"} - goal_amount { 10000} - - + factory :fv_poverty_fighting_campaign, class: "Campaign" do + name { "Fighting Poverty 2021" } + goal_amount { 10000 } + factory :fv_poverty_fighting_campaign_with_nonprofit_and_profile do nonprofit { create(:fv_poverty) } profile diff --git a/spec/factories/cards.rb b/spec/factories/cards.rb index 936d26750c..1f8381b456 100644 --- a/spec/factories/cards.rb +++ b/spec/factories/cards.rb @@ -5,13 +5,13 @@ FactoryBot.define do factory :card do factory :active_card_1 do - name { 'card 1' } + name { "card 1" } end factory :active_card_2 do - name { 'card 1' } + name { "card 1" } end factory :inactive_card do - name { 'card 1' } + name { "card 1" } inactive { true } end end diff --git a/spec/factories/custom_field_definitions.rb b/spec/factories/custom_field_definitions.rb index 7978d78544..3f02c4ef45 100644 --- a/spec/factories/custom_field_definitions.rb +++ b/spec/factories/custom_field_definitions.rb @@ -3,12 +3,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :custom_field_definition do - nonprofit { '' } - name { 'Def Name' } - factory :custom_field_definition_with_nonprofit do - name { 'Def Name' } - nonprofit { create(:fv_poverty) } - end - end + factory :custom_field_definition do + nonprofit { "" } + name { "Def Name" } + factory :custom_field_definition_with_nonprofit do + name { "Def Name" } + nonprofit { create(:fv_poverty) } + end + end end diff --git a/spec/factories/custom_field_joins.rb b/spec/factories/custom_field_joins.rb index 61fc1f08cb..2beeebc681 100644 --- a/spec/factories/custom_field_joins.rb +++ b/spec/factories/custom_field_joins.rb @@ -8,7 +8,7 @@ supporter_id { 4 } created_at { DateTime.now } updated_at { DateTime.now } - value { 'value' } + value { "value" } trait :value_from_id do after(:create) do |cfj| diff --git a/spec/factories/donations.rb b/spec/factories/donations.rb index 0dac205bef..48ee75e509 100644 --- a/spec/factories/donations.rb +++ b/spec/factories/donations.rb @@ -4,21 +4,23 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do factory :donation do - factory :donation_with_dedication_designation do - dedication { { - contact: { - email: 'email@ema.com' - }, - name: 'our loved one', - note: "we miss them dearly", - type: 'memory' - } } - designation { 'designated for soup kitchen'} + factory :donation_with_dedication_designation do + dedication { + { + contact: { + email: "email@ema.com" + }, + name: "our loved one", + note: "we miss them dearly", + type: "memory" + } + } + designation { "designated for soup kitchen" } - nonprofit {association :fv_poverty} + nonprofit { association :fv_poverty } - supporter { association :supporter} - amount {500} + supporter { association :supporter } + amount { 500 } end - end + end end diff --git a/spec/factories/events.rb b/spec/factories/events.rb index 888c7ba38d..86f7cf4cff 100644 --- a/spec/factories/events.rb +++ b/spec/factories/events.rb @@ -4,42 +4,42 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do factory :event do - name { 'The event of Wonders' } + name { "The event of Wonders" } start_datetime { DateTime.new(2025, 5, 11, 4, 5, 6) } end_datetime { DateTime.new(2025, 5, 11, 5, 1, 7) } - address { '100 N Appleton St' } - city { 'Appleton' } - state_code { 'WI' } - slug { 'event-of-wonders' } + address { "100 N Appleton St" } + city { "Appleton" } + state_code { "WI" } + slug { "event-of-wonders" } nonprofit_id { 55352 } profile end - factory :fv_poverty_fighting_event, class: 'Event' do - name { "Fighting Poverty 2021"} - + factory :fv_poverty_fighting_event, class: "Event" do + name { "Fighting Poverty 2021" } + start_datetime { DateTime.new(2025, 5, 11, 4, 5, 6) } end_datetime { DateTime.new(2025, 5, 11, 5, 1, 7) } - address { '100 N Appleton St' } - city { 'Appleton' } - state_code { 'WI' } - slug { 'fighting-poverty' } + address { "100 N Appleton St" } + city { "Appleton" } + state_code { "WI" } + slug { "fighting-poverty" } factory :fv_poverty_fighting_event_with_nonprofit_and_profile do nonprofit { create(:fv_poverty) } profile end end - + factory :event_base, class: "Event" do - sequence(:name){|i| "The event of Wonders #{i}"} - start_datetime {DateTime.new(2025, 5, 11, 4,5,6)} - end_datetime {DateTime.new(2025, 5, 11, 5,1,7)} - address {"100 N Appleton St"} - city {"Appleton"} - state_code {"WI"} - sequence(:slug){|i| "event-of-wonders-#{i}"} - nonprofit {association :nonprofit_base} + sequence(:name) { |i| "The event of Wonders #{i}" } + start_datetime { DateTime.new(2025, 5, 11, 4, 5, 6) } + end_datetime { DateTime.new(2025, 5, 11, 5, 1, 7) } + address { "100 N Appleton St" } + city { "Appleton" } + state_code { "WI" } + sequence(:slug) { |i| "event-of-wonders-#{i}" } + nonprofit { association :nonprofit_base } profile end end diff --git a/spec/factories/nonprofits.rb b/spec/factories/nonprofits.rb index 10d17b7c44..752e7f5472 100644 --- a/spec/factories/nonprofits.rb +++ b/spec/factories/nonprofits.rb @@ -3,39 +3,39 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :nm_justice, class: 'Nonprofit' do + factory :nm_justice, class: "Nonprofit" do id { 55352 } - name { 'New Mexico Justice' } - city { 'Albuquerque' } - state_code { 'NM' } + name { "New Mexico Justice" } + city { "Albuquerque" } + state_code { "NM" } zip_code { 55_555 } - email { 'nmj@gmail.com' } - slug { 'new-mexico-equality' } - state_code_slug { 'nm'} - city_slug { 'albuquerque'} + email { "nmj@gmail.com" } + slug { "new-mexico-equality" } + state_code_slug { "nm" } + city_slug { "albuquerque" } register_np_only { true } end - factory :fv_poverty, class: 'Nonprofit' do + factory :fv_poverty, class: "Nonprofit" do id { 22352 } - name { 'Ending Poverty in the Fox Valley Inc.' } - city { 'Appleton' } - state_code { 'WI' } + name { "Ending Poverty in the Fox Valley Inc." } + city { "Appleton" } + state_code { "WI" } zip_code { 54915 } - email { 'contact@endpovertyinthefoxvalleyinc.org' } - website {'https://endpovertyinthefoxvalleyinc.org'} - slug { 'end-poverty-in-the-fox-valley-inc' } - state_code_slug { 'wi'} - city_slug { 'appleton'} + email { "contact@endpovertyinthefoxvalleyinc.org" } + website { "https://endpovertyinthefoxvalleyinc.org" } + slug { "end-poverty-in-the-fox-valley-inc" } + state_code_slug { "wi" } + city_slug { "appleton" } register_np_only { true } end - factory :nonprofit_base, class: 'Nonprofit' do - name { 'Ending Poverty in the Fox Valley Inc.' } - city { 'Appleton '} - state_code { 'wi'} + factory :nonprofit_base, class: "Nonprofit" do + name { "Ending Poverty in the Fox Valley Inc." } + city { "Appleton " } + state_code { "wi" } sequence(:slug) { |n| "#{n}-end-poverty-in-the-fox-valley-inc" } - state_code_slug { 'wi'} - city_slug { 'appleton'} + state_code_slug { "wi" } + city_slug { "appleton" } end end diff --git a/spec/factories/object_event_hook_configs.rb b/spec/factories/object_event_hook_configs.rb index c0a705edb0..b8e93b9a3a 100644 --- a/spec/factories/object_event_hook_configs.rb +++ b/spec/factories/object_event_hook_configs.rb @@ -3,14 +3,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :open_fn_config, class: ObjectEventHookConfig do + factory :open_fn_config, class: "ObjectEventHookConfig" do webhook_service { :open_fn } configuration do { - webhook_url: 'https://www.openfn.org/inbox/my-inbox-id', - headers: { 'x-api-key': 'my-secret-key' } + webhook_url: "https://www.openfn.org/inbox/my-inbox-id", + headers: {"x-api-key": "my-secret-key"} } end - object_event_types { ['supporter.update'] } + object_event_types { ["supporter.update"] } end end diff --git a/spec/factories/offline_transaction_charges.rb b/spec/factories/offline_transaction_charges.rb index 7a545ad309..bce2e6a0bd 100644 --- a/spec/factories/offline_transaction_charges.rb +++ b/spec/factories/offline_transaction_charges.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :offline_transaction_charge do - payment { create(:payment, gross_amount: 4000, net_amount: 3700, fee_total: 300, date: Time.current) } - end + factory :offline_transaction_charge do + payment { create(:payment, gross_amount: 4000, net_amount: 3700, fee_total: 300, date: Time.current) } + end end diff --git a/spec/factories/offline_transaction_disputes.rb b/spec/factories/offline_transaction_disputes.rb index 068d9ba158..0e3492dde2 100644 --- a/spec/factories/offline_transaction_disputes.rb +++ b/spec/factories/offline_transaction_disputes.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :offline_transaction_dispute do - payment { '' } - end + factory :offline_transaction_dispute do + payment { "" } + end end diff --git a/spec/factories/offline_transaction_refunds.rb b/spec/factories/offline_transaction_refunds.rb index 0df8dc349e..d5a3815f17 100644 --- a/spec/factories/offline_transaction_refunds.rb +++ b/spec/factories/offline_transaction_refunds.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :offline_transaction_refund do - payment { '' } - end + factory :offline_transaction_refund do + payment { "" } + end end diff --git a/spec/factories/offline_transactions.rb b/spec/factories/offline_transactions.rb index e40f69d863..e70ac6de4d 100644 --- a/spec/factories/offline_transactions.rb +++ b/spec/factories/offline_transactions.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :offline_transaction do - amount { 4000 } - end + factory :offline_transaction do + amount { 4000 } + end end diff --git a/spec/factories/payment_imports.rb b/spec/factories/payment_imports.rb index 39cf0df70f..fdb9f1beb6 100644 --- a/spec/factories/payment_imports.rb +++ b/spec/factories/payment_imports.rb @@ -4,7 +4,7 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do factory :payment_import do - user { '' } - nonprofit { '' } + user { "" } + nonprofit { "" } end end diff --git a/spec/factories/recurrences.rb b/spec/factories/recurrences.rb index 854ab3c446..f5a1ba5cd2 100644 --- a/spec/factories/recurrences.rb +++ b/spec/factories/recurrences.rb @@ -3,43 +3,43 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :recurrence do - supporter { association :supporter_with_fv_poverty } - recurring_donation do - association(:rd_with_dedication_designation, - nonprofit: supporter.nonprofit, - supporter: supporter, - donation: association(:donation_with_dedication_designation, nonprofit: supporter.nonprofit, - supporter: supporter)) - end - amount { 500 } + factory :recurrence do + supporter { association :supporter_with_fv_poverty } + recurring_donation do + association(:rd_with_dedication_designation, + nonprofit: supporter.nonprofit, + supporter: supporter, + donation: association(:donation_with_dedication_designation, nonprofit: supporter.nonprofit, + supporter: supporter)) + end + amount { 500 } - factory :recurrence_with_paydate_earlier_in_month do - recurring_donation do - association(:rd_with_dedication_designation, - nonprofit: supporter.nonprofit, - supporter: supporter, - donation: association( - :donation_with_dedication_designation, - nonprofit: supporter.nonprofit, - supporter: supporter - ), - paydate: 3) - end - end + factory :recurrence_with_paydate_earlier_in_month do + recurring_donation do + association(:rd_with_dedication_designation, + nonprofit: supporter.nonprofit, + supporter: supporter, + donation: association( + :donation_with_dedication_designation, + nonprofit: supporter.nonprofit, + supporter: supporter + ), + paydate: 3) + end + end - factory :recurrence_with_paydate_later_in_month do - recurring_donation do - association(:rd_with_dedication_designation, - nonprofit: supporter.nonprofit, - supporter: supporter, - donation: association( - :donation_with_dedication_designation, - nonprofit: supporter.nonprofit, - supporter: supporter - ), - paydate: 5) - end - end - end + factory :recurrence_with_paydate_later_in_month do + recurring_donation do + association(:rd_with_dedication_designation, + nonprofit: supporter.nonprofit, + supporter: supporter, + donation: association( + :donation_with_dedication_designation, + nonprofit: supporter.nonprofit, + supporter: supporter + ), + paydate: 5) + end + end + end end diff --git a/spec/factories/recurring_donations.rb b/spec/factories/recurring_donations.rb index e8a5501ad2..1ae1520be1 100644 --- a/spec/factories/recurring_donations.rb +++ b/spec/factories/recurring_donations.rb @@ -4,11 +4,11 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do factory :recurring_donation do - factory :rd_with_dedication_designation do - nonprofit {association :fv_poverty} - start_date { Time.current} - interval { 1} - time_unit {"month"} + factory :rd_with_dedication_designation do + nonprofit { association :fv_poverty } + start_date { Time.current } + interval { 1 } + time_unit { "month" } end end end diff --git a/spec/factories/roles.rb b/spec/factories/roles.rb index 65ca390ae7..50795f6944 100644 --- a/spec/factories/roles.rb +++ b/spec/factories/roles.rb @@ -5,14 +5,13 @@ FactoryBot.define do factory :role, aliases: [:role_base] do trait :as_nonprofit_admin do - host {association :nonprofit_base} - name { 'nonprofit_admin'} + host { association :nonprofit_base } + name { "nonprofit_admin" } end trait :as_nonprofit_associate do - - host {association :nonprofit_base} - name { 'nonprofit_associate'} + host { association :nonprofit_base } + name { "nonprofit_associate" } end end end diff --git a/spec/factories/stripe_charges.rb b/spec/factories/stripe_charges.rb index 308acfe32d..4fbf634858 100644 --- a/spec/factories/stripe_charges.rb +++ b/spec/factories/stripe_charges.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :stripe_charge do - payment { '' } - end + factory :stripe_charge do + payment { "" } + end end diff --git a/spec/factories/stripe_disputes.rb b/spec/factories/stripe_disputes.rb index 5d96032cca..e7a65599af 100644 --- a/spec/factories/stripe_disputes.rb +++ b/spec/factories/stripe_disputes.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :stripe_dispute do - payment { '' } - end + factory :stripe_dispute do + payment { "" } + end end diff --git a/spec/factories/stripe_refunds.rb b/spec/factories/stripe_refunds.rb index a9fb1d6701..823b0c5bb9 100644 --- a/spec/factories/stripe_refunds.rb +++ b/spec/factories/stripe_refunds.rb @@ -3,7 +3,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :stripe_refund do - payment { '' } - end + factory :stripe_refund do + payment { "" } + end end diff --git a/spec/factories/stripe_transactions.rb b/spec/factories/stripe_transactions.rb index cb2ed22d85..daf6e8d8b4 100644 --- a/spec/factories/stripe_transactions.rb +++ b/spec/factories/stripe_transactions.rb @@ -3,8 +3,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :stripe_transaction do - initial_amount { 1 } - net_amount { 1 } - end + factory :stripe_transaction do + initial_amount { 1 } + net_amount { 1 } + end end diff --git a/spec/factories/subtransaction_payments.rb b/spec/factories/subtransaction_payments.rb index 2f5b94ab2d..5520b4f510 100644 --- a/spec/factories/subtransaction_payments.rb +++ b/spec/factories/subtransaction_payments.rb @@ -3,9 +3,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :subtransaction_payment do - factory :subtransaction_payment_with_offline_charge do - paymentable { create(:offline_transaction_charge) } - end - end + factory :subtransaction_payment do + factory :subtransaction_payment_with_offline_charge do + paymentable { create(:offline_transaction_charge) } + end + end end diff --git a/spec/factories/subtransactions.rb b/spec/factories/subtransactions.rb index 27e9279f96..6e83ebc995 100644 --- a/spec/factories/subtransactions.rb +++ b/spec/factories/subtransactions.rb @@ -3,12 +3,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :subtransaction do - subtransactable { create(:offline_transaction) } - payments do - [ - create(:subtransaction_payment_with_offline_charge) - ] - end - end + factory :subtransaction do + subtransactable { create(:offline_transaction) } + payments do + [ + create(:subtransaction_payment_with_offline_charge) + ] + end + end end diff --git a/spec/factories/supporter_notes.rb b/spec/factories/supporter_notes.rb index 82ff974d03..88a9f237e4 100644 --- a/spec/factories/supporter_notes.rb +++ b/spec/factories/supporter_notes.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true FactoryBot.define do - factory :supporter_note do - factory :supporter_note_with_fv_poverty do - supporter { create(:supporter_with_fv_poverty) } - content { 'Some content in our note' } - factory :supporter_note_with_fv_poverty_with_user do - user { create(:user) } - end - end - end + factory :supporter_note do + factory :supporter_note_with_fv_poverty do + supporter { create(:supporter_with_fv_poverty) } + content { "Some content in our note" } + factory :supporter_note_with_fv_poverty_with_user do + user { create(:user) } + end + end + end end diff --git a/spec/factories/supporters.rb b/spec/factories/supporters.rb index 8678791226..4a6477149f 100644 --- a/spec/factories/supporters.rb +++ b/spec/factories/supporters.rb @@ -4,7 +4,7 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do factory :supporter do - name { 'Fake Supporter Name' } + name { "Fake Supporter Name" } nonprofit_id { 55352 } trait :has_a_card do after(:create) do |supporter| @@ -13,8 +13,8 @@ end end - factory :supporter_with_fv_poverty, class: 'Supporter' do - name { 'Fake Supporter Name' } - nonprofit { association :fv_poverty} + factory :supporter_with_fv_poverty, class: "Supporter" do + name { "Fake Supporter Name" } + nonprofit { association :fv_poverty } end end diff --git a/spec/factories/tag_definitions.rb b/spec/factories/tag_definitions.rb index 17671a8504..b830b2cd48 100644 --- a/spec/factories/tag_definitions.rb +++ b/spec/factories/tag_definitions.rb @@ -3,10 +3,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :tag_definition do - factory :tag_definition_with_nonprofit do - name { 'Tag Name' } - nonprofit { create(:fv_poverty) } - end - end + factory :tag_definition do + factory :tag_definition_with_nonprofit do + name { "Tag Name" } + nonprofit { create(:fv_poverty) } + end + end end diff --git a/spec/factories/ticket_levels.rb b/spec/factories/ticket_levels.rb index ab9b829466..e1e791babe 100644 --- a/spec/factories/ticket_levels.rb +++ b/spec/factories/ticket_levels.rb @@ -8,16 +8,16 @@ end end - factory :ticket_level_with_event, class: 'TicketLevel' do - event { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } - factory :ticket_level_with_event_non_admin__order_3__not_deleted do - name { 'ticket level name' } - description { 'desc ticket' } - amount { 200 } - admin_only { false} - deleted { false} - limit { 2} - order { 3} - end + factory :ticket_level_with_event, class: "TicketLevel" do + event { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } + factory :ticket_level_with_event_non_admin__order_3__not_deleted do + name { "ticket level name" } + description { "desc ticket" } + amount { 200 } + admin_only { false } + deleted { false } + limit { 2 } + order { 3 } + end end end diff --git a/spec/factories/transactions.rb b/spec/factories/transactions.rb index f1c80c6227..e50e48caa4 100644 --- a/spec/factories/transactions.rb +++ b/spec/factories/transactions.rb @@ -3,21 +3,23 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :transaction do - supporter { create(:supporter) } - end + factory :transaction do + supporter { create(:supporter) } + end - factory :transaction_for_donation, class: "Transaction" do + factory :transaction_for_donation, class: "Transaction" do + amount { 4000 } + supporter { create(:supporter_with_fv_poverty) } + subtransaction { + build( + :subtransaction + ) + } - amount { 4000 } - supporter { create(:supporter_with_fv_poverty) } - subtransaction { build( - :subtransaction - )} - - transaction_assignments { [ - build(:transaction_assignment - ) - ]} - end + transaction_assignments { + [ + build(:transaction_assignment) + ] + } + end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 47e2134f80..c27fe15d10 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -3,12 +3,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE FactoryBot.define do - factory :user, aliases: [:user_base] do - sequence(:email) { |i| "user#{i}@example.string.com" } - password { 'whocares' } + factory :user, aliases: [:user_base] do + sequence(:email) { |i| "user#{i}@example.string.com" } + password { "whocares" } - factory :confirmed_user do - confirmed_at { Time.current } - end - end + factory :confirmed_user do + confirmed_at { Time.current } + end + end end diff --git a/spec/legacy_lib/calculate/calculate_fees_spec.rb b/spec/legacy_lib/calculate/calculate_fees_spec.rb index 908f4707dc..7cbbfa95ba 100644 --- a/spec/legacy_lib/calculate/calculate_fees_spec.rb +++ b/spec/legacy_lib/calculate/calculate_fees_spec.rb @@ -2,27 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../../app/legacy_lib/calculate_fees' +require_relative "../../../app/legacy_lib/calculate_fees" describe CalculateFees do - describe '.for_single_amount' do - it 'returns 2.2% + platform fee + 30 cents for an online donation' do + describe ".for_single_amount" do + it "returns 2.2% + platform fee + 30 cents for an online donation" do expect(CalculateFees.for_single_amount(10_000, 0.018)).to eq(430) end - it 'returns 2.2% + + 30 cents for an online donation with no platform fee' do + it "returns 2.2% + + 30 cents for an online donation with no platform fee" do expect(CalculateFees.for_single_amount(10_000)).to eq(250) end - it 'returns 2.2% + platform fee + 30 cents for an online donation with higher platform fee' do + it "returns 2.2% + platform fee + 30 cents for an online donation with higher platform fee" do expect(CalculateFees.for_single_amount(10_000, 0.038)).to eq(630) end - it 'raises an error with a negative amount' do + it "raises an error with a negative amount" do expect { CalculateFees.for_single_amount(-10, 0.01) }.to raise_error(ParamValidation::ValidationError) end - it 'raises an error with a negative fee' do + it "raises an error with a negative fee" do expect { CalculateFees.for_single_amount(1000, -0.01) }.to raise_error(ParamValidation::ValidationError) end end diff --git a/spec/legacy_lib/calculate/calculate_suggested_amounts_spec.rb b/spec/legacy_lib/calculate/calculate_suggested_amounts_spec.rb index 73ba79a571..85c498340e 100644 --- a/spec/legacy_lib/calculate/calculate_suggested_amounts_spec.rb +++ b/spec/legacy_lib/calculate/calculate_suggested_amounts_spec.rb @@ -2,103 +2,103 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../../app/legacy_lib/calculate_suggested_amounts' +require_relative "../../../app/legacy_lib/calculate_suggested_amounts" describe CalculateSuggestedAmounts do - describe '.calculate' do - it 'param validation' do + describe ".calculate" do + it "param validation" do expect { CalculateSuggestedAmounts.calculate(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error, [{ key: :amount, name: :required }, { key: :amount, name: :is_a }, { key: :amount, name: :min }, { key: :amount, name: :max }]) + expect_validation_errors(error, [{key: :amount, name: :required}, {key: :amount, name: :is_a}, {key: :amount, name: :min}, {key: :amount, name: :max}]) end) - expect { CalculateSuggestedAmounts.calculate('fffff') }.to(raise_error do |error| + expect { CalculateSuggestedAmounts.calculate("fffff") }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error, [{ key: :amount, name: :is_a }, { key: :amount, name: :min }, { key: :amount, name: :max }]) + expect_validation_errors(error, [{key: :amount, name: :is_a}, {key: :amount, name: :min}, {key: :amount, name: :max}]) end) end - it '1 gives you 2-4' do + it "1 gives you 2-4" do result = CalculateSuggestedAmounts.calculate(100) expect(result).to eq([200, 300, 400]) end - it '1.25 gives you 1, 2-4' do + it "1.25 gives you 1, 2-4" do result = CalculateSuggestedAmounts.calculate(125) expect(result).to eq([100, 200, 300, 400]) end - it '2 gives you 1, 3-5' do + it "2 gives you 1, 3-5" do result = CalculateSuggestedAmounts.calculate(200) expect(result).to eq([100, 300, 400, 500]) end - it '9 gives you 8, 10, 15,20' do + it "9 gives you 8, 10, 15,20" do result = CalculateSuggestedAmounts.calculate(900) expect(result).to eq([800, 1000, 1500, 2000]) end - it '9.5 gives you 9, 10, 15,20' do + it "9.5 gives you 9, 10, 15,20" do result = CalculateSuggestedAmounts.calculate(950) expect(result).to eq([900, 1000, 1500, 2000]) end - it '10 gives you 9, 15, 20, 25' do + it "10 gives you 9, 15, 20, 25" do result = CalculateSuggestedAmounts.calculate(1000) expect(result).to eq([900, 1500, 2000, 2500]) end - it '11 gives you 10, 15, 20, 25' do + it "11 gives you 10, 15, 20, 25" do result = CalculateSuggestedAmounts.calculate(1100) expect(result).to eq([1000, 1500, 2000, 2500]) end - it '35 gives you 30, 40, 45, 50' do + it "35 gives you 30, 40, 45, 50" do result = CalculateSuggestedAmounts.calculate(3500) expect(result).to eq([3000, 4000, 4500, 5000]) end - it '40 gives you 35, 45, 50, 75' do + it "40 gives you 35, 45, 50, 75" do result = CalculateSuggestedAmounts.calculate(4000) expect(result).to eq([3500, 4500, 5000, 7500]) end - it '43 gives you 40, 45, 50, 75' do + it "43 gives you 40, 45, 50, 75" do result = CalculateSuggestedAmounts.calculate(4300) expect(result).to eq([4000, 4500, 5000, 7500]) end - it '47 gives you 45, 50, 75, 100' do + it "47 gives you 45, 50, 75, 100" do result = CalculateSuggestedAmounts.calculate(4700) expect(result).to eq([4500, 5000, 7500, 10_000]) end - it '47 gives you 45, 50, 75, 100' do + it "47 gives you 45, 50, 75, 100" do result = CalculateSuggestedAmounts.calculate(4700) expect(result).to eq([4500, 5000, 7500, 10_000]) end - it '50 gives you 45, 75, 100, 125' do + it "50 gives you 45, 75, 100, 125" do result = CalculateSuggestedAmounts.calculate(5000) expect(result).to eq([4500, 7500, 10_000, 12_500]) end - it '65 gives you 50, 75, 100, 125' do + it "65 gives you 50, 75, 100, 125" do result = CalculateSuggestedAmounts.calculate(6500) expect(result).to eq([5000, 7500, 10_000, 12_500]) end - it '75 gives you 50, 100, 125, 150' do + it "75 gives you 50, 100, 125, 150" do result = CalculateSuggestedAmounts.calculate(7500) expect(result).to eq([5000, 10_000, 12_500, 15_000]) end - it '999925 gives you 999900, 999950, 999975' do + it "999925 gives you 999900, 999950, 999975" do result = CalculateSuggestedAmounts.calculate(99_992_500) expect(result).to eq([99_990_000, 99_995_000, 99_997_500]) end - it '999950 gives you 999925, 999975' do + it "999950 gives you 999925, 999975" do result = CalculateSuggestedAmounts.calculate(99_995_000) expect(result).to eq([99_992_500, 99_997_500]) end diff --git a/spec/legacy_lib/chunked_uploader_spec.rb b/spec/legacy_lib/chunked_uploader_spec.rb index 5378ad5df7..d48e4c1277 100644 --- a/spec/legacy_lib/chunked_uploader_spec.rb +++ b/spec/legacy_lib/chunked_uploader_spec.rb @@ -2,44 +2,44 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -describe "ChunkedUploader" do - let(:input) { ['something\nexit','anotherbreak\n']} - let(:result) {'something\nexitanotherbreak\n'} - - it 'sends a File to the block' do +describe "ChunkedUploader" do + let(:input) { ['something\nexit', 'anotherbreak\n'] } + let(:result) { 'something\nexitanotherbreak\n' } + + it "sends a File to the block" do ChunkedUploader.upload(input) do |io| - expect(io.class).to eq File + expect(io.class).to eq File end end - it 'it sends the accurate result to the block' do + it "it sends the accurate result to the block" do ChunkedUploader.upload(input) do |io| expect(io.read).to eq result end end - describe 'chunked uploads' do - let(:input) { (['something\nexit','anotherbreak\n'] * 200000).flatten} - let(:result) {'something\nexitanotherbreak\n' * 200000} - let(:key) { "root/middle/child"} - it 'file service uploads 5MB+ file' do + describe "chunked uploads" do + let(:input) { (['something\nexit', 'anotherbreak\n'] * 200000).flatten } + let(:result) { 'something\nexitanotherbreak\n' * 200000 } + let(:key) { "root/middle/child" } + + it "file service uploads 5MB+ file" do ChunkedUploader.upload(input) do |io| ActiveStorage::Blob.service.upload(key, io) end - expect( ActiveStorage::Blob.service.download(key)).to eq result + expect(ActiveStorage::Blob.service.download(key)).to eq result end - describe 's3' do - xit 'uploads 5MB+ file' do + describe "s3" do + xit "uploads 5MB+ file" do s3_test = ActiveStorage::Service.configure(:s3_test, Rails.configuration.active_storage.service_configurations) ChunkedUploader.upload(input) do |io| s3_test.upload(key, io) end - expect( s3_test.download(key)).to eq result + expect(s3_test.download(key)).to eq result end end end - end diff --git a/spec/legacy_lib/construct/construct_nonprofit_spec.rb b/spec/legacy_lib/construct/construct_nonprofit_spec.rb index 8a61de1240..85295a389a 100644 --- a/spec/legacy_lib/construct/construct_nonprofit_spec.rb +++ b/spec/legacy_lib/construct/construct_nonprofit_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe ConstructNonprofit, pending: true do # describe '.construct' do diff --git a/spec/legacy_lib/copy_naming_algorithm_spec.rb b/spec/legacy_lib/copy_naming_algorithm_spec.rb index 3fe85b7b57..e0cd1fa1ff 100644 --- a/spec/legacy_lib/copy_naming_algorithm_spec.rb +++ b/spec/legacy_lib/copy_naming_algorithm_spec.rb @@ -2,27 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe CopyNamingAlgorithm do - describe '.create_copy_name' do - let(:base_name_short) { 'b' } - let(:base_name_short_copy) { 'b_copy-00' } - let(:base_name_short_copy_1) { 'b_copy-01' } - let(:base_name_short_copy_2) { 'b_copy-02' } - - let(:base_name_long) { 'ten digits' } - let(:base_name_long_copy) { 'te_copy-00' } - let(:base_name_long_copy_1) { 'te_copy-01' } - let(:base_name_long_copy_2) { 'te_copy-02' } - - it 'create copy when none exist already' do + describe ".create_copy_name" do + let(:base_name_short) { "b" } + let(:base_name_short_copy) { "b_copy-00" } + let(:base_name_short_copy_1) { "b_copy-01" } + let(:base_name_short_copy_2) { "b_copy-02" } + + let(:base_name_long) { "ten digits" } + let(:base_name_long_copy) { "te_copy-00" } + let(:base_name_long_copy_1) { "te_copy-01" } + let(:base_name_long_copy_2) { "te_copy-02" } + + it "create copy when none exist already" do names = [base_name_short] result = TestCopyNamingAlgorithm.new(name_entities: names).create_copy_name(base_name_short) expect(result).to eq base_name_short_copy end - it 'create copy when one exists already' do + it "create copy when one exists already" do names = [base_name_short, base_name_short_copy] result = TestCopyNamingAlgorithm.new(name_entities: names).create_copy_name(base_name_short) expect(result).to eq base_name_short_copy_1 @@ -31,7 +31,7 @@ expect(result).to eq base_name_short_copy_1 end - it 'create copy when two exist already' do + it "create copy when two exist already" do names = [base_name_short, base_name_short_copy, base_name_short_copy_1] result = TestCopyNamingAlgorithm.new(name_entities: names).create_copy_name(base_name_short) @@ -44,13 +44,13 @@ expect(result).to eq base_name_short_copy_2 end - it 'create copy when none exists - longer' do + it "create copy when none exists - longer" do names = [base_name_long] result = TestCopyNamingAlgorithm.new(name_entities: names).create_copy_name(base_name_long) expect(result).to eq base_name_long_copy end - it 'create copy when one exists - longer' do + it "create copy when one exists - longer" do names = [base_name_long, base_name_long_copy] result = TestCopyNamingAlgorithm.new(name_entities: names).create_copy_name(base_name_long) expect(result).to eq base_name_long_copy_1 @@ -59,7 +59,7 @@ expect(result).to eq base_name_long_copy_1 end - it 'create copy when two exists - longer' do + it "create copy when two exists - longer" do names = [base_name_long, base_name_long_copy, base_name_long_copy_1] result = TestCopyNamingAlgorithm.new(name_entities: names).create_copy_name(base_name_long) expect(result).to eq base_name_long_copy_2 @@ -71,16 +71,16 @@ expect(result).to eq base_name_long_copy_2 end - it 'raises ArgumentError on length limit problem' do - names = ['c'] + it "raises ArgumentError on length limit problem" do + names = ["c"] expect { TestCopyNamingAlgorithm.new(name_entities: names, max_length: 4).create_copy_name(names[0]) }.to(raise_error do |e| expect(e).to be_a ArgumentError expect(e.message).to start_with("It's not possible to generate a name using name_to_copy:") end) end - it 'raises ArgumentError on copy limit problem' do - names = ['c', 'c_copy-0'] + it "raises ArgumentError on copy limit problem" do + names = ["c", "c_copy-0"] expect { TestCopyNamingAlgorithm.new(name_entities: names, max_copies: 1).create_copy_name(names[0]) }.to(raise_error do |e| expect(e).to be_a ArgumentError expect(e.message).to start_with("It's not possible to generate a UNIQUE name using name_to_copy:") @@ -88,14 +88,14 @@ end end - describe '.generate_copy_number' do - it 'adds one digit for copy number if under 10' do + describe ".generate_copy_number" do + it "adds one digit for copy number if under 10" do algo = TestCopyNamingAlgorithm.new(max_copies: 9) (0..9).each do |i| expect(algo.generate_copy_number(i)).to eq i.to_s end end - it 'adds 2 digits for copy number if under 100' do + it "adds 2 digits for copy number if under 100" do algo = TestCopyNamingAlgorithm.new(max_copies: 99) (0..99).each do |i| if i < 10 @@ -106,7 +106,7 @@ end end - it 'adds 3 digits for copy number if under 1000' do + it "adds 3 digits for copy number if under 1000" do algo = TestCopyNamingAlgorithm.new(max_copies: 999) (0..999).each do |i| if i < 10 @@ -130,11 +130,11 @@ def initialize(name_entities: [], max_length: 10, max_copies: 20) end def copy_addition - '_copy' + "_copy" end def separator_before_copy_number - '-' + "-" end attr_reader :max_length diff --git a/spec/legacy_lib/create/create_campaign_gift_spec.rb b/spec/legacy_lib/create/create_campaign_gift_spec.rb index 733efa1659..b7543bd480 100644 --- a/spec/legacy_lib/create/create_campaign_gift_spec.rb +++ b/spec/legacy_lib/create/create_campaign_gift_spec.rb @@ -2,57 +2,58 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe CreateCampaignGift do - describe '.create' do - describe 'param validation' do - let (:donation) { force_create(:donation) } - it 'basic validation' do + describe ".create" do + describe "param validation" do + let(:donation) { force_create(:donation) } + + it "basic validation" do expect { CreateCampaignGift.create({}) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error.data, [{ - key: :campaign_gift_option_id, - name: :required - }, - { - key: :campaign_gift_option_id, - name: :is_integer - }, - { - key: :donation_id, - name: :required - }, - { - key: :donation_id, - name: :is_integer - }]) + key: :campaign_gift_option_id, + name: :required + }, + { + key: :campaign_gift_option_id, + name: :is_integer + }, + { + key: :donation_id, + name: :required + }, + { + key: :donation_id, + name: :is_integer + }]) end) end - it 'validates donation exists' do + it "validates donation exists" do expect { CreateCampaignGift.create(donation_id: 555, campaign_gift_option_id: 5555) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error.data, key: :donation_id) - expect(error.message).to eq '555 is not a valid donation id.' + expect(error.message).to eq "555 is not a valid donation id." end) end - it 'validates campaign gift option exists' do + it "validates campaign gift option exists" do expect { CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: 5555) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error.data, key: :campaign_gift_option_id) - expect(error.message).to eq '5555 is not a valid campaign gift option' + expect(error.message).to eq "5555 is not a valid campaign gift option" end) end - describe 'donation and campaign gift option exist so we validate the details' do + describe "donation and campaign gift option exist so we validate the details" do let(:profile) { force_create(:profile, user: force_create(:user)) } let(:nonprofit) { force_create(:nm_justice) } let(:campaign) { force_create(:campaign, profile: profile, nonprofit: nonprofit) } let(:bad_campaign) { force_create(:campaign, profile: profile, nonprofit: nonprofit) } - it 'rejects adding multiple gift options' do + it "rejects adding multiple gift options" do donation = force_create(:donation) campaign_gift_option = force_create(:campaign_gift_option, campaign: campaign) @@ -64,7 +65,7 @@ } end - it 'rejects adding a gift option when the gift option campaign and donation campaign dont match' do + it "rejects adding a gift option when the gift option campaign and donation campaign dont match" do donation = force_create(:donation, campaign: campaign) campaign_gift_option = force_create(:campaign_gift_option, campaign: bad_campaign) profile @@ -78,78 +79,77 @@ } end - it 'rejects associations when the donation amount is too low' do + it "rejects associations when the donation amount is too low" do donation = force_create(:donation, campaign: campaign, amount: 299) - campaign_gift_option = force_create(:campaign_gift_option, campaign: campaign, amount_one_time: 300, name: 'name') + campaign_gift_option = force_create(:campaign_gift_option, campaign: campaign, amount_one_time: 300, name: "name") expect { expect { CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) }.to raise_error { |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error.data, key: :campaign_gift_option_id) expect(error.message).to eq "#{campaign_gift_option.id} gift options requires a donation of 300 for donation #{donation.id}" } - }.to have_enqueued_job(AdminFailedGiftJob).with(donation,campaign_gift_option) + }.to have_enqueued_job(AdminFailedGiftJob).with(donation, campaign_gift_option) end - it 'rejects associations when the recurring donation amount is too low' do + it "rejects associations when the recurring donation amount is too low" do donation = force_create(:donation, campaign: campaign, amount: 299, recurring: true) - rd = force_create(:recurring_donation, amount: 299, donation: donation) - campaign_gift_option = force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, name: 'name') + force_create(:recurring_donation, amount: 299, donation: donation) + campaign_gift_option = force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, name: "name") expect { expect { CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) }.to raise_error { |error| - expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error.data, key: :campaign_gift_option_id) - expect(error.message).to eq "#{campaign_gift_option.id} gift options requires a recurring donation of 300 for donation #{donation.id}" - } - }.to have_enqueued_job(AdminFailedGiftJob).with(donation,campaign_gift_option) + expect(error).to be_a(ParamValidation::ValidationError) + expect_validation_errors(error.data, key: :campaign_gift_option_id) + expect(error.message).to eq "#{campaign_gift_option.id} gift options requires a recurring donation of 300 for donation #{donation.id}" + } + }.to have_enqueued_job(AdminFailedGiftJob).with(donation, campaign_gift_option) end - it 'rejects association when the there are no gifts available' do - + it "rejects association when the there are no gifts available" do donation = force_create(:donation, campaign: campaign, amount: 300, recurring: true) - rd = force_create(:recurring_donation, amount: 300, donation: donation) + force_create(:recurring_donation, amount: 300, donation: donation) campaign_gift_option = force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, quantity: 1) - campaign_gift = force_create(:campaign_gift, campaign_gift_option: campaign_gift_option) + force_create(:campaign_gift, campaign_gift_option: campaign_gift_option) expect { expect { CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) }.to raise_error { |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error.data, [{ key: :campaign_gift_option_id }]) + expect_validation_errors(error.data, [{key: :campaign_gift_option_id}]) expect(error.message).to eq "#{campaign_gift_option.id} has no more inventory" expect(CampaignGift.count).to eq 1 } - }.to have_enqueued_job(AdminFailedGiftJob).with(donation,campaign_gift_option) + }.to have_enqueued_job(AdminFailedGiftJob).with(donation, campaign_gift_option) end end end - describe 'successful insert' do + describe "successful insert" do let(:profile) { force_create(:profile, user: force_create(:user)) } - let(:nonprofit) {create(:nm_justice)} + let(:nonprofit) { create(:nm_justice) } let(:campaign) { force_create(:campaign, profile: profile, nonprofit: nonprofit) } - describe 'insert with no option quantity limit' do - let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, amount_one_time: 5000) } + describe "insert with no option quantity limit" do + let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, amount_one_time: 5000) } - it 'inserts non_recurring properly' do + it "inserts non_recurring properly" do Timecop.freeze(2020, 4, 5) do donation = force_create(:donation, campaign: campaign, amount: 5000) result = CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) - expected = { donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil }.with_indifferent_access + expected = {donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil}.with_indifferent_access expect(result.attributes).to eq expected expect(CampaignGift.first.attributes).to eq expected expect(Campaign.count).to eq 1 end end - it 'inserts recurring properly' do + it "inserts recurring properly" do Timecop.freeze(2020, 4, 5) do donation = force_create(:donation, campaign: campaign, amount: 300) - rd = force_create(:recurring_donation, amount: 300, donation: donation) + force_create(:recurring_donation, amount: 300, donation: donation) result = CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) - expected = { donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil }.with_indifferent_access + expected = {donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil}.with_indifferent_access expect(result.attributes).to eq expected expect(CampaignGift.first.attributes).to eq expected expect(Campaign.count).to eq 1 @@ -157,26 +157,26 @@ end end - describe 'insert when option quantity is 0' do + describe "insert when option quantity is 0" do let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, amount_one_time: 5000, quantity: 0) } - it 'inserts non_recurring properly' do + it "inserts non_recurring properly" do Timecop.freeze(2020, 4, 5) do donation = force_create(:donation, campaign: campaign, amount: 5000) result = CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) - expected = { donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil }.with_indifferent_access + expected = {donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil}.with_indifferent_access expect(result.attributes).to eq expected expect(CampaignGift.first.attributes).to eq expected expect(Campaign.count).to eq 1 end end - it 'inserts recurring properly' do + it "inserts recurring properly" do Timecop.freeze(2020, 4, 5) do donation = force_create(:donation, campaign: campaign, amount: 300) - rd = force_create(:recurring_donation, amount: 300, donation: donation) + force_create(:recurring_donation, amount: 300, donation: donation) result = CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) - expected = { donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil }.with_indifferent_access + expected = {donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil}.with_indifferent_access expect(result.attributes).to eq expected expect(CampaignGift.first.attributes).to eq expected expect(Campaign.count).to eq 1 @@ -184,26 +184,26 @@ end end - describe 'insert when option inventory is less than quantity total' do + describe "insert when option inventory is less than quantity total" do let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, amount_recurring: 300, amount_one_time: 5000, quantity: 1) } - it 'inserts non_recurring properly' do + it "inserts non_recurring properly" do Timecop.freeze(2020, 4, 5) do donation = force_create(:donation, campaign: campaign, amount: 5000) result = CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) - expected = { donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil }.with_indifferent_access + expected = {donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil}.with_indifferent_access expect(result.attributes).to eq expected expect(CampaignGift.first.attributes).to eq expected expect(Campaign.count).to eq 1 end end - it 'inserts recurring properly' do + it "inserts recurring properly" do Timecop.freeze(2020, 4, 5) do donation = force_create(:donation, campaign: campaign, amount: 300) - rd = force_create(:recurring_donation, amount: 300, donation: donation) + force_create(:recurring_donation, amount: 300, donation: donation) result = CreateCampaignGift.create(donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id) - expected = { donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil }.with_indifferent_access + expected = {donation_id: donation.id, campaign_gift_option_id: campaign_gift_option.id, created_at: Time.now, updated_at: Time.now, id: result.id, recurring_donation_id: nil}.with_indifferent_access expect(result.attributes).to eq expected expect(CampaignGift.first.attributes).to eq expected expect(Campaign.count).to eq 1 diff --git a/spec/legacy_lib/create/create_campaign_spec.rb b/spec/legacy_lib/create/create_campaign_spec.rb index fafd741716..60ce12688d 100644 --- a/spec/legacy_lib/create/create_campaign_spec.rb +++ b/spec/legacy_lib/create/create_campaign_spec.rb @@ -2,11 +2,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe CreateCampaign do - it 'is untested' do - pending 'add tests here' + it "is untested" do + pending "add tests here" raise end end diff --git a/spec/legacy_lib/create/create_peer_to_peer_campaign_spec.rb b/spec/legacy_lib/create/create_peer_to_peer_campaign_spec.rb index 601ee0faed..ed8955c20f 100644 --- a/spec/legacy_lib/create/create_peer_to_peer_campaign_spec.rb +++ b/spec/legacy_lib/create/create_peer_to_peer_campaign_spec.rb @@ -2,106 +2,106 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe CreatePeerToPeerCampaign do - describe '.create' do - let!(:profile) { force_create(:profile, user: force_create(:user)) } - let!(:parent_campaign) { force_create(:campaign, name: 'Parent campaign', nonprofit: force_create(:nm_justice)) } - - context 'when successful' do - around do |example| - Timecop.freeze(2020, 4, 5) do - example.run - end - end - - it 'returns a campaign' do - campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, - goal_amount_dollars: '1000' } - - result = described_class.create(campaign_params, profile.id) - - expect(result).to be_a Campaign - end - - describe 'returns created peer-to-peer campaign' do - subject { described_class.create(campaign_params, profile.id) } - - let(:campaign_params) do - { name: 'Child campaign', parent_campaign_id: parent_campaign.id, - goal_amount_dollars: '1000' } - end - - it { is_expected.to be_a(Campaign) } - - it { - is_expected.to have_attributes( - errors: be_empty, - parent_campaign: parent_campaign, - created_at: Time.current - ) - } - end - - describe 'assigns proper slug' do - subject { described_class.create(campaign_params, profile.id) } - - let(:campaign_params) do - { name: 'Child campaign', parent_campaign_id: parent_campaign.id, - goal_amount_dollars: '1000' } - end - - it { - is_expected.to have_attributes( - errors: be_empty, - slug: 'child-campaign_000' - ) - } - end - - it 'saves campaign' do - campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, - goal_amount_dollars: '1000' } - expect { described_class.create(campaign_params, profile.id) }.to change(Campaign, :count).by 1 - end - end - - context 'when on failure' do - it "returns an error if parent campaign can't be found" do - campaign_params = {} - expect do - described_class.create(campaign_params, profile.id) - end.to raise_error(ActiveRecord::RecordNotFound) - end - - it 'returns a list of error messages for attribute validation' do # rubocop:disable RSpec/MultipleExpectations - campaign_params = { parent_campaign_id: parent_campaign.id } - expect { described_class.create(campaign_params, profile.id) }.to( - raise_error do |error| - expect(error).to be_an_instance_of(ActiveRecord::RecordInvalid) - expect(error.record).to be_a Campaign - expect(error.record.errors.empty?).to be false - expect(error.record.errors['goal_amount']).to match [ - "can't be blank", 'is not a number' - ] - end - ) - end - - RSpec::Matchers.define_negated_matcher :not_change, :change - - it "doesn't save campaign" do - campaign_params = {} - Timecop.freeze(2020, 4, 5) do - expect do - described_class.create( - campaign_params, - profile.id - ) - end.to raise_error(ActiveRecord::RecordNotFound).and not_change(Campaign, :count) - end - end - end - end + describe ".create" do + let!(:profile) { force_create(:profile, user: force_create(:user)) } + let!(:parent_campaign) { force_create(:campaign, name: "Parent campaign", nonprofit: force_create(:nm_justice)) } + + context "when successful" do + around do |example| + Timecop.freeze(2020, 4, 5) do + example.run + end + end + + it "returns a campaign" do + campaign_params = {name: "Child campaign", parent_campaign_id: parent_campaign.id, + goal_amount_dollars: "1000"} + + result = described_class.create(campaign_params, profile.id) + + expect(result).to be_a Campaign + end + + describe "returns created peer-to-peer campaign" do + subject { described_class.create(campaign_params, profile.id) } + + let(:campaign_params) do + {name: "Child campaign", parent_campaign_id: parent_campaign.id, + goal_amount_dollars: "1000"} + end + + it { is_expected.to be_a(Campaign) } + + it { + is_expected.to have_attributes( + errors: be_empty, + parent_campaign: parent_campaign, + created_at: Time.current + ) + } + end + + describe "assigns proper slug" do + subject { described_class.create(campaign_params, profile.id) } + + let(:campaign_params) do + {name: "Child campaign", parent_campaign_id: parent_campaign.id, + goal_amount_dollars: "1000"} + end + + it { + is_expected.to have_attributes( + errors: be_empty, + slug: "child-campaign_000" + ) + } + end + + it "saves campaign" do + campaign_params = {name: "Child campaign", parent_campaign_id: parent_campaign.id, + goal_amount_dollars: "1000"} + expect { described_class.create(campaign_params, profile.id) }.to change(Campaign, :count).by 1 + end + end + + context "when on failure" do + it "returns an error if parent campaign can't be found" do + campaign_params = {} + expect do + described_class.create(campaign_params, profile.id) + end.to raise_error(ActiveRecord::RecordNotFound) + end + + it "returns a list of error messages for attribute validation" do # rubocop:disable RSpec/MultipleExpectations + campaign_params = {parent_campaign_id: parent_campaign.id} + expect { described_class.create(campaign_params, profile.id) }.to( + raise_error do |error| + expect(error).to be_an_instance_of(ActiveRecord::RecordInvalid) + expect(error.record).to be_a Campaign + expect(error.record.errors.empty?).to be false + expect(error.record.errors["goal_amount"]).to match [ + "can't be blank", "is not a number" + ] + end + ) + end + + RSpec::Matchers.define_negated_matcher :not_change, :change + + it "doesn't save campaign" do + campaign_params = {} + Timecop.freeze(2020, 4, 5) do + expect do + described_class.create( + campaign_params, + profile.id + ) + end.to raise_error(ActiveRecord::RecordNotFound).and not_change(Campaign, :count) + end + end + end + end end diff --git a/spec/legacy_lib/delete/delete_campaign_gift_option_spec.rb b/spec/legacy_lib/delete/delete_campaign_gift_option_spec.rb index 05c2e4b380..8f314c291d 100644 --- a/spec/legacy_lib/delete/delete_campaign_gift_option_spec.rb +++ b/spec/legacy_lib/delete/delete_campaign_gift_option_spec.rb @@ -2,29 +2,29 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe DeleteCampaignGiftOption do - describe '.delete' do - let(:nonprofit) { create(:nm_justice)} + describe ".delete" do + let(:nonprofit) { create(:nm_justice) } let(:profile) { force_create(:profile, user: force_create(:user)) } - let(:campaign) { force_create(:campaign, profile: profile, nonprofit:nonprofit) } + let(:campaign) { force_create(:campaign, profile: profile, nonprofit: nonprofit) } let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign) } let(:campaign_gift) { force_create(:campaign_gift, campaign_gift_option: campaign_gift_option) } - it 'cgo deletion is rejected because a gift has already been sold' do + it "cgo deletion is rejected because a gift has already been sold" do campaign_gift_option campaign_gift expect { DeleteCampaignGiftOption.delete(campaign_gift_option) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :campaign_gift_option_id }]) + expect_validation_errors(error.data, [{key: :campaign_gift_option_id}]) expect(error.message).to eq("#{campaign_gift_option.id} already has campaign gifts. It can't be deleted for safety reasons.") expect(CampaignGiftOption.any?).to eq true end) end - it 'cgo deletion succeeds' do + it "cgo deletion succeeds" do Timecop.freeze(2020, 10, 12) do campaign_gift_option result = DeleteCampaignGiftOption.delete(campaign_gift_option) diff --git a/spec/legacy_lib/export/export_payments_spec.rb b/spec/legacy_lib/export/export_payments_spec.rb index cf7b94db8c..e3325d5022 100644 --- a/spec/legacy_lib/export/export_payments_spec.rb +++ b/spec/legacy_lib/export/export_payments_spec.rb @@ -2,47 +2,48 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'support/test_upload_service' +require "rails_helper" +require "support/test_upload_service" describe ExportPayments do - before(:each) do - stub_const('CHUNKED_UPLOAD_SERVICE', TestUploadService.new) + before do + stub_const("CHUNKED_UPLOAD_SERVICE", TestUploadService.new) end - let(:email) { 'example@example.com' } + let(:email) { "example@example.com" } let(:user) { force_create(:user, email: email) } let(:nonprofit) { force_create(:nm_justice) } let(:supporters) do - [force_create(:supporter, name: 'supporter-0', nonprofit: nonprofit), - force_create(:supporter, name: 'supporter-1', nonprofit: nonprofit)] + [force_create(:supporter, name: "supporter-0", nonprofit: nonprofit), + force_create(:supporter, name: "supporter-1", nonprofit: nonprofit)] end let(:payments) do [force_create(:payment, gross_amount: 1000, fee_total: 99, net_amount: 901, supporter: supporters[0], nonprofit: nonprofit), - force_create(:payment, gross_amount: 2000, fee_total: 22, net_amount: 1978, supporter: supporters[1], nonprofit: nonprofit)] + force_create(:payment, gross_amount: 2000, fee_total: 22, net_amount: 1978, supporter: supporters[1], nonprofit: nonprofit)] end - let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/payments-04-06-2020--01-02-03-#{UUID::Regex}\.csv/} + let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/payments-04-06-2020--01-02-03-#{UUID::Regex}\.csv/o } - before(:each) do + before do payments end - context '.initiate_export' do - context 'param verification' do - it 'performs initial verification' do + + context ".initiate_export" do + context "param verification" do + it "performs initial verification" do expect { ExportPayments.initiate_export(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect(error.data.length).to eq(6) - expect_validation_errors(error.data, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_hash }]) + expect_validation_errors(error.data, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_hash}]) end) end - it 'nonprofit doesnt exist' do + it "nonprofit doesnt exist" do fake_npo = 8_888_881 expect { ExportPayments.initiate_export(fake_npo, {}, 8_888_883) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -50,7 +51,7 @@ end) end - it 'user doesnt exist' do + it "user doesnt exist" do fake_user = 8_888_883 expect { ExportPayments.initiate_export(nonprofit.id, {}, fake_user) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -59,73 +60,74 @@ end end - it 'creates an export object and schedules job' do + it "creates an export object and schedules job" do Timecop.freeze(2020, 4, 5) do - params = { param1: 'pp' }.with_indifferent_access - expect{ + params = {param1: "pp"}.with_indifferent_access + expect { ExportPayments.initiate_export(nonprofit.id, params, user.id) }.to have_enqueued_job(PaymentExportCreateJob) - + export = Export.first - expected_export = { id: export.id, - user_id: user.id, - nonprofit_id: nonprofit.id, - status: 'queued', - export_type: 'ExportPayments', - parameters: params.to_json, - updated_at: Time.now, - created_at: Time.now, - url: nil, - ended: nil, - exception: nil }.with_indifferent_access + expected_export = {id: export.id, + user_id: user.id, + nonprofit_id: nonprofit.id, + status: "queued", + export_type: "ExportPayments", + parameters: params.to_json, + updated_at: Time.now, + created_at: Time.now, + url: nil, + ended: nil, + exception: nil}.with_indifferent_access expect(export.attributes).to eq(expected_export) end end end - context '.run_export' do - context 'param validation' do - it 'rejects basic invalid data' do + + context ".run_export" do + context "param validation" do + it "rejects basic invalid data" do expect { ExportPayments.run_export(nil, nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_json }, - { key: 'export_id', name: :required }, - { key: 'export_id', name: :is_integer }]) + expect_validation_errors(error, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_json}, + {key: "export_id", name: :required}, + {key: "export_id", name: :is_integer}]) end) end - it 'rejects json which isnt a hash' do - expect { ExportPayments.run_export(1, [{ item: '' }, { item: '' }].to_json, 1, 1) }.to(raise_error do |error| + it "rejects json which isnt a hash" do + expect { ExportPayments.run_export(1, [{item: ""}, {item: ""}].to_json, 1, 1) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error, [ - { key: :params, name: :is_hash } - ]) + {key: :params, name: :is_hash} + ]) end) end - it 'no export throw an exception' do - expect { ExportPayments.run_export(0, { x: 1 }.to_json, 0, 11_111) }.to(raise_error do |error| + it "no export throw an exception" do + expect { ExportPayments.run_export(0, {x: 1}.to_json, 0, 11_111) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :export_id - expect(error.message).to start_with('Export') + expect(error.message).to start_with("Export") end) end - it 'no nonprofit' do + it "no nonprofit" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: user) Timecop.freeze(2020, 4, 6) do - expect { ExportPayments.run_export(0, { x: 1 }.to_json, user.id, @export.id) }.to(raise_error do |error| + expect { ExportPayments.run_export(0, {x: 1}.to_json, user.id, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :npo_id - expect(error.message).to start_with('Nonprofit') + expect(error.message).to start_with("Nonprofit") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -136,17 +138,17 @@ end end - it 'no user' do + it "no user" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: user) Timecop.freeze(2020, 4, 6) do - expect { ExportPayments.run_export(nonprofit.id, { x: 1 }.to_json, 0, @export.id) }.to(raise_error do |error| + expect { ExportPayments.run_export(nonprofit.id, {x: 1}.to_json, 0, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :user_id - expect(error.message).to start_with('User') + expect(error.message).to start_with("User") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -156,7 +158,7 @@ end end - it 'handles exception in upload properly' do + it "handles exception in upload properly" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: user) CHUNKED_UPLOAD_SERVICE.raise_error @@ -166,7 +168,7 @@ expect(error.message).to eq TestUploadService::TEST_ERROR_MESSAGE @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -176,7 +178,7 @@ end end - it 'uploads as expected' do + it "uploads as expected" do Timecop.freeze(2020, 4, 5) do @export = create(:export, user: user, created_at: Time.now, updated_at: Time.now) Timecop.freeze(2020, 4, 6, 1, 2, 3) do @@ -185,7 +187,7 @@ @export.reload expect(@export.url).to match export_url_regex - expect(@export.status).to eq 'completed' + expect(@export.status).to eq "completed" expect(@export.exception).to be_nil expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -194,8 +196,8 @@ expect(csv[0]).to eq MockHelpers.payment_export_headers - expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq 'text/csv' - expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq 'attachment' + expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq "text/csv" + expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq "attachment" end end end diff --git a/spec/legacy_lib/export/export_recurring_donations_spec.rb b/spec/legacy_lib/export/export_recurring_donations_spec.rb index 04ab3feadf..621835b9fe 100644 --- a/spec/legacy_lib/export/export_recurring_donations_spec.rb +++ b/spec/legacy_lib/export/export_recurring_donations_spec.rb @@ -2,42 +2,42 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'support/test_upload_service' +require "rails_helper" +require "support/test_upload_service" describe ExportRecurringDonations do - before(:each) do - stub_const('CHUNKED_UPLOAD_SERVICE', TestUploadService.new) - @email = 'example@example.com' + before do + stub_const("CHUNKED_UPLOAD_SERVICE", TestUploadService.new) + @email = "example@example.com" @user = force_create(:user, email: @email) @nonprofit = force_create(:nm_justice) - @supporters = [force_create(:supporter, name: 'supporter-0', nonprofit: @nonprofit), - force_create(:supporter, name: 'supporter-1', nonprofit: @nonprofit)] + @supporters = [force_create(:supporter, name: "supporter-0", nonprofit: @nonprofit), + force_create(:supporter, name: "supporter-1", nonprofit: @nonprofit)] @donations = [force_create(:donation, nonprofit: @nonprofit, supporter: @supporters[0]), - force_create(:donation, nonprofit: @nonprofit, supporter: @supporters[1])] - @recurring_donations = [force_create(:recurring_donation, donation: @donations[0], nonprofit: @nonprofit, edit_token: 'edit_token_1', active: true), - force_create(:recurring_donation, donation: @donations[1], supporter: @supporters[1], nonprofit: @nonprofit, edit_token: 'edit_token_2', active: true)] + force_create(:donation, nonprofit: @nonprofit, supporter: @supporters[1])] + @recurring_donations = [force_create(:recurring_donation, donation: @donations[0], nonprofit: @nonprofit, edit_token: "edit_token_1", active: true), + force_create(:recurring_donation, donation: @donations[1], supporter: @supporters[1], nonprofit: @nonprofit, edit_token: "edit_token_2", active: true)] CHUNKED_UPLOAD_SERVICE.clear end - let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/recurring_donations-04-06-2020--01-02-03-#{UUID::Regex}\.csv/} - - context '.initiate_export' do - context 'param verification' do - it 'performs initial verification' do + let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/recurring_donations-04-06-2020--01-02-03-#{UUID::Regex}\.csv/o } + + context ".initiate_export" do + context "param verification" do + it "performs initial verification" do expect { ExportRecurringDonations.initiate_export(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect(error.data.length).to eq(6) - expect_validation_errors(error.data, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_hash }]) + expect_validation_errors(error.data, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_hash}]) end) end - it 'nonprofit doesnt exist' do + it "nonprofit doesnt exist" do fake_npo = 8_888_881 expect { ExportRecurringDonations.initiate_export(fake_npo, {}, 8_888_883) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -45,7 +45,7 @@ end) end - it 'user doesnt exist' do + it "user doesnt exist" do fake_user = 8_888_883 expect { ExportRecurringDonations.initiate_export(@nonprofit.id, {}, fake_user) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -54,73 +54,74 @@ end end - it 'creates an export object and schedules job' do + it "creates an export object and schedules job" do Timecop.freeze(2020, 4, 5) do - params = { param1: 'pp', root_url: 'https://localhost:8080' }.with_indifferent_access + params = {param1: "pp", root_url: "https://localhost:8080"}.with_indifferent_access expect { - ExportRecurringDonations.initiate_export(@nonprofit.id, params, @user.id) + ExportRecurringDonations.initiate_export(@nonprofit.id, params, @user.id) }.to have_enqueued_job(RecurringDonationsExportCreateJob) export = Export.first - expected_export = { id: export.id, - user_id: @user.id, - nonprofit_id: @nonprofit.id, - status: 'queued', - export_type: 'ExportRecurringDonations', - parameters: params.to_json, - updated_at: Time.now, - created_at: Time.now, - url: nil, - ended: nil, - exception: nil }.with_indifferent_access + expected_export = {id: export.id, + user_id: @user.id, + nonprofit_id: @nonprofit.id, + status: "queued", + export_type: "ExportRecurringDonations", + parameters: params.to_json, + updated_at: Time.now, + created_at: Time.now, + url: nil, + ended: nil, + exception: nil}.with_indifferent_access expect(export.attributes).to eq(expected_export) end end end - context '.run_export' do - context 'param validation' do - it 'rejects basic invalid data' do + + context ".run_export" do + context "param validation" do + it "rejects basic invalid data" do expect { ExportRecurringDonations.run_export(nil, nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_json }, - { key: 'export_id', name: :required }, - { key: 'export_id', name: :is_integer }]) + expect_validation_errors(error, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_json}, + {key: "export_id", name: :required}, + {key: "export_id", name: :is_integer}]) end) end - it 'rejects json which isnt a hash' do - expect { ExportRecurringDonations.run_export(1, [{ item: '' }, { item: '' }].to_json, 1, 1) }.to(raise_error do |error| + it "rejects json which isnt a hash" do + expect { ExportRecurringDonations.run_export(1, [{item: ""}, {item: ""}].to_json, 1, 1) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error, [ - { key: :params, name: :is_hash } - ]) + {key: :params, name: :is_hash} + ]) end) end - it 'no export throw an exception' do - expect { ExportRecurringDonations.run_export(0, { x: 1 }.to_json, 0, 11_111) }.to(raise_error do |error| + it "no export throw an exception" do + expect { ExportRecurringDonations.run_export(0, {x: 1}.to_json, 0, 11_111) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :export_id - expect(error.message).to start_with('Export') + expect(error.message).to start_with("Export") end) end - it 'no nonprofit' do + it "no nonprofit" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: @user) Timecop.freeze(2020, 4, 6) do - expect { ExportRecurringDonations.run_export(0, { x: 1 }.to_json, @user.id, @export.id) }.to(raise_error do |error| + expect { ExportRecurringDonations.run_export(0, {x: 1}.to_json, @user.id, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :npo_id - expect(error.message).to start_with('Nonprofit') + expect(error.message).to start_with("Nonprofit") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -129,17 +130,17 @@ end end - it 'no user' do + it "no user" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: @user) Timecop.freeze(2020, 4, 6) do - expect { ExportRecurringDonations.run_export(@nonprofit.id, { x: 1 }.to_json, 0, @export.id) }.to(raise_error do |error| + expect { ExportRecurringDonations.run_export(@nonprofit.id, {x: 1}.to_json, 0, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :user_id - expect(error.message).to start_with('User') + expect(error.message).to start_with("User") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -149,7 +150,7 @@ end end - it 'handles exception in upload properly' do + it "handles exception in upload properly" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: @user) CHUNKED_UPLOAD_SERVICE.raise_error @@ -159,7 +160,7 @@ expect(error.message).to eq TestUploadService::TEST_ERROR_MESSAGE @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -170,16 +171,16 @@ end end - it 'uploads as expected' do + it "uploads as expected" do Timecop.freeze(2020, 4, 5) do @export = create(:export, user: @user, created_at: Time.now, updated_at: Time.now) Timecop.freeze(2020, 4, 6, 1, 2, 3) do - ExportRecurringDonations.run_export(@nonprofit.id, { root_url: 'https://localhost:8080/' }.to_json, @user.id, @export.id) + ExportRecurringDonations.run_export(@nonprofit.id, {root_url: "https://localhost:8080/"}.to_json, @user.id, @export.id) expect(ExportRecurringDonationsCompletedJob).to have_been_enqueued.with(@export) @export.reload expect(@export.url).to match export_url_regex - expect(@export.status).to eq 'completed' + expect(@export.status).to eq "completed" expect(@export.exception).to be_nil expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -188,8 +189,8 @@ expect(csv[0]).to eq MockHelpers.recurring_donation_export_headers - expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq 'text/csv' - expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq 'attachment' + expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq "text/csv" + expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq "attachment" end end end diff --git a/spec/legacy_lib/export/export_supporter_notes_spec.rb b/spec/legacy_lib/export/export_supporter_notes_spec.rb index df94e686d3..1ded961881 100644 --- a/spec/legacy_lib/export/export_supporter_notes_spec.rb +++ b/spec/legacy_lib/export/export_supporter_notes_spec.rb @@ -2,12 +2,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'support/test_upload_service' +require "rails_helper" +require "support/test_upload_service" describe ExportSupporterNotes do - before(:each) do - stub_const('CHUNKED_UPLOAD_SERVICE', TestUploadService.new) + before do + stub_const("CHUNKED_UPLOAD_SERVICE", TestUploadService.new) supporter_note_for_s1 supporter_note_1_for_s2 supporter_note_2_for_s2 @@ -19,20 +19,20 @@ let(:supporter2) { force_create(:supporter, nonprofit: nonprofit) } let(:user) { force_create(:user, email: email) } - let(:email) { 'example@example.com' } + let(:email) { "example@example.com" } - let(:export_header) { ['Id', 'Email', 'Note Created At', 'Note Contents'] } + let(:export_header) { ["Id", "Email", "Note Created At", "Note Contents"] } let(:note_content_1) do - 'CONTENT1' + "CONTENT1" end let(:note_content_2) do - 'CONTENT2' + "CONTENT2" end let(:note_content_3) do - 'CONTENT3' + "CONTENT3" end let(:supporter_note_for_s1) do @@ -47,24 +47,24 @@ force_create(:supporter_note, supporter: supporter2, created_at: DateTime.new(2020, 4, 5), content: note_content_3) end - let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/supporters-notes-04-06-2020--01-02-03-#{UUID::Regex}\.csv/} + let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/supporters-notes-04-06-2020--01-02-03-#{UUID::Regex}\.csv/o } - context '.initiate_export' do - context 'param verification' do - it 'performs initial verification' do + context ".initiate_export" do + context "param verification" do + it "performs initial verification" do expect { ExportSupporterNotes.initiate_export(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect(error.data.length).to eq(6) - expect_validation_errors(error.data, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_hash }]) + expect_validation_errors(error.data, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_hash}]) end) end - it 'nonprofit doesnt exist' do + it "nonprofit doesnt exist" do fake_npo = 8_888_881 expect { ExportSupporterNotes.initiate_export(fake_npo, {}, 8_888_883) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -72,7 +72,7 @@ end) end - it 'user doesnt exist' do + it "user doesnt exist" do fake_user = 8_888_883 expect { ExportSupporterNotes.initiate_export(nonprofit.id, {}, fake_user) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -81,75 +81,74 @@ end end - it 'creates an export object and schedules job' do + it "creates an export object and schedules job" do Timecop.freeze(2020, 4, 5) do - - params = { param1: 'pp', root_url: 'https://localhost:8080' }.with_indifferent_access + params = {param1: "pp", root_url: "https://localhost:8080"}.with_indifferent_access - expect{ + expect { ExportSupporterNotes.initiate_export(nonprofit.id, params, user.id) }.to have_enqueued_job(SupporterNotesExportCreateJob) export = Export.first - expected_export = { id: export.id, - user_id: user.id, - nonprofit_id: nonprofit.id, - status: 'queued', - export_type: 'ExportSupporterNotes', - parameters: params.to_json, - updated_at: Time.now, - created_at: Time.now, - url: nil, - ended: nil, - exception: nil }.with_indifferent_access + expected_export = {id: export.id, + user_id: user.id, + nonprofit_id: nonprofit.id, + status: "queued", + export_type: "ExportSupporterNotes", + parameters: params.to_json, + updated_at: Time.now, + created_at: Time.now, + url: nil, + ended: nil, + exception: nil}.with_indifferent_access expect(export.attributes).to eq(expected_export) end end end - context '.run_export' do - context 'param validation' do - it 'rejects basic invalid data' do + context ".run_export" do + context "param validation" do + it "rejects basic invalid data" do expect { ExportSupporterNotes.run_export(nil, nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_json }, - { key: 'export_id', name: :required }, - { key: 'export_id', name: :is_integer }]) + expect_validation_errors(error, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_json}, + {key: "export_id", name: :required}, + {key: "export_id", name: :is_integer}]) end) end - it 'rejects json which isnt a hash' do - expect { ExportSupporterNotes.run_export(1, [{ item: '' }, { item: '' }].to_json, 1, 1) }.to(raise_error do |error| + it "rejects json which isnt a hash" do + expect { ExportSupporterNotes.run_export(1, [{item: ""}, {item: ""}].to_json, 1, 1) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error, [ - { key: :params, name: :is_hash } - ]) + {key: :params, name: :is_hash} + ]) end) end - it 'no export throw an exception' do - expect { ExportSupporterNotes.run_export(0, { x: 1 }.to_json, 0, 11_111) }.to(raise_error do |error| + it "no export throw an exception" do + expect { ExportSupporterNotes.run_export(0, {x: 1}.to_json, 0, 11_111) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :export_id - expect(error.message).to start_with('Export') + expect(error.message).to start_with("Export") end) end - it 'no nonprofit' do + it "no nonprofit" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: user) Timecop.freeze(2020, 4, 6) do - expect { ExportSupporterNotes.run_export(0, { x: 1 }.to_json, user.id, @export.id) }.to(raise_error do |error| + expect { ExportSupporterNotes.run_export(0, {x: 1}.to_json, user.id, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :npo_id - expect(error.message).to start_with('Nonprofit') + expect(error.message).to start_with("Nonprofit") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -158,17 +157,17 @@ end end - it 'no user' do + it "no user" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: user) Timecop.freeze(2020, 4, 6) do - expect { ExportSupporterNotes.run_export(nonprofit.id, { x: 1 }.to_json, 0, @export.id) }.to(raise_error do |error| + expect { ExportSupporterNotes.run_export(nonprofit.id, {x: 1}.to_json, 0, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :user_id - expect(error.message).to start_with('User') + expect(error.message).to start_with("User") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -178,39 +177,39 @@ end end - it 'handles exception in upload properly' do + it "handles exception in upload properly" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: user) CHUNKED_UPLOAD_SERVICE.raise_error Timecop.freeze(2020, 4, 6) do expect { - expect { ExportSupporterNotes.run_export(nonprofit.id, {}.to_json, user.id, @export.id) }.to(raise_error do |error| - expect(error).to be_a StandardError - expect(error.message).to eq TestUploadService::TEST_ERROR_MESSAGE - - @export.reload - expect(@export.status).to eq 'failed' - expect(@export.exception).to eq error.to_s - expect(@export.ended).to eq Time.now - expect(@export.updated_at).to eq Time.now - end) - }.to have_enqueued_job(ExportSupporterNotesFailedJob).with(@export) + expect { ExportSupporterNotes.run_export(nonprofit.id, {}.to_json, user.id, @export.id) }.to(raise_error do |error| + expect(error).to be_a StandardError + expect(error.message).to eq TestUploadService::TEST_ERROR_MESSAGE + + @export.reload + expect(@export.status).to eq "failed" + expect(@export.exception).to eq error.to_s + expect(@export.ended).to eq Time.now + expect(@export.updated_at).to eq Time.now + end) + }.to have_enqueued_job(ExportSupporterNotesFailedJob).with(@export) end end end - it 'uploads as expected' do + it "uploads as expected" do Timecop.freeze(2020, 4, 5) do @export = create(:export, user: user, created_at: Time.now, updated_at: Time.now) Timecop.freeze(2020, 4, 6, 1, 2, 3) do expect { - ExportSupporterNotes.run_export(nonprofit.id, { root_url: 'https://localhost:8080/' }.to_json, user.id, @export.id) + ExportSupporterNotes.run_export(nonprofit.id, {root_url: "https://localhost:8080/"}.to_json, user.id, @export.id) }.to have_enqueued_job(ExportSupporterNotesCompletedJob).with(@export) @export.reload expect(@export.url).to match export_url_regex - expect(@export.status).to eq 'completed' + expect(@export.status).to eq "completed" expect(@export.exception).to be_nil expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -219,8 +218,8 @@ expect(csv[0]).to eq export_header - expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq 'text/csv' - expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq 'attachment' + expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq "text/csv" + expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq "attachment" end end end diff --git a/spec/legacy_lib/export/export_supporters_spec.rb b/spec/legacy_lib/export/export_supporters_spec.rb index abd0e06d8c..fc626caf99 100644 --- a/spec/legacy_lib/export/export_supporters_spec.rb +++ b/spec/legacy_lib/export/export_supporters_spec.rb @@ -2,36 +2,37 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'support/test_upload_service' +require "rails_helper" +require "support/test_upload_service" describe ExportSupporters do - before(:each) do - stub_const('CHUNKED_UPLOAD_SERVICE', TestUploadService.new) + before do + stub_const("CHUNKED_UPLOAD_SERVICE", TestUploadService.new) @nonprofit = force_create(:nm_justice) - @email = 'example@example.com' + @email = "example@example.com" @user = force_create(:user, email: @email) @supporters = 2.times { force_create(:supporter, nonprofit: @nonprofit) } end - let(:export_header) { 'Last Name,First Name,Full Name,Organization,Email,Phone,Address,City,State,Postal Code,Country,Anonymous?,Supporter Id,Total Contributed,Id,Last Payment Received,Notes,Tags'.split(',') } - let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/supporters-04-06-2020--01-02-03-#{UUID::Regex}\.csv/} - context '.initiate_export' do - context 'param verification' do - it 'performs initial verification' do + let(:export_header) { "Last Name,First Name,Full Name,Organization,Email,Phone,Address,City,State,Postal Code,Country,Anonymous?,Supporter Id,Total Contributed,Id,Last Payment Received,Notes,Tags".split(",") } + let(:export_url_regex) { /http:\/\/fake\.url\/tmp\/csv-exports\/supporters-04-06-2020--01-02-03-#{UUID::Regex}\.csv/o } + + context ".initiate_export" do + context "param verification" do + it "performs initial verification" do expect { ExportSupporters.initiate_export(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect(error.data.length).to eq(6) - expect_validation_errors(error.data, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_hash }]) + expect_validation_errors(error.data, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_hash}]) end) end - it 'nonprofit doesnt exist' do + it "nonprofit doesnt exist" do fake_npo = 8_888_881 expect { ExportSupporters.initiate_export(fake_npo, {}, 8_888_883) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -39,7 +40,7 @@ end) end - it 'user doesnt exist' do + it "user doesnt exist" do fake_user = 8_888_883 expect { ExportSupporters.initiate_export(@nonprofit.id, {}, fake_user) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) @@ -48,73 +49,74 @@ end end - it 'creates an export object and schedules job' do - Timecop.freeze(2020, 4, 5) do - params = { param1: 'pp', root_url: 'https://localhost:8080' }.with_indifferent_access + it "creates an export object and schedules job" do + Timecop.freeze(2020, 4, 5) do + params = {param1: "pp", root_url: "https://localhost:8080"}.with_indifferent_access expect { ExportSupporters.initiate_export(@nonprofit.id, params, @user.id) }.to have_enqueued_job(SupportersExportCreateJob) export = Export.first - expected_export = { id: export.id, - user_id: @user.id, - nonprofit_id: @nonprofit.id, - status: 'queued', - export_type: 'ExportSupporters', - parameters: params.to_json, - updated_at: Time.now, - created_at: Time.now, - url: nil, - ended: nil, - exception: nil }.with_indifferent_access + expected_export = {id: export.id, + user_id: @user.id, + nonprofit_id: @nonprofit.id, + status: "queued", + export_type: "ExportSupporters", + parameters: params.to_json, + updated_at: Time.now, + created_at: Time.now, + url: nil, + ended: nil, + exception: nil}.with_indifferent_access expect(export.attributes).to eq(expected_export) end end end - context '.run_export' do - context 'param validation' do - it 'rejects basic invalid data' do + + context ".run_export" do + context "param validation" do + it "rejects basic invalid data" do expect { ExportSupporters.run_export(nil, nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error, [{ key: 'npo_id', name: :required }, - { key: 'npo_id', name: :is_integer }, - { key: 'user_id', name: :required }, - { key: 'user_id', name: :is_integer }, - { key: 'params', name: :required }, - { key: 'params', name: :is_json }, - { key: 'export_id', name: :required }, - { key: 'export_id', name: :is_integer }]) + expect_validation_errors(error, [{key: "npo_id", name: :required}, + {key: "npo_id", name: :is_integer}, + {key: "user_id", name: :required}, + {key: "user_id", name: :is_integer}, + {key: "params", name: :required}, + {key: "params", name: :is_json}, + {key: "export_id", name: :required}, + {key: "export_id", name: :is_integer}]) end) end - it 'rejects json which isnt a hash' do - expect { ExportSupporters.run_export(1, [{ item: '' }, { item: '' }].to_json, 1, 1) }.to(raise_error do |error| + it "rejects json which isnt a hash" do + expect { ExportSupporters.run_export(1, [{item: ""}, {item: ""}].to_json, 1, 1) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) expect_validation_errors(error, [ - { key: :params, name: :is_hash } - ]) + {key: :params, name: :is_hash} + ]) end) end - it 'no export throw an exception' do - expect { ExportSupporters.run_export(0, { x: 1 }.to_json, 0, 11_111) }.to(raise_error do |error| + it "no export throw an exception" do + expect { ExportSupporters.run_export(0, {x: 1}.to_json, 0, 11_111) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :export_id - expect(error.message).to start_with('Export') + expect(error.message).to start_with("Export") end) end - it 'no nonprofit' do + it "no nonprofit" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: @user) Timecop.freeze(2020, 4, 6) do - expect { ExportSupporters.run_export(0, { x: 1 }.to_json, @user.id, @export.id) }.to(raise_error do |error| + expect { ExportSupporters.run_export(0, {x: 1}.to_json, @user.id, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :npo_id - expect(error.message).to start_with('Nonprofit') + expect(error.message).to start_with("Nonprofit") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -123,17 +125,17 @@ end end - it 'no user' do + it "no user" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: @user) Timecop.freeze(2020, 4, 6) do - expect { ExportSupporters.run_export(@nonprofit.id, { x: 1 }.to_json, 0, @export.id) }.to(raise_error do |error| + expect { ExportSupporters.run_export(@nonprofit.id, {x: 1}.to_json, 0, @export.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect(error.data[:key]).to eq :user_id - expect(error.message).to start_with('User') + expect(error.message).to start_with("User") @export.reload - expect(@export.status).to eq 'failed' + expect(@export.status).to eq "failed" expect(@export.exception).to eq error.to_s expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -143,39 +145,39 @@ end end - it 'handles exception in upload properly' do + it "handles exception in upload properly" do Timecop.freeze(2020, 4, 5) do @export = force_create(:export, user: @user) CHUNKED_UPLOAD_SERVICE.raise_error Timecop.freeze(2020, 4, 6) do - expect { - expect { ExportSupporters.run_export(@nonprofit.id, {}.to_json, @user.id, @export.id) }.to(raise_error do |error| - expect(error).to be_a StandardError - expect(error.message).to eq TestUploadService::TEST_ERROR_MESSAGE - - @export.reload - expect(@export.status).to eq 'failed' - expect(@export.exception).to eq error.to_s - expect(@export.ended).to eq Time.now - expect(@export.updated_at).to eq Time.now - end) - }.to have_enqueued_job(ExportSupportersFailedJob).with(@export) + expect { + expect { ExportSupporters.run_export(@nonprofit.id, {}.to_json, @user.id, @export.id) }.to(raise_error do |error| + expect(error).to be_a StandardError + expect(error.message).to eq TestUploadService::TEST_ERROR_MESSAGE + + @export.reload + expect(@export.status).to eq "failed" + expect(@export.exception).to eq error.to_s + expect(@export.ended).to eq Time.now + expect(@export.updated_at).to eq Time.now + end) + }.to have_enqueued_job(ExportSupportersFailedJob).with(@export) end end end - it 'uploads as expected' do + it "uploads as expected" do Timecop.freeze(2020, 4, 5) do @export = create(:export, user: @user, created_at: Time.now, updated_at: Time.now) Timecop.freeze(2020, 4, 6, 1, 2, 3) do expect { - ExportSupporters.run_export(@nonprofit.id, { root_url: 'https://localhost:8080/' }.to_json, @user.id, @export.id) + ExportSupporters.run_export(@nonprofit.id, {root_url: "https://localhost:8080/"}.to_json, @user.id, @export.id) }.to have_enqueued_job(ExportSupportersCompletedJob).with(@export) @export.reload expect(@export.url).to match export_url_regex - expect(@export.status).to eq 'completed' + expect(@export.status).to eq "completed" expect(@export.exception).to be_nil expect(@export.ended).to eq Time.now expect(@export.updated_at).to eq Time.now @@ -184,8 +186,8 @@ expect(csv[0]).to eq export_header - expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq 'text/csv' - expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq 'attachment' + expect(CHUNKED_UPLOAD_SERVICE.options[:content_type]).to eq "text/csv" + expect(CHUNKED_UPLOAD_SERVICE.options[:content_disposition]).to eq "attachment" end end end diff --git a/spec/legacy_lib/fetch/fetch_misc_nonprofit_settings_spec.rb b/spec/legacy_lib/fetch/fetch_misc_nonprofit_settings_spec.rb index cc8dbbc2ee..425b051fd4 100644 --- a/spec/legacy_lib/fetch/fetch_misc_nonprofit_settings_spec.rb +++ b/spec/legacy_lib/fetch/fetch_misc_nonprofit_settings_spec.rb @@ -2,38 +2,38 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe FetchMiscellaneousNpInfo do - describe '.fetch' do - describe 'validates params' do - it 'with empty args' do + describe ".fetch" do + describe "validates params" do + it "with empty args" do expect { FetchMiscellaneousNpInfo.fetch(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :np_id, name: :required }, - { key: :np_id, name: :is_integer }]) + expect_validation_errors(error.data, [{key: :np_id, name: :required}, + {key: :np_id, name: :is_integer}]) end) end - it 'with invalid np' do + it "with invalid np" do expect { FetchMiscellaneousNpInfo.fetch(50) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :np_id }]) + expect_validation_errors(error.data, [{key: :np_id}]) end) end end - describe 'with valid nonprofit' do - before(:each) do + describe "with valid nonprofit" do + before do @np = force_create(:nm_justice) end - it 'returns hash with empty misc settings' do + it "returns hash with empty misc settings" do expect(FetchMiscellaneousNpInfo.fetch(@np.id).attributes).to eq(MiscellaneousNpInfo.new.attributes) end - it 'returns the misc if already there' do - a = force_create(:miscellaneous_np_info, nonprofit: @np, donate_again_url: 'http://donateagain.url') + it "returns the misc if already there" do + a = force_create(:miscellaneous_np_info, nonprofit: @np, donate_again_url: "http://donateagain.url") expect(FetchMiscellaneousNpInfo.fetch(@np.id)).to eq(a) end end diff --git a/spec/legacy_lib/fetch/fetch_nonprofit_email_spec.rb b/spec/legacy_lib/fetch/fetch_nonprofit_email_spec.rb index 0e19ef0db1..394ea6cbd1 100644 --- a/spec/legacy_lib/fetch/fetch_nonprofit_email_spec.rb +++ b/spec/legacy_lib/fetch/fetch_nonprofit_email_spec.rb @@ -2,23 +2,23 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe FetchNonprofitEmail, pending: true do - context '.with_charge' do + context ".with_charge" do let(:charge) { Models::Charge } it "returns the nonprofit org email if it's there!" do - charge.nonprofit.email = 'nonprofit@someorg.org' - expect(FetchNonprofitEmail.with_charge(charge)).to eq('nonprofit@someorg.org') + charge.nonprofit.email = "nonprofit@someorg.org" + expect(FetchNonprofitEmail.with_charge(charge)).to eq("nonprofit@someorg.org") end - it 'returns support@commitchange.com if Nonprofit email is blank' do - charge.nonprofit.email = '' + it "returns support@commitchange.com if Nonprofit email is blank" do + charge.nonprofit.email = "" expect(FetchNonprofitEmail.with_charge(charge)).to eq(Houdini.hoster.support_email) end - it 'returns support@commitchange.com if Nonprofit email is nil' do + it "returns support@commitchange.com if Nonprofit email is nil" do charge.nonprofit.email = nil expect(FetchNonprofitEmail.with_charge(charge)).to eq(Houdini.hoster.support_email) end diff --git a/spec/legacy_lib/format/currency_spec.rb b/spec/legacy_lib/format/currency_spec.rb index 31fb7c0a86..82595bf854 100644 --- a/spec/legacy_lib/format/currency_spec.rb +++ b/spec/legacy_lib/format/currency_spec.rb @@ -2,47 +2,47 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Format::Currency do symbol = Houdini.intl.currencies[0] - describe '.dollars_to_cents' do - context 'with dollar sign' do - it 'converts to a cents value as an integer' do + describe ".dollars_to_cents" do + context "with dollar sign" do + it "converts to a cents value as an integer" do expect(Format::Currency.dollars_to_cents("#{symbol}11.11")).to eq(1111) end end - context 'without dollar sign' do - it 'converts to a cents value as an integer' do - expect(Format::Currency.dollars_to_cents('11.00')).to eq(1100) + context "without dollar sign" do + it "converts to a cents value as an integer" do + expect(Format::Currency.dollars_to_cents("11.00")).to eq(1100) end end - context 'with large amount' do - it 'converts to a cents value as an integer' do + context "with large amount" do + it "converts to a cents value as an integer" do expect(Format::Currency.dollars_to_cents("#{symbol}111111111111.11")).to eq(11_111_111_111_111) end end end - describe '.cents_to_dollars' do - context 'hundreth-precision (eg $1.11)' do - it 'converts to dollars with hundredth precision' do - expect(Format::Currency.cents_to_dollars(111)).to eq('1.11') + describe ".cents_to_dollars" do + context "hundreth-precision (eg $1.11)" do + it "converts to dollars with hundredth precision" do + expect(Format::Currency.cents_to_dollars(111)).to eq("1.11") end end - context 'tenth-precision (eg. $1.10)' do - it 'converts to dollars with a trailing zero' do - expect(Format::Currency.cents_to_dollars(110)).to eq('1.10') + context "tenth-precision (eg. $1.10)" do + it "converts to dollars with a trailing zero" do + expect(Format::Currency.cents_to_dollars(110)).to eq("1.10") end end - context 'whole value (eg. $1)' do - it 'converts to dollars without decimals' do - expect(Format::Currency.cents_to_dollars(100)).to eq('1') + context "whole value (eg. $1)" do + it "converts to dollars without decimals" do + expect(Format::Currency.cents_to_dollars(100)).to eq("1") end end end diff --git a/spec/legacy_lib/format/dedication_spec.rb b/spec/legacy_lib/format/dedication_spec.rb index 2ce5b6da71..b604d9b7d4 100644 --- a/spec/legacy_lib/format/dedication_spec.rb +++ b/spec/legacy_lib/format/dedication_spec.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../../app/legacy_lib/format/dedication' +require_relative "../../../app/legacy_lib/format/dedication" describe Format::Dedication do - describe '.from_json' do - it 'returns string if not json' do - expect(Format::Dedication.from_json('Hello there')).to eq('Hello there') + describe ".from_json" do + it "returns string if not json" do + expect(Format::Dedication.from_json("Hello there")).to eq("Hello there") end - it 'returns dedication with type, name, and note if json' do + it "returns dedication with type, name, and note if json" do json = '{"type": "memory", "name": "Bob Ross", "note": "This is the note"}' - expect(Format::Dedication.from_json(json)).to eq('Donation made in memory of Bob Ross. Note: This is the note') + expect(Format::Dedication.from_json(json)).to eq("Donation made in memory of Bob Ross. Note: This is the note") end end end diff --git a/spec/legacy_lib/format/geography_spec.rb b/spec/legacy_lib/format/geography_spec.rb index de42fb525f..0166d80d77 100644 --- a/spec/legacy_lib/format/geography_spec.rb +++ b/spec/legacy_lib/format/geography_spec.rb @@ -2,20 +2,20 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../../app/legacy_lib/format/geography' +require_relative "../../../app/legacy_lib/format/geography" describe Format::Geography do - describe '.full_state_to_code' do - it 'converts a full state name, case-insensitive, to a state code' do - expect(Format::Geography.full_state_to_code('New mexico')).to eq('NM') + describe ".full_state_to_code" do + it "converts a full state name, case-insensitive, to a state code" do + expect(Format::Geography.full_state_to_code("New mexico")).to eq("NM") end - it 'ignores pre-existing state codes' do - expect(Format::Geography.full_state_to_code('NM')).to eq('NM') + it "ignores pre-existing state codes" do + expect(Format::Geography.full_state_to_code("NM")).to eq("NM") end - it 'returns nil when unrecognized' do - expect(Format::Geography.full_state_to_code('xxyyxx')).to eq(nil) + it "returns nil when unrecognized" do + expect(Format::Geography.full_state_to_code("xxyyxx")).to eq(nil) end end end diff --git a/spec/legacy_lib/format/indefinitize_spec.rb b/spec/legacy_lib/format/indefinitize_spec.rb index ad2401d399..4ea4272542 100644 --- a/spec/legacy_lib/format/indefinitize_spec.rb +++ b/spec/legacy_lib/format/indefinitize_spec.rb @@ -2,26 +2,26 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../../app/legacy_lib/format/indefinitize' +require_relative "../../../app/legacy_lib/format/indefinitize" describe Format::Indefinitize do - describe '#article' do - it 'returns an for string starting with vowel' do - expect(Format::Indefinitize.article('apple')).to eq('an') + describe "#article" do + it "returns an for string starting with vowel" do + expect(Format::Indefinitize.article("apple")).to eq("an") end - it 'returns a for string not starting with vowel' do - expect(Format::Indefinitize.article('bear')).to eq('a') + it "returns a for string not starting with vowel" do + expect(Format::Indefinitize.article("bear")).to eq("a") end end - describe '#with_article' do - it 'returns an and word for string starting with vowel' do - expect(Format::Indefinitize.with_article('apple')).to eq('an apple') + describe "#with_article" do + it "returns an and word for string starting with vowel" do + expect(Format::Indefinitize.with_article("apple")).to eq("an apple") end - it 'returns a and word for not string starting with vowel' do - expect(Format::Indefinitize.with_article('bear')).to eq('a bear') + it "returns a and word for not string starting with vowel" do + expect(Format::Indefinitize.with_article("bear")).to eq("a bear") end end end diff --git a/spec/legacy_lib/format/name_spec.rb b/spec/legacy_lib/format/name_spec.rb index 0f48167042..c62fa7969d 100644 --- a/spec/legacy_lib/format/name_spec.rb +++ b/spec/legacy_lib/format/name_spec.rb @@ -2,13 +2,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'spec_helper' -require 'format/name' +require "spec_helper" +require "format/name" describe Format::Name do - describe '.email_from_np' do - it 'gives the name, minus commas, with our email in brackets' do - result = Format::Name.email_from_np('Test, X, Y') + describe ".email_from_np" do + it "gives the name, minus commas, with our email in brackets" do + result = Format::Name.email_from_np("Test, X, Y") expect(result).to eq("\"Test X Y\" <#{Houdini.hoster.support_email}>") end end diff --git a/spec/legacy_lib/format/url_spec.rb b/spec/legacy_lib/format/url_spec.rb index 008043c609..31b1dc5803 100644 --- a/spec/legacy_lib/format/url_spec.rb +++ b/spec/legacy_lib/format/url_spec.rb @@ -2,15 +2,15 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../../app/legacy_lib/format/url' +require_relative "../../../app/legacy_lib/format/url" describe Format::Url do - describe '.concat' do - let(:event_url) { 'al/birmingham/hand-in-paw/events/picasso-pets' } - let(:root_url) { 'http://localhost:8080/' } - let(:formatted_url) { 'http://localhost:8080/al/birmingham/hand-in-paw/events/picasso-pets' } + describe ".concat" do + let(:event_url) { "al/birmingham/hand-in-paw/events/picasso-pets" } + let(:root_url) { "http://localhost:8080/" } + let(:formatted_url) { "http://localhost:8080/al/birmingham/hand-in-paw/events/picasso-pets" } - it 'removes extra whacks from the url' do + it "removes extra whacks from the url" do # and helps prevent broken links in emails expect(Format::Url.concat(root_url, event_url)).to eq(formatted_url) end diff --git a/spec/legacy_lib/import/import_civicrm_payments_spec.rb b/spec/legacy_lib/import/import_civicrm_payments_spec.rb index e22bab1917..1e713a8730 100644 --- a/spec/legacy_lib/import/import_civicrm_payments_spec.rb +++ b/spec/legacy_lib/import/import_civicrm_payments_spec.rb @@ -2,11 +2,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe ImportCivicrmPayments do - it 'is untested', pending: true do - pending 'add tests here' + it "is untested", pending: true do + pending "add tests here" raise end end diff --git a/spec/legacy_lib/insert/insert_bank_account_spec.rb b/spec/legacy_lib/insert/insert_bank_account_spec.rb index 6e120913a5..29f24e6690 100644 --- a/spec/legacy_lib/insert/insert_bank_account_spec.rb +++ b/spec/legacy_lib/insert/insert_bank_account_spec.rb @@ -2,12 +2,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertBankAccount do let(:stripe_helper) { StripeMockHelper.default_helper } - around(:each) do |example| - Timecop.freeze(2020, 5, 4) do + around do |example| + Timecop.freeze(2020, 5, 4) do StripeMockHelper.mock do example.run end @@ -15,99 +15,104 @@ end let(:nonprofit) { force_create(:nm_justice) } - let(:user) { force_create(:user, email: 'x@example.com') } + let(:user) { force_create(:user, email: "x@example.com") } - describe '.with_stripe' do - describe 'param validation' do - it 'validates np and user' do + describe ".with_stripe" do + describe "param validation" do + it "validates np and user" do expect { InsertBankAccount.with_stripe(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :nonprofit, name: :required }, - { key: :nonprofit, name: :is_a }, - { key: :user, name: :required }, - { key: :user, name: :is_a }]) + expect_validation_errors(error.data, [{key: :nonprofit, name: :required}, + {key: :nonprofit, name: :is_a}, + {key: :user, name: :required}, + {key: :user, name: :is_a}]) end) expect { InsertBankAccount.with_stripe(1, 2, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :nonprofit, name: :is_a }, - { key: :user, name: :is_a } - ]) + {key: :nonprofit, name: :is_a}, + {key: :user, name: :is_a} + ]) end) end - it 'validate stripe_bank_account_token' do + it "validate stripe_bank_account_token" do expect { InsertBankAccount.with_stripe(nonprofit, user, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [{ - key: :stripe_bank_account_token, - name: :required - }, - { - key: :stripe_bank_account_token, - name: :not_blank - }]) + key: :stripe_bank_account_token, + name: :required + }, + { + key: :stripe_bank_account_token, + name: :not_blank + }]) end) end - it 'validates whether vetted' do - expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: 'blah') }.to(raise_error do |error| + it "validates whether vetted" do + expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: "blah") }.to(raise_error do |error| expect(error).to be_a ArgumentError - expect(error.message).to include('vetted') + expect(error.message).to include("vetted") end) end end - describe 'exceptions in main function' do - before (:each) { nonprofit.vetted = true } - it 'StripeAccount.find_or_create fails' do + describe "exceptions in main function" do + before { nonprofit.vetted = true } + + it "StripeAccount.find_or_create fails" do expect(StripeAccount).to receive(:find_or_create).and_raise(StandardError.new) - expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: 'blah') }.to(raise_error do |error| + expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: "blah") }.to(raise_error do |error| expect(error).to be_a StandardError end) end - it 'Stripe::Account.retrieve fails' do - expect(StripeAccount).to receive(:find_or_create).and_return('account_id') - StripeMockHelper.prepare_error(Stripe::StripeError.new('some error happened'), :get_account) + it "Stripe::Account.retrieve fails" do + expect(StripeAccount).to receive(:find_or_create).and_return("account_id") + StripeMockHelper.prepare_error(Stripe::StripeError.new("some error happened"), :get_account) - expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: 'blah') }.to(raise_error do |error| + expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: "blah") }.to(raise_error do |error| expect(error).to be_a Stripe::StripeError end) end end - describe 'works with account retrieval' do - before (:each) { nonprofit.vetted = true; nonprofit.save! } - let(:stripe_acct) { Stripe::Account.create(managed: true, country: 'US', display_name: 'test_display_name') } - let(:stripe_bank_account_token) { StripeMockHelper.generate_bank_token(country: 'US', routing_number: '110000000', account_number: '000123456789') } + describe "works with account retrieval" do + before { + nonprofit.vetted = true + nonprofit.save! + } + + let(:stripe_acct) { Stripe::Account.create(managed: true, country: "US", display_name: "test_display_name") } + let(:stripe_bank_account_token) { StripeMockHelper.generate_bank_token(country: "US", routing_number: "110000000", account_number: "000123456789") } - it 'sets failure message when external_account create fails' do + it "sets failure message when external_account create fails" do expect(Stripe::Account).to receive(:retrieve).and_return(stripe_acct) - StripeMockHelper.prepare_error(Stripe::StripeError.new('hmm'), :create_external_account) + StripeMockHelper.prepare_error(Stripe::StripeError.new("hmm"), :create_external_account) expect { InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: stripe_bank_account_token) }.to raise_error { |error| expect(error).to be_a ArgumentError - expect(error.message).to eq 'Failed to connect the bank account: #' + expect(error.message).to eq "Failed to connect the bank account: #" } end - it 'works with external account creation' do + it "works with external account creation" do expect(Stripe::Account).to receive(:retrieve).and_return(stripe_acct) result = InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: stripe_bank_account_token) - expected = { email: user.email, - stripe_bank_account_token: stripe_bank_account_token, - pending_verification: true, - created_at: Time.now, - updated_at: Time.now, - status: nil, # doesn't seem to be used - id: 1, - deleted: nil, - account_number: nil, # doesn't seem to be used - nonprofit_id: nonprofit.id, - bank_name: nil }.with_indifferent_access + expected = {email: user.email, + stripe_bank_account_token: stripe_bank_account_token, + pending_verification: true, + created_at: Time.now, + updated_at: Time.now, + status: nil, # doesn't seem to be used + id: 1, + deleted: nil, + account_number: nil, # doesn't seem to be used + nonprofit_id: nonprofit.id, + bank_name: nil}.with_indifferent_access expect(result.attributes.with_indifferent_access.except(:confirmation_token, :stripe_bank_account_id, :name)).to eq expected expect(result[:confirmation_token]).to_not be_blank expect(result[:stripe_bank_account_id]).to_not be_blank @@ -115,43 +120,45 @@ end end - describe 'handles replacing the old accounts' do - before (:each) do - nonprofit.vetted = true; nonprofit.save! + describe "handles replacing the old accounts" do + before do + nonprofit.vetted = true + nonprofit.save! old_bank_account_false old_bank_account_nil old_bank_account_true end - let(:stripe_acct) { Stripe::Account.create(managed: true, country: 'US', display_name: 'test_display_name') } - let(:stripe_bank_account_token) { StripeMockHelper.generate_bank_token(country: 'US', routing_number: '110000000', account_number: '000123456789') } + + let(:stripe_acct) { Stripe::Account.create(managed: true, country: "US", display_name: "test_display_name") } + let(:stripe_bank_account_token) { StripeMockHelper.generate_bank_token(country: "US", routing_number: "110000000", account_number: "000123456789") } let(:old_bank_account_nil) { force_create(:bank_account, nonprofit: nonprofit, deleted: nil) } let(:old_bank_account_false) { force_create(:bank_account, nonprofit: nonprofit, deleted: false) } let(:old_bank_account_true) { force_create(:bank_account, nonprofit: nonprofit, deleted: true) } - it 'works with external account creation' do + it "works with external account creation" do expect(Stripe::Account).to receive(:retrieve).and_return(stripe_acct) result = InsertBankAccount.with_stripe(nonprofit, user, stripe_bank_account_token: stripe_bank_account_token) - expected = { email: user.email, - stripe_bank_account_token: stripe_bank_account_token, - pending_verification: true, - created_at: Time.now, - updated_at: Time.now, - status: nil, # doesn't seem to be used - id: result['id'], - deleted: nil, - account_number: nil, # doesn't seem to be used - nonprofit_id: nonprofit.id, - bank_name: nil }.with_indifferent_access + expected = {email: user.email, + stripe_bank_account_token: stripe_bank_account_token, + pending_verification: true, + created_at: Time.now, + updated_at: Time.now, + status: nil, # doesn't seem to be used + id: result["id"], + deleted: nil, + account_number: nil, # doesn't seem to be used + nonprofit_id: nonprofit.id, + bank_name: nil}.with_indifferent_access expect(result.attributes.with_indifferent_access.except(:confirmation_token, :stripe_bank_account_id, :name)).to eq expected expect(result[:confirmation_token]).to_not be_blank expect(result[:stripe_bank_account_id]).to_not be_blank expect(result[:name]).to_not be_blank expect(nonprofit.bank_account).to eq result - expect(BankAccount.where('nonprofit_id = ?', nonprofit.id).count).to eq 4 - expect(BankAccount.where('nonprofit_id = ? and deleted = true', nonprofit.id).count).to eq 3 + expect(BankAccount.where("nonprofit_id = ?", nonprofit.id).count).to eq 4 + expect(BankAccount.where("nonprofit_id = ? and deleted = true", nonprofit.id).count).to eq 3 end end end diff --git a/spec/legacy_lib/insert/insert_card_spec.rb b/spec/legacy_lib/insert/insert_card_spec.rb index 5e68664df0..6dd8daac17 100644 --- a/spec/legacy_lib/insert/insert_card_spec.rb +++ b/spec/legacy_lib/insert/insert_card_spec.rb @@ -2,12 +2,12 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertCard do - describe '.with_stripe' do - let(:stripe_helper) { StripeMockHelper.default_helper} + describe ".with_stripe" do + let(:stripe_helper) { StripeMockHelper.default_helper } - let(:stripe_card_token) { StripeMockHelper.generate_card_token(last4: '9191', exp_year: 2011) } + let(:stripe_card_token) { StripeMockHelper.generate_card_token(last4: "9191", exp_year: 2011) } let(:default_card_attribs) do { created_at: Time.now, @@ -30,7 +30,7 @@ user end - around(:each) do |example| + around do |example| Timecop.freeze(2025, 5, 4) do StripeMockHelper.mock do example.run @@ -38,17 +38,17 @@ end end - it 'params are invalid' do + it "params are invalid" do expect { InsertCard.with_stripe({}) }.to raise_error(ParamValidation::ValidationError) do |error| - expect_validation_errors(error.data, [{ key: 'holder_id', name: :required }, - { key: 'holder_type', name: 'included_in' }, - { key: 'holder_type', name: 'required' }, - { key: 'stripe_card_id', name: 'required' }, - { key: 'stripe_card_id', name: 'not_blank' }, - { key: 'stripe_card_token', name: 'required' }, - { key: 'stripe_card_token', name: 'not_blank' }, - { key: 'name', name: 'required' }, - { key: 'name', name: 'not_blank' }]) + expect_validation_errors(error.data, [{key: "holder_id", name: :required}, + {key: "holder_type", name: "included_in"}, + {key: "holder_type", name: "required"}, + {key: "stripe_card_id", name: "required"}, + {key: "stripe_card_id", name: "not_blank"}, + {key: "stripe_card_token", name: "required"}, + {key: "stripe_card_token", name: "not_blank"}, + {key: "name", name: "required"}, + {key: "name", name: "not_blank"}]) end # expect(ret[:status]).to eq(:unprocessable_entity) # expect(ret[:json][:error]).to start_with('Validation error') @@ -65,14 +65,15 @@ # { key: 'name', name: 'not_blank' }]) end - describe 'for supporter' do + describe "for supporter" do let(:supporter) { force_create(:supporter, nonprofit: nonprofit) } let(:event) do force_create(:event, nonprofit: nonprofit, end_datetime: Time.now.since(1.day)) end let(:user_not_from_nonprofit) { force_create(:user) } + def verify_cust_added_supporter(stripe_customer_id, holder_id) - verify_cust_added(stripe_customer_id, holder_id, 'Supporter') + verify_cust_added(stripe_customer_id, holder_id, "Supporter") end def verify_supporter_source_token(source_token, card) @@ -83,84 +84,93 @@ def verify_event_source_token(source_token, card, event) verify_source_token(source_token, card, 20, event.end_datetime.since(20.days), event) end - context 'card exists' do + context "card exists" do let(:supporter) { create(:supporter, :has_a_card, nonprofit: nonprofit) } - it 'should properly add supporter card' do + it "should properly add supporter card" do expect(supporter.cards.count).to eq(1) stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| stripe_customer = m.call(*args); stripe_customer } - card_data = { holder_type: 'Supporter', holder_id: supporter.id, stripe_card_id: 'card_88888', stripe_card_token: stripe_card_token, name: 'card_name' } + expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| + stripe_customer = m.call(*args) + stripe_customer + } + card_data = {holder_type: "Supporter", holder_id: supporter.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} orig_card = supporter.cards.first card_ret = InsertCard.with_stripe(card_data) supporter.reload - card = supporter.cards.where('cards.name = ?', 'card_name').first + card = supporter.cards.where("cards.name = ?", "card_name").first expected_card = { id: card.id, - name: 'card_name', + name: "card_name", stripe_card_token: stripe_card_token, - stripe_card_id: 'card_88888', + stripe_card_id: "card_88888", holder_id: supporter.id, - holder_type: 'Supporter', - stripe_customer_id: stripe_customer['id'] + holder_type: "Supporter", + stripe_customer_id: stripe_customer["id"] }.merge(default_card_attribs).with_indifferent_access expect(card.attributes).to eq expected_card expect(supporter.cards.count).to eq(2) - expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(2) - expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0) + expect(Card.where("holder_id = ? and holder_type = ?", supporter.id, "Supporter").count).to eq(2) + expect(Card.where("holder_id = ? and holder_type = ? and inactive != ?", supporter.id, "Supporter", false).count).to eq(0) expect(supporter.cards.find(orig_card.id)).to eq(orig_card) verify_cust_added_supporter(card.stripe_customer_id, supporter.id) - verify_supporter_source_token(card_ret['token'], card) + verify_supporter_source_token(card_ret["token"], card) end - it 'should properly add card for event' do + it "should properly add card for event" do expect(supporter.cards.count).to eq(1) stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| stripe_customer = m.call(*args); stripe_customer } - card_data = { holder_type: 'Supporter', holder_id: supporter.id, stripe_card_id: 'card_88888', stripe_card_token: stripe_card_token, name: 'card_name' } + expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| + stripe_customer = m.call(*args) + stripe_customer + } + card_data = {holder_type: "Supporter", holder_id: supporter.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} orig_card = supporter.cards.first card_ret = InsertCard.with_stripe(card_data, nil, event.id, user) supporter.reload - card = supporter.cards.where('cards.name = ?', 'card_name').first + card = supporter.cards.where("cards.name = ?", "card_name").first expected_card = { id: card.id, - name: 'card_name', + name: "card_name", stripe_card_token: stripe_card_token, - stripe_card_id: 'card_88888', + stripe_card_id: "card_88888", holder_id: supporter.id, - holder_type: 'Supporter', - stripe_customer_id: stripe_customer['id'] + holder_type: "Supporter", + stripe_customer_id: stripe_customer["id"] }.merge(default_card_attribs).with_indifferent_access expect(card.attributes).to eq expected_card expect(supporter.cards.count).to eq(2) - expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(2) - expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0) + expect(Card.where("holder_id = ? and holder_type = ?", supporter.id, "Supporter").count).to eq(2) + expect(Card.where("holder_id = ? and holder_type = ? and inactive != ?", supporter.id, "Supporter", false).count).to eq(0) expect(supporter.cards.find(orig_card.id)).to eq(orig_card) verify_cust_added_supporter(card.stripe_customer_id, supporter.id) - verify_event_source_token(card_ret['token'], card, event) + verify_event_source_token(card_ret["token"], card, event) end end - context 'card doesnt exist' do - it 'invalid params get ignored' do + context "card doesnt exist" do + it "invalid params get ignored" do stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| stripe_customer = m.call(*args); stripe_customer } - card_data = { holder_type: 'Supporter', holder_id: supporter.id, stripe_card_id: 'card_88888', stripe_card_token: stripe_card_token, - name: 'card_name', created_at: DateTime.new(0), updated_at: DateTime.new(0), inactive: true } + expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| + stripe_customer = m.call(*args) + stripe_customer + } + card_data = {holder_type: "Supporter", holder_id: supporter.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, + name: "card_name", created_at: DateTime.new(0), updated_at: DateTime.new(0), inactive: true} card_ret = InsertCard.with_stripe(card_data) @@ -170,35 +180,38 @@ def verify_event_source_token(source_token, card, event) expected_card = { id: card.id, - holder_type: 'Supporter', + holder_type: "Supporter", holder_id: supporter.id, stripe_card_token: stripe_card_token, - name: 'card_name', - stripe_card_id: 'card_88888', - stripe_customer_id: stripe_customer['id'] + name: "card_name", + stripe_card_id: "card_88888", + stripe_customer_id: stripe_customer["id"] }.merge(default_card_attribs).with_indifferent_access expect(card.attributes).to eq expected_card - verify_supporter_source_token(card_ret['token'], card) + verify_supporter_source_token(card_ret["token"], card) end - it 'should properly add supporter card when no card exist' do + it "should properly add supporter card when no card exist" do stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| stripe_customer = m.call(*args); stripe_customer } + expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| + stripe_customer = m.call(*args) + stripe_customer + } - card_data = { holder_type: 'Supporter', holder_id: supporter.id, stripe_card_id: 'card_88888', stripe_card_token: stripe_card_token, name: 'card_name' } + card_data = {holder_type: "Supporter", holder_id: supporter.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} card_ret = InsertCard.with_stripe(card_data) supporter.reload - card = supporter.cards.where('cards.name = ?', 'card_name').first + card = supporter.cards.where("cards.name = ?", "card_name").first expected_card = { id: card.id, - name: 'card_name', - stripe_card_id: 'card_88888', + name: "card_name", + stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, - stripe_customer_id: stripe_customer['id'], - holder_type: 'Supporter', + stripe_customer_id: stripe_customer["id"], + holder_type: "Supporter", holder_id: supporter.id }.merge(default_card_attribs).with_indifferent_access @@ -206,69 +219,75 @@ def verify_event_source_token(source_token, card, event) expect(supporter.cards.count).to eq(1) - expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(1) - expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0) + expect(Card.where("holder_id = ? and holder_type = ?", supporter.id, "Supporter").count).to eq(1) + expect(Card.where("holder_id = ? and holder_type = ? and inactive != ?", supporter.id, "Supporter", false).count).to eq(0) verify_cust_added_supporter(card.stripe_customer_id, supporter.id) - verify_supporter_source_token(card_ret['token'], card) + verify_supporter_source_token(card_ret["token"], card) end - it 'should properly add card for event' do + it "should properly add card for event" do stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| stripe_customer = m.call(*args); stripe_customer } - card_data = { holder_type: 'Supporter', holder_id: supporter.id, stripe_card_id: 'card_88888', stripe_card_token: stripe_card_token, name: 'card_name' } + expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| + stripe_customer = m.call(*args) + stripe_customer + } + card_data = {holder_type: "Supporter", holder_id: supporter.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} card_ret = InsertCard.with_stripe(card_data, nil, event.id, user) supporter.reload - card = supporter.cards.where('cards.name = ?', 'card_name').first + card = supporter.cards.where("cards.name = ?", "card_name").first expected_card = { id: card.id, - name: 'card_name', + name: "card_name", stripe_card_token: stripe_card_token, - stripe_card_id: 'card_88888', + stripe_card_id: "card_88888", holder_id: supporter.id, - holder_type: 'Supporter', - stripe_customer_id: stripe_customer['id'] + holder_type: "Supporter", + stripe_customer_id: stripe_customer["id"] }.merge(default_card_attribs).with_indifferent_access expect(card.attributes).to eq expected_card expect(supporter.cards.count).to eq(1) - expect(Card.where('holder_id = ? and holder_type = ?', supporter.id, 'Supporter').count).to eq(1) - expect(Card.where('holder_id = ? and holder_type = ? and inactive != ?', supporter.id, 'Supporter', false).count).to eq(0) + expect(Card.where("holder_id = ? and holder_type = ?", supporter.id, "Supporter").count).to eq(1) + expect(Card.where("holder_id = ? and holder_type = ? and inactive != ?", supporter.id, "Supporter", false).count).to eq(0) verify_cust_added_supporter(card.stripe_customer_id, supporter.id) - verify_event_source_token(card_ret['token'], card, event) + verify_event_source_token(card_ret["token"], card, event) end end - it 'should return proper error when no supporter exists' do - expect { InsertCard.with_stripe(holder_id: 5_555_555, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', stripe_card_token: stripe_card_token, name: 'name')}. - to raise_error(RuntimeError) {|error| expect(error.message).to eq 'Sorry, you need to provide a nonprofit or supporter'} + it "should return proper error when no supporter exists" do + expect { InsertCard.with_stripe(holder_id: 5_555_555, holder_type: "Supporter", stripe_card_id: "card_fafjeht", stripe_card_token: stripe_card_token, name: "name") } + .to raise_error(RuntimeError) { |error| expect(error.message).to eq "Sorry, you need to provide a nonprofit or supporter" } end - it 'should return proper error when you try to add using an event with unauthorized user' do + it "should return proper error when you try to add using an event with unauthorized user" do expect { - InsertCard.with_stripe({ holder_id: supporter.id, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', stripe_card_token: stripe_card_token, name: 'name' }, nil, event.id, user_not_from_nonprofit) - }.to raise_error(AuthenticationError) + InsertCard.with_stripe({holder_id: supporter.id, holder_type: "Supporter", stripe_card_id: "card_fafjeht", stripe_card_token: stripe_card_token, name: "name"}, nil, event.id, user_not_from_nonprofit) + }.to raise_error(AuthenticationError) end - it 'should return proper error when an invalid event_id is provided' do - expect {InsertCard.with_stripe({ holder_id: supporter.id, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', - stripe_card_token: stripe_card_token, name: 'name' }, nil, 55_555, user_not_from_nonprofit)}.to raise_error(RuntimeError) do |error| - expect(error.message).to eq 'Oops! There was an error: 55555 is not a valid event' + it "should return proper error when an invalid event_id is provided" do + expect { + InsertCard.with_stripe({holder_id: supporter.id, holder_type: "Supporter", stripe_card_id: "card_fafjeht", + stripe_card_token: stripe_card_token, name: "name"}, nil, 55_555, user_not_from_nonprofit) + }.to raise_error(RuntimeError) do |error| + expect(error.message).to eq "Oops! There was an error: 55555 is not a valid event" end end - it 'should return proper error when event doesnt match the supporters nonprofit' do + it "should return proper error when event doesnt match the supporters nonprofit" do supporter2 = force_create(:supporter, nonprofit: force_create(:fv_poverty)) - expect { InsertCard.with_stripe({ holder_id: supporter2.id, holder_type: 'Supporter', stripe_card_id: 'card_fafjeht', stripe_card_token: stripe_card_token, name: 'name' }, - nil, event.id, user_not_from_nonprofit)}.to raise_error(RuntimeError) do |error| - expect(error.message).to eq "Oops! There was an error: Event #{event.id} is not for the same nonprofit as supporter #{supporter2.id}" - end - + expect { + InsertCard.with_stripe({holder_id: supporter2.id, holder_type: "Supporter", stripe_card_id: "card_fafjeht", stripe_card_token: stripe_card_token, name: "name"}, + nil, event.id, user_not_from_nonprofit) + }.to raise_error(RuntimeError) do |error| + expect(error.message).to eq "Oops! There was an error: Event #{event.id} is not for the same nonprofit as supporter #{supporter2.id}" + end end end @@ -287,12 +306,12 @@ def verify_cust_added(stripe_customer_id, holder_id, holder_type) end def verify_source_token(source_token, card, max_uses, expiration_time, event = nil) - tok = SourceToken.where('token = ?', source_token).first + tok = SourceToken.where("token = ?", source_token).first expected = { created_at: Time.now, updated_at: Time.now, tokenizable_id: card.id, - tokenizable_type: 'Card', + tokenizable_type: "Card", max_uses: max_uses, total_uses: 0, expiration: expiration_time, diff --git a/spec/legacy_lib/insert/insert_charge_spec.rb b/spec/legacy_lib/insert/insert_charge_spec.rb index 250f072236..3174edbbf8 100644 --- a/spec/legacy_lib/insert/insert_charge_spec.rb +++ b/spec/legacy_lib/insert/insert_charge_spec.rb @@ -2,414 +2,417 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'stripe_mock' +require "rails_helper" +require "stripe_mock" describe InsertCharge do include_context :shared_donation_charge_context let!(:donation) { force_create(:donation, id: 555) } - describe '.with_stripe' do - before(:each) do + + describe ".with_stripe" do + before do Houdini.payment_providers.stripe.connect = true end - describe 'param validation' do - it 'does basic validation' do + + describe "param validation" do + it "does basic validation" do expect { InsertCharge.with_stripe(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, - [ - { key: :amount, name: :required }, - { key: :amount, name: :is_integer }, - { key: :amount, name: :min }, - { key: :nonprofit_id, name: :required }, - { key: :nonprofit_id, name: :is_integer }, - { key: :supporter_id, name: :required }, - { key: :supporter_id, name: :is_integer }, - { key: :card_id, name: :required }, - { key: :card_id, name: :is_integer }, - { key: :statement, name: :required }, - { key: :statement, name: :not_blank } - ]) + [ + {key: :amount, name: :required}, + {key: :amount, name: :is_integer}, + {key: :amount, name: :min}, + {key: :nonprofit_id, name: :required}, + {key: :nonprofit_id, name: :is_integer}, + {key: :supporter_id, name: :required}, + {key: :supporter_id, name: :is_integer}, + {key: :card_id, name: :required}, + {key: :card_id, name: :is_integer}, + {key: :statement, name: :required}, + {key: :statement, name: :not_blank} + ]) end) end - it 'verify the amount minimum works' do + it "verify the amount minimum works" do expect { InsertCharge.with_stripe(amount: -1) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, - [ - { key: :amount, name: :min }, - { key: :nonprofit_id, name: :required }, - { key: :nonprofit_id, name: :is_integer }, - { key: :supporter_id, name: :required }, - { key: :supporter_id, name: :is_integer }, - { key: :card_id, name: :required }, - { key: :card_id, name: :is_integer }, - { key: :statement, name: :required }, - { key: :statement, name: :not_blank } - - ]) + [ + {key: :amount, name: :min}, + {key: :nonprofit_id, name: :required}, + {key: :nonprofit_id, name: :is_integer}, + {key: :supporter_id, name: :required}, + {key: :supporter_id, name: :is_integer}, + {key: :card_id, name: :required}, + {key: :card_id, name: :is_integer}, + {key: :statement, name: :required}, + {key: :statement, name: :not_blank} + + ]) end) end - it 'verify that we check for valid nonprofit' do + it "verify that we check for valid nonprofit" do expect do InsertCharge.with_stripe(amount: 100, - nonprofit_id: 5555, - supporter_id: 5555, - card_id: 5555, - statement: 'our statement') - end .to(raise_error do |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, - [ - { key: :nonprofit_id } - ]) - end) + nonprofit_id: 5555, + supporter_id: 5555, + card_id: 5555, + statement: "our statement") + end.to(raise_error do |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, + [ + {key: :nonprofit_id} + ]) + end) end - it 'verify that we check for valid supporter' do + it "verify that we check for valid supporter" do expect do InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: 5555, - card_id: 5555, - statement: 'our statement') - end .to(raise_error do |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, - [ - { key: :supporter_id } - ]) - end) + nonprofit_id: nonprofit.id, + supporter_id: 5555, + card_id: 5555, + statement: "our statement") + end.to(raise_error do |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, + [ + {key: :supporter_id} + ]) + end) end - it 'verify that we check for valid card' do + it "verify that we check for valid card" do expect do InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: 5555, - statement: 'our statement') - end .to(raise_error do |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, - [ - { key: :card_id } - ]) - end) + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: 5555, + statement: "our statement") + end.to(raise_error do |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, + [ + {key: :card_id} + ]) + end) end - it 'verify that we check that the supporter belongs to the correct nonprofit' do + it "verify that we check that the supporter belongs to the correct nonprofit" do expect do InsertCharge.with_stripe(amount: 100, - nonprofit_id: other_nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - statement: 'our statement') - end .to(raise_error do |error| - expect(error).to be_a ParamValidation::ValidationError - expect(error.message).to eq "#{supporter.id} does not belong to this nonprofit #{other_nonprofit.id}" - expect_validation_errors(error.data, - [ - { key: :supporter_id } - ]) - end) + nonprofit_id: other_nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + statement: "our statement") + end.to(raise_error do |error| + expect(error).to be_a ParamValidation::ValidationError + expect(error.message).to eq "#{supporter.id} does not belong to this nonprofit #{other_nonprofit.id}" + expect_validation_errors(error.data, + [ + {key: :supporter_id} + ]) + end) end - it 'verify that we check that the card belongs to the correct supporter' do + it "verify that we check that the card belongs to the correct supporter" do expect do InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card_for_other_supporter.id, - statement: 'our statement') - end .to(raise_error do |error| - expect(error).to be_a ParamValidation::ValidationError - expect(error.message).to eq "#{card_for_other_supporter.id} does not belong to this supporter #{supporter.id}" - expect_validation_errors(error.data, - [ - { key: :card_id } - ]) - end) + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card_for_other_supporter.id, + statement: "our statement") + end.to(raise_error do |error| + expect(error).to be_a ParamValidation::ValidationError + expect(error.message).to eq "#{card_for_other_supporter.id} does not belong to this supporter #{supporter.id}" + expect_validation_errors(error.data, + [ + {key: :card_id} + ]) + end) end end - describe 'handle StripeAccount Find and Create failure' do - before(:each) do - StripeMockHelper.prepare_error(Stripe::StripeError.new('chaos'), :new_account) + describe "handle StripeAccount Find and Create failure" do + before do + StripeMockHelper.prepare_error(Stripe::StripeError.new("chaos"), :new_account) end - it 'does it fail properly' do + + it "does it fail properly" do expect do InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - statement: 'our statement') - end .to(raise_error do |error| - expect(error).to be_a Stripe::StripeError - end) + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + statement: "our statement") + end.to(raise_error do |error| + expect(error).to be_a Stripe::StripeError + end) expect(Charge).to_not be_exists expect(Payment).to_not be_exists end end - describe 'charge when customer belongs to client' do - before(:each) do - nonprofit.stripe_account_id = Stripe::Account.create['id'] + describe "charge when customer belongs to client" do + before do + nonprofit.stripe_account_id = Stripe::Account.create["id"] nonprofit.save! - card.stripe_customer_id = 'some other id' + card.stripe_customer_id = "some other id" card.save! - StripeMockHelper.prepare_error(Stripe::StripeError.new('chaos'), :get_customer) + StripeMockHelper.prepare_error(Stripe::StripeError.new("chaos"), :get_customer) end - it 'handles card error' do - expect(Stripe::Charge).to receive(:create).with({ application_fee: 33, + it "handles card error" do + expect(Stripe::Charge).to receive(:create).with({application_fee: 33, customer: card.stripe_customer_id, amount: 100, - currency: 'usd', - description: 'our statement<> blah-no-way', - statement_descriptor: 'our statement blah-n', - metadata: nil }, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| m.call(*args) } + currency: "usd", + description: "our statement<> blah-no-way", + statement_descriptor: "our statement blah-n", + metadata: nil}, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| m.call(*args) } StripeMockHelper.prepare_card_error(:card_declined) finished_result = InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - statement: 'our statement<> blah-no-way') + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + statement: "our statement<> blah-no-way") - common_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: 'failed', failure_message: 'There was an error with your card: The card was declined', created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: "failed", failure_message: "There was an error with your card: The card was declined", created_at: Time.now, updated_at: Time.now, disbursed: nil} result_expected = common_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: nil, supporter_id: supporter.id, ticket_id: nil, payment_id: nil, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_expected + expect(finished_result["charge"].attributes).to eq result_expected expect(Charge.first.attributes).to eq result_expected expect(Payment).to_not be_exists end - it 'handles general Stripe error' do - expect(Stripe::Charge).to receive(:create).with({ application_fee: 33, + it "handles general Stripe error" do + expect(Stripe::Charge).to receive(:create).with({application_fee: 33, customer: card.stripe_customer_id, amount: 100, - currency: 'usd', - description: 'our statement<> blah-no-way', - statement_descriptor: 'our statement blah-n', - metadata: nil }, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| m.call(*args) } - StripeMockHelper.prepare_error(Stripe::StripeError.new('blah'), :new_charge) + currency: "usd", + description: "our statement<> blah-no-way", + statement_descriptor: "our statement blah-n", + metadata: nil}, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| m.call(*args) } + StripeMockHelper.prepare_error(Stripe::StripeError.new("blah"), :new_charge) finished_result = InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - statement: 'our statement<> blah-no-way') + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + statement: "our statement<> blah-no-way") - common_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: 'failed', failure_message: "We're sorry, but something went wrong. We've been notified about this issue.", created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: "failed", failure_message: "We're sorry, but something went wrong. We've been notified about this issue.", created_at: Time.now, updated_at: Time.now, disbursed: nil} result_expected = common_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: nil, supporter_id: supporter.id, ticket_id: nil, payment_id: nil, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_expected + expect(finished_result["charge"].attributes).to eq result_expected expect(Charge.first.attributes).to eq result_expected expect(Payment).to_not be_exists end - describe 'input success' do + describe "input success" do let(:valid_input) do - { amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - donation_id: 555, - towards: 'blah', - kind: 'kind', - statement: 'our statement<> blah-no-way' } + {amount: 100, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + donation_id: 555, + towards: "blah", + kind: "kind", + statement: "our statement<> blah-no-way"} end - let (:date) { Time.new(2002, 10, 31) } + let(:date) { Time.new(2002, 10, 31) } let(:valid_input_with_date) { valid_input.merge(date: date) } - it 'saves the payment and updates the charge' do + it "saves the payment and updates the charge" do stripe_charge_id = nil - expect(Stripe::Charge).to receive(:create).with({ application_fee: 33, + expect(Stripe::Charge).to receive(:create).with({application_fee: 33, customer: card.stripe_customer_id, amount: 100, - currency: 'usd', - description: 'our statement<> blah-no-way', - statement_descriptor: 'our statement blah-n', - metadata: nil }, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| + currency: "usd", + description: "our statement<> blah-no-way", + statement_descriptor: "our statement blah-n", + metadata: nil}, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| a = m.call(*args) - stripe_charge_id = a['id'] + stripe_charge_id = a["id"] a } finished_result = InsertCharge.with_stripe(valid_input) - common_charge_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: 'pending', failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_charge_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: "pending", failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil} result_charge_expected = common_charge_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: 555, supporter_id: supporter.id, ticket_id: nil, payment_id: Payment.first.id, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_charge_expected + expect(finished_result["charge"].attributes).to eq result_charge_expected expect(Charge.first.attributes).to eq result_charge_expected expect(Charge.count).to eq 1 - common_payment_expected = { id: Payment.first.id, - gross_amount: 100, - fee_total: -33, - net_amount: 67, - towards: 'blah', - kind: 'kind', - donation_id: 555, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - refund_total: 0, - date: Time.now, - created_at: Time.now, - updated_at: Time.now, - search_vectors: nil }.with_indifferent_access - - expect(finished_result['payment'].attributes).to eq common_payment_expected + common_payment_expected = {id: Payment.first.id, + gross_amount: 100, + fee_total: -33, + net_amount: 67, + towards: "blah", + kind: "kind", + donation_id: 555, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + refund_total: 0, + date: Time.now, + created_at: Time.now, + updated_at: Time.now, + search_vectors: nil}.with_indifferent_access + + expect(finished_result["payment"].attributes).to eq common_payment_expected expect(Payment.first.attributes).to eq common_payment_expected expect(Payment.count).to eq 1 end - it 'saves the payment and updates the charge with passed date' do + it "saves the payment and updates the charge with passed date" do stripe_charge_id = nil - expect(Stripe::Charge).to receive(:create).with({ application_fee: 33, + expect(Stripe::Charge).to receive(:create).with({application_fee: 33, customer: card.stripe_customer_id, amount: 100, - currency: 'usd', - description: 'our statement<> blah-no-way', - statement_descriptor: 'our statement blah-n', - metadata: nil }, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| + currency: "usd", + description: "our statement<> blah-no-way", + statement_descriptor: "our statement blah-n", + metadata: nil}, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| a = m.call(*args) - stripe_charge_id = a['id'] + stripe_charge_id = a["id"] a } finished_result = InsertCharge.with_stripe(valid_input_with_date) - common_charge_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: 'pending', failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_charge_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: "pending", failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil} result_charge_expected = common_charge_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: 555, supporter_id: supporter.id, ticket_id: nil, payment_id: Payment.first.id, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_charge_expected + expect(finished_result["charge"].attributes).to eq result_charge_expected expect(Charge.first.attributes).to eq result_charge_expected expect(Charge.count).to eq 1 - common_payment_expected = { id: Payment.first.id, - gross_amount: 100, - fee_total: -33, - net_amount: 67, - towards: 'blah', - kind: 'kind', - donation_id: 555, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - refund_total: 0, - date: date, - created_at: Time.now, - updated_at: Time.now, - search_vectors: nil }.with_indifferent_access - - expect(finished_result['payment'].attributes).to eq common_payment_expected + common_payment_expected = {id: Payment.first.id, + gross_amount: 100, + fee_total: -33, + net_amount: 67, + towards: "blah", + kind: "kind", + donation_id: 555, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + refund_total: 0, + date: date, + created_at: Time.now, + updated_at: Time.now, + search_vectors: nil}.with_indifferent_access + + expect(finished_result["payment"].attributes).to eq common_payment_expected expect(Payment.first.attributes).to eq common_payment_expected expect(Payment.count).to eq 1 end end end - describe 'charge when customer belongs to us' do - before(:each) do - nonprofit.stripe_account_id = Stripe::Account.create['id'] + describe "charge when customer belongs to us" do + before do + nonprofit.stripe_account_id = Stripe::Account.create["id"] nonprofit.save! - card.stripe_customer_id = 'some other id' + card.stripe_customer_id = "some other id" cust = Stripe::Customer.create - card.stripe_customer_id = cust['id'] + card.stripe_customer_id = cust["id"] card.save! new_cust = Stripe::Customer.create - card_for_other_supporter.stripe_customer_id = new_cust['id'] + card_for_other_supporter.stripe_customer_id = new_cust["id"] card_for_other_supporter.save! # StripeMockHelper.prepare_error(Stripe::StripeError.new("chaos"), :get_customer) end def create_expected_charge_args(expected_card) - [{ application_fee: 33, - customer: expected_card.stripe_customer_id, - amount: 100, - currency: 'usd', - description: 'our statement<> blah-no-way', - statement_descriptor: 'our statement blah-n', - metadata: nil, - destination: nonprofit.stripe_account_id }, {}] + [{application_fee: 33, + customer: expected_card.stripe_customer_id, + amount: 100, + currency: "usd", + description: "our statement<> blah-no-way", + statement_descriptor: "our statement blah-n", + metadata: nil, + destination: nonprofit.stripe_account_id}, {}] end - it 'handles card error' do + it "handles card error" do expect(Stripe::Charge).to receive(:create).with(*create_expected_charge_args(card)).and_wrap_original { |m, *args| m.call(*args) } StripeMockHelper.prepare_card_error(:card_declined) finished_result = InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - statement: 'our statement<> blah-no-way') + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + statement: "our statement<> blah-no-way") - common_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: 'failed', failure_message: 'There was an error with your card: The card was declined', created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: "failed", failure_message: "There was an error with your card: The card was declined", created_at: Time.now, updated_at: Time.now, disbursed: nil} result_expected = common_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: nil, supporter_id: supporter.id, ticket_id: nil, payment_id: nil, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_expected + expect(finished_result["charge"].attributes).to eq result_expected expect(Charge.first.attributes).to eq result_expected expect(Payment).to_not be_exists end - it 'handles general Stripe error' do + it "handles general Stripe error" do expect(Stripe::Charge).to receive(:create).with(*create_expected_charge_args(card)).and_wrap_original { |m, *args| m.call(*args) } - StripeMockHelper.prepare_error(Stripe::StripeError.new('blah'), :new_charge) + StripeMockHelper.prepare_error(Stripe::StripeError.new("blah"), :new_charge) finished_result = InsertCharge.with_stripe(amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: card.id, - statement: 'our statement<> blah-no-way') + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: card.id, + statement: "our statement<> blah-no-way") - common_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: 'failed', failure_message: "We're sorry, but something went wrong. We've been notified about this issue.", created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: nil, status: "failed", failure_message: "We're sorry, but something went wrong. We've been notified about this issue.", created_at: Time.now, updated_at: Time.now, disbursed: nil} result_expected = common_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: nil, supporter_id: supporter.id, ticket_id: nil, payment_id: nil, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_expected + expect(finished_result["charge"].attributes).to eq result_expected expect(Charge.first.attributes).to eq result_expected expect(Payment).to_not be_exists end - describe 'input success' do - let (:date) { Time.new(2002, 10, 31) } + describe "input success" do + let(:date) { Time.new(2002, 10, 31) } - it 'saves the payment and updates the charge' do + it "saves the payment and updates the charge" do saves_the_payment_updates_the_charge(card) end - it 'saves the payment and updates the charge, if old rd and using wrong card' do + it "saves the payment and updates the charge, if old rd and using wrong card" do saves_the_payment_updates_the_charge(card_for_other_supporter, true) end - it 'saves the payment and updates the charge with passed date' do + it "saves the payment and updates the charge with passed date" do saves_the_payment_and_updates_the_charge_with_passed_date(card) end - it 'saves the payment and updates the charge with passed date, if old rd and using wrong card' do + it "saves the payment and updates the charge with passed date, if old rd and using wrong card" do saves_the_payment_and_updates_the_charge_with_passed_date(card, true) end def insert_charge_input(expected_card, pass_old_donation = nil, pass_date = nil) - inner = { amount: 100, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - card_id: expected_card.id, - donation_id: 555, - towards: 'blah', - kind: 'kind', - statement: 'our statement<> blah-no-way' } + inner = {amount: 100, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + card_id: expected_card.id, + donation_id: 555, + towards: "blah", + kind: "kind", + statement: "our statement<> blah-no-way"} inner = inner.merge(old_donation: true) if pass_old_donation @@ -422,36 +425,36 @@ def saves_the_payment_updates_the_charge(expected_card, pass_old_donation = nil) stripe_charge_id = nil expect(Stripe::Charge).to receive(:create).with(*create_expected_charge_args(expected_card)).and_wrap_original { |m, *args| a = m.call(*args) - stripe_charge_id = a['id'] + stripe_charge_id = a["id"] a } finished_result = InsertCharge.with_stripe(insert_charge_input(expected_card, pass_old_donation)) - common_charge_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: 'pending', failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_charge_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: "pending", failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil} result_charge_expected = common_charge_expected.merge(card_id: expected_card.id, nonprofit_id: nonprofit.id, donation_id: 555, supporter_id: supporter.id, ticket_id: nil, payment_id: Payment.first.id, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_charge_expected + expect(finished_result["charge"].attributes).to eq result_charge_expected expect(Charge.first.attributes).to eq result_charge_expected expect(Charge.count).to eq 1 - common_payment_expected = { id: Payment.first.id, - gross_amount: 100, - fee_total: -33, - net_amount: 67, - towards: 'blah', - kind: 'kind', - donation_id: 555, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - refund_total: 0, - date: Time.now, - created_at: Time.now, - updated_at: Time.now, - search_vectors: nil }.with_indifferent_access - - expect(finished_result['payment'].attributes).to eq common_payment_expected + common_payment_expected = {id: Payment.first.id, + gross_amount: 100, + fee_total: -33, + net_amount: 67, + towards: "blah", + kind: "kind", + donation_id: 555, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + refund_total: 0, + date: Time.now, + created_at: Time.now, + updated_at: Time.now, + search_vectors: nil}.with_indifferent_access + + expect(finished_result["payment"].attributes).to eq common_payment_expected expect(Payment.first.attributes).to eq common_payment_expected expect(Payment.count).to eq 1 end @@ -460,36 +463,36 @@ def saves_the_payment_and_updates_the_charge_with_passed_date(expected_card, pas stripe_charge_id = nil expect(Stripe::Charge).to receive(:create).with(*create_expected_charge_args(expected_card)).and_wrap_original { |m, *args| a = m.call(*args) - stripe_charge_id = a['id'] + stripe_charge_id = a["id"] a } finished_result = InsertCharge.with_stripe(insert_charge_input(expected_card, pass_old_donation, true)) - common_charge_expected = { id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: 'pending', failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil } + common_charge_expected = {id: Charge.first.id, amount: 100, fee: 33, stripe_charge_id: stripe_charge_id, status: "pending", failure_message: nil, created_at: Time.now, updated_at: Time.now, disbursed: nil} result_charge_expected = common_charge_expected.merge(card_id: card.id, nonprofit_id: nonprofit.id, donation_id: 555, supporter_id: supporter.id, ticket_id: nil, payment_id: Payment.first.id, profile_id: nil, direct_debit_detail_id: nil).with_indifferent_access - expect(finished_result['charge'].attributes).to eq result_charge_expected + expect(finished_result["charge"].attributes).to eq result_charge_expected expect(Charge.first.attributes).to eq result_charge_expected expect(Charge.count).to eq 1 - common_payment_expected = { id: Payment.first.id, - gross_amount: 100, - fee_total: -33, - net_amount: 67, - towards: 'blah', - kind: 'kind', - donation_id: 555, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - refund_total: 0, - date: date, - created_at: Time.now, - updated_at: Time.now, - search_vectors: nil }.with_indifferent_access - - expect(finished_result['payment'].attributes).to eq common_payment_expected + common_payment_expected = {id: Payment.first.id, + gross_amount: 100, + fee_total: -33, + net_amount: 67, + towards: "blah", + kind: "kind", + donation_id: 555, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + refund_total: 0, + date: date, + created_at: Time.now, + updated_at: Time.now, + search_vectors: nil}.with_indifferent_access + + expect(finished_result["payment"].attributes).to eq common_payment_expected expect(Payment.first.attributes).to eq common_payment_expected expect(Payment.count).to eq 1 end diff --git a/spec/legacy_lib/insert/insert_custom_field_joins_spec.rb b/spec/legacy_lib/insert/insert_custom_field_joins_spec.rb index 1ad658b2e3..182cd73971 100644 --- a/spec/legacy_lib/insert/insert_custom_field_joins_spec.rb +++ b/spec/legacy_lib/insert/insert_custom_field_joins_spec.rb @@ -2,61 +2,61 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertCustomFieldJoins do - describe '.find_or_create' do + describe ".find_or_create" do let(:nonprofit) { force_create(:nm_justice) } let(:other_nonprofit) { force_create(:fv_poverty) } let(:supporter) { force_create(:supporter, nonprofit: nonprofit) } let(:other_supporter) { force_create(:supporter, nonprofit: other_nonprofit) } - let(:initial_custom_field_definition) { force_create(:custom_field_definition, nonprofit: nonprofit, name: 'CFM Name') } + let(:initial_custom_field_definition) { force_create(:custom_field_definition, nonprofit: nonprofit, name: "CFM Name") } - describe 'param validation' do - it 'basic validation' do + describe "param validation" do + it "basic validation" do expect { InsertCustomFieldJoins.find_or_create(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :np_id, name: :required }, - { key: :np_id, name: :is_integer }, - { key: :supporter_ids, name: :required }, - { key: :supporter_ids, name: :is_array }, - { key: :supporter_ids, name: :min_length }, - { key: :field_data, name: :required }, - { key: :field_data, name: :is_array }, - { key: :field_data, name: :min_length } - ]) + {key: :np_id, name: :required}, + {key: :np_id, name: :is_integer}, + {key: :supporter_ids, name: :required}, + {key: :supporter_ids, name: :is_array}, + {key: :supporter_ids, name: :min_length}, + {key: :field_data, name: :required}, + {key: :field_data, name: :is_array}, + {key: :field_data, name: :min_length} + ]) end) end - it 'validate nonprofit existence' do + it "validate nonprofit existence" do expect { InsertCustomFieldJoins.find_or_create(5, [555], [[1, 1]]) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :np_id } - ]) + {key: :np_id} + ]) - expect(error.message).to eq '5 is not a valid non-profit' + expect(error.message).to eq "5 is not a valid non-profit" end) end - it 'validate supporter in nonprofit' do + it "validate supporter in nonprofit" do expect { InsertCustomFieldJoins.find_or_create(nonprofit.id, [other_supporter.id], [[1, 1]]) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :supporter_ids } - ]) + {key: :supporter_ids} + ]) expect(error.message).to eq "#{other_supporter.id} is not a valid supporter for nonprofit #{nonprofit.id}" end) end end - it 'run insert' do - new_cf_name = 'new cf name' - new_cf_value = 'value' - old_cf_value = 'old_cf_value' + it "run insert" do + new_cf_name = "new cf name" + new_cf_value = "value" + old_cf_value = "old_cf_value" expect(InsertCustomFieldJoins).to receive(:in_bulk) do |np_id, supporters_id, field_data| expect(np_id).to eq nonprofit.id expect(supporters_id).to eq [supporter.id] @@ -64,66 +64,66 @@ expect(field_data).to include(custom_field_definition_id: initial_custom_field_definition.id, value: old_cf_value) expect(field_data).to include(custom_field_definition_id: CustomFieldDefinition.where(name: new_cf_name).first.id, value: new_cf_value) end - result = InsertCustomFieldJoins.find_or_create(nonprofit.id, [supporter.id], [ - [ - initial_custom_field_definition.name, - old_cf_value - ], - [ - new_cf_name, - new_cf_value - ] - ]) + InsertCustomFieldJoins.find_or_create(nonprofit.id, [supporter.id], [ + [ + initial_custom_field_definition.name, + old_cf_value + ], + [ + new_cf_name, + new_cf_value + ] + ]) expect(CustomFieldDefinition.count).to eq 2 end end - describe '.in_bulk' do - context 'parameter validation' do - it 'should validate parameters' do + describe ".in_bulk" do + context "parameter validation" do + it "should validate parameters" do response = InsertCustomFieldJoins.in_bulk(nil, nil, nil) errors = response[:json][:errors] expect(errors.length).to eq(6) expect(response[:status]).to eq :unprocessable_entity expect_validation_errors(errors, [ - { key: :np_id, name: :required }, - { key: :np_id, name: :is_integer }, - { key: :supporter_ids, name: :required }, - { key: :supporter_ids, name: :is_array }, - { key: :field_data, name: :is_array }, - { key: :field_data, name: :required } - ]) + {key: :np_id, name: :required}, + {key: :np_id, name: :is_integer}, + {key: :supporter_ids, name: :required}, + {key: :supporter_ids, name: :is_array}, + {key: :field_data, name: :is_array}, + {key: :field_data, name: :required} + ]) end - context 'requiring db' do - before(:each) do + context "requiring db" do + before do @nonprofit = force_create(:nm_justice) @bad_nonprofit = force_create(:fv_poverty, id: 50) end - it 'nonprofit must be valid' do + + it "nonprofit must be valid" do response = InsertCustomFieldJoins.in_bulk(@nonprofit.id + 1, [], []) expect(response[:status]).to eq :unprocessable_entity expect(response[:json][:error]).to include("Nonprofit #{@nonprofit.id + 1} is not valid") end - it 'supporters if empty should do nothing' do + it "supporters if empty should do nothing" do response = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [], []) expect(response).to eq(successful_json(0, 0)) end - it 'supporters if empty should do nothing' do + it "supporters if empty should do nothing" do response = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [50], []) expect(response).to eq(successful_json(0, 0)) end end end - context 'main testing' do - before(:each) do + context "main testing" do + before do @nonprofit = force_create(:nm_justice) @other_nonprofit = force_create(:fv_poverty) @random_supporter = create(:supporter, nonprofit: @other_nonprofit) - @delete_cfm = [20, 40, 60] @add_cfm = [25, 35] @@ -161,59 +161,59 @@ end end - it 'invalid nonprofit-supporter combo returns okay' do + it "invalid nonprofit-supporter combo returns okay" do results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [@supporters[:supporter_from_other_np][:entity].id], []) expect(results).to eq(successful_json(0, 0)) end - it 'strips cfms which dont belong to nonprofit' do + it "strips cfms which dont belong to nonprofit" do results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [@supporters[:np_supporter_with_add][:entity].id], - create_cfm_data([100], [150])) + create_cfm_data([100], [150])) expect(results).to eq(successful_json(0, 0)) - expect(CustomFieldJoin.where('supporter_id = ? and custom_field_definition_id = ?', @supporters[:np_supporter_with_add][:entity].id, 100).count).to eq 0 + expect(CustomFieldJoin.where("supporter_id = ? and custom_field_definition_id = ?", @supporters[:np_supporter_with_add][:entity].id, 100).count).to eq 0 end - it 'delete' do + it "delete" do expect(CustomFieldJoin.count).to eq 13 @supporters[:np_supporter_with_some_of_both][:entity].id - results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, - [@supporters[:np_supporter_with_some_of_both][:entity].id, @supporters[:np_supporter_with_cfms_to_delete][:entity].id, @supporters[:np_supporter_with_add][:entity].id, @supporters[:supporter_from_other_np][:entity].id, @supporters[:np_supporter_with_no_changes][:entity].id], - create_cfm_data(@add_cfm, @delete_cfm)) + InsertCustomFieldJoins.in_bulk(@nonprofit.id, + [@supporters[:np_supporter_with_some_of_both][:entity].id, @supporters[:np_supporter_with_cfms_to_delete][:entity].id, @supporters[:np_supporter_with_add][:entity].id, @supporters[:supporter_from_other_np][:entity].id, @supporters[:np_supporter_with_no_changes][:entity].id], + create_cfm_data(@add_cfm, @delete_cfm)) - expect(CustomFieldJoin.where('supporter_id = ? ', @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 + expect(CustomFieldJoin.where("supporter_id = ? ", @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 - expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 + expect(CustomFieldJoin.where("supporter_id = ?", @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 - expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_cfms_to_delete][:entity].id).count).to eq 4 + expect(CustomFieldJoin.where("supporter_id = ?", @supporters[:np_supporter_with_cfms_to_delete][:entity].id).count).to eq 4 - expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:supporter_from_other_np][:entity].id).count).to eq 3 + expect(CustomFieldJoin.where("supporter_id = ?", @supporters[:supporter_from_other_np][:entity].id).count).to eq 3 - expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_no_changes][:entity].id).count).to eq 2 + expect(CustomFieldJoin.where("supporter_id = ?", @supporters[:np_supporter_with_no_changes][:entity].id).count).to eq 2 expect(CustomFieldJoin.count).to eq 16 end - it 'id, updated_at, created_at changes are stripped' do + it "id, updated_at, created_at changes are stripped" do invalid_id = 10_000_000 Timecop.freeze(2020, 9, 1, 12, 0, 0) do results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, - [@supporters[:np_supporter_with_add][:entity].id], - [{ custom_field_definition_id: 25, value: 'CFM value 25', id: invalid_id, created_at: Time.now.ago(3000), updated_at: Time.now.ago(2999) }]) - expected = { custom_field_definition_id: 25, value: 'CFM value 25', created_at: Time.now, updated_at: Time.now, supporter_id: @supporters[:np_supporter_with_add][:entity].id }.with_indifferent_access + [@supporters[:np_supporter_with_add][:entity].id], + [{custom_field_definition_id: 25, value: "CFM value 25", id: invalid_id, created_at: Time.now.ago(3000), updated_at: Time.now.ago(2999)}]) + expected = {custom_field_definition_id: 25, value: "CFM value 25", created_at: Time.now, updated_at: Time.now, supporter_id: @supporters[:np_supporter_with_add][:entity].id}.with_indifferent_access expect(results).to eq(successful_json(1, 0)) - result_tag = @supporters[:np_supporter_with_add][:entity].custom_field_joins.where('custom_field_definition_id = ?', 25).first + result_tag = @supporters[:np_supporter_with_add][:entity].custom_field_joins.where("custom_field_definition_id = ?", 25).first - expect(result_tag.attributes.with_indifferent_access.reject { |k, _| k == 'id' }).to eq(expected) + expect(result_tag.attributes.with_indifferent_access.reject { |k, _| k == "id" }).to eq(expected) expect(result_tag.attributes[:id]).to_not eq invalid_id end end - it 'add_to_one' do + it "add_to_one" do expect(CustomFieldJoin.count).to eq 13 np_supporter_with_add_cfms = @supporters[:np_supporter_with_add][:entity].custom_field_joins.to_a @@ -222,39 +222,39 @@ Timecop.travel(20) do results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, - [ - @supporters[:np_supporter_with_add][:entity].id, # add 2 - @supporters[:np_supporter_with_no_changes][:entity], # update 2 - @supporters[:np_supporter_with_some_of_both][:entity].id - ], # add 2, delete 1 - create_cfm_data(@add_cfm, @delete_cfm)) + [ + @supporters[:np_supporter_with_add][:entity].id, # add 2 + @supporters[:np_supporter_with_no_changes][:entity], # update 2 + @supporters[:np_supporter_with_some_of_both][:entity].id + ], # add 2, delete 1 + create_cfm_data(@add_cfm, @delete_cfm)) expect(results).to eq(successful_json(6, 1)) expect(@supporters[:np_supporter_with_no_changes][:entity].custom_field_joins).to match_array(np_supporter_with_no_changes_cfms) - expect(CustomFieldJoin.where('supporter_id = ? ', @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 + expect(CustomFieldJoin.where("supporter_id = ? ", @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 - original_db_pairs = get_original_and_db(np_supporter_with_add_cfms, CustomFieldJoin.where('supporter_id = ? and custom_field_definition_id in (?)', - @supporters[:np_supporter_with_add][:entity].id, - @supporters[:np_supporter_with_add][:cfm_ids]).pluck(:id)) + original_db_pairs = get_original_and_db(np_supporter_with_add_cfms, CustomFieldJoin.where("supporter_id = ? and custom_field_definition_id in (?)", + @supporters[:np_supporter_with_add][:entity].id, + @supporters[:np_supporter_with_add][:cfm_ids]).pluck(:id)) original_db_pairs.each do |orig, db| expect(db.attributes.length).to eq(orig.attributes.length) expect(db.attributes).to eq(orig.attributes) end - expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 + expect(CustomFieldJoin.where("supporter_id = ?", @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 - original_db_pairs = get_original_and_db(np_supporter_with_some_of_both_cfms, CustomFieldJoin.where('supporter_id = ? and custom_field_definition_id in (?)', - @supporters[:np_supporter_with_some_of_both][:entity].id, - [35]).pluck(:id)) + original_db_pairs = get_original_and_db(np_supporter_with_some_of_both_cfms, CustomFieldJoin.where("supporter_id = ? and custom_field_definition_id in (?)", + @supporters[:np_supporter_with_some_of_both][:entity].id, + [35]).pluck(:id)) skip_attribs = %w[updated_at value] original_db_pairs.each do |orig, db| expect(db.attributes.length).to eq(orig.attributes.length) expect(db.attributes.reject { |key, _value| skip_attribs.include?(key) }).to eq(orig.attributes.reject { |key, _value| skip_attribs.include?(key) }) - expect(db.attributes['updated_at']).to be > orig.attributes['updated_at'] - expect(db.attributes['value']).to eq 'CFM value 35' + expect(db.attributes["updated_at"]).to be > orig.attributes["updated_at"] + expect(db.attributes["value"]).to eq "CFM value 35" end expect(CustomFieldJoin.count).to eq 15 @@ -264,16 +264,16 @@ end def successful_json(inserted, deleted) - { json: { inserted_count: inserted, removed_count: deleted }, status: :ok } + {json: {inserted_count: inserted, removed_count: deleted}, status: :ok} end def create_cfm_data(cfm_to_add = [], cfm_to_delete = []) use_nil = true - cfm_to_add.map { |cfm| { custom_field_definition_id: cfm, value: "CFM value #{cfm}" } } + cfm_to_delete.map do |cfm| - value = use_nil ? nil : '' - use_nil = !use_nil - { custom_field_definition_id: cfm, value: value } - end + cfm_to_add.map { |cfm| {custom_field_definition_id: cfm, value: "CFM value #{cfm}"} } + cfm_to_delete.map do |cfm| + value = use_nil ? nil : "" + use_nil = !use_nil + {custom_field_definition_id: cfm, value: value} + end end def get_original_and_db(original_items, ids_to_verify) diff --git a/spec/legacy_lib/insert/insert_disputes_spec.rb b/spec/legacy_lib/insert/insert_disputes_spec.rb index dfe71db95a..a4d562ea63 100644 --- a/spec/legacy_lib/insert/insert_disputes_spec.rb +++ b/spec/legacy_lib/insert/insert_disputes_spec.rb @@ -2,14 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertDisputes, pending: true do before(:all) do # @data = PsqlFixtures.init end - describe '.create_record' do + describe ".create_record" do before(:all) do # @ch = @data['recurring_donation']['charge'] # @payment = @data['recurring_donation']['payment'] @@ -17,29 +17,29 @@ # @result = InsertDisputes.create_record(@ch['stripe_charge_id'], @dispute_id) end - it 'raises an error when the stripe charge id not found' do - expect { InsertDisputes.create_record('x', 'y') }.to raise_exception(ArgumentError) + it "raises an error when the stripe charge id not found" do + expect { InsertDisputes.create_record("x", "y") }.to raise_exception(ArgumentError) raise end - it 'creates a valid payment record' do - expect(@result[:payment]['fee_total']).to eq(-(@payment['fee_total']) - 1500) - expect(@result[:payment]['supporter_id']).to eq(@ch['supporter_id']) - expect(@result[:payment]['kind']).to eq('Dispute') - expect(@result[:payment]['nonprofit_id']).to eq(@ch['nonprofit_id']) - expect(@result[:payment]['gross_amount']).to eq(-@ch['amount']) - expect(@result[:payment]['net_amount']).to eq(-(@payment['gross_amount']) - @payment['fee_total'] - 1500) - expect(@result[:payment]['donation_id']).to be_present + it "creates a valid payment record" do + expect(@result[:payment]["fee_total"]).to eq(-@payment["fee_total"] - 1500) + expect(@result[:payment]["supporter_id"]).to eq(@ch["supporter_id"]) + expect(@result[:payment]["kind"]).to eq("Dispute") + expect(@result[:payment]["nonprofit_id"]).to eq(@ch["nonprofit_id"]) + expect(@result[:payment]["gross_amount"]).to eq(-@ch["amount"]) + expect(@result[:payment]["net_amount"]).to eq(-@payment["gross_amount"] - @payment["fee_total"] - 1500) + expect(@result[:payment]["donation_id"]).to be_present raise end - it 'creates a valid dispute record' do - expect(@result[:dispute]['gross_amount']).to eq(@payment['gross_amount']) - expect(@result[:dispute]['status']).to eq('needs_response') - expect(@result[:dispute]['charge_id']).to be_present - expect(@result[:dispute]['payment_id']).to eq(@result[:payment]['id']) - expect(@result[:dispute]['reason']).to eq('unrecognized') - expect(@result[:dispute]['stripe_dispute_id']).to eq(@dispute_id) + it "creates a valid dispute record" do + expect(@result[:dispute]["gross_amount"]).to eq(@payment["gross_amount"]) + expect(@result[:dispute]["status"]).to eq("needs_response") + expect(@result[:dispute]["charge_id"]).to be_present + expect(@result[:dispute]["payment_id"]).to eq(@result[:payment]["id"]) + expect(@result[:dispute]["reason"]).to eq("unrecognized") + expect(@result[:dispute]["stripe_dispute_id"]).to eq(@dispute_id) raise end end diff --git a/spec/legacy_lib/insert/insert_donation_spec.rb b/spec/legacy_lib/insert/insert_donation_spec.rb index 98ac3512b4..447ff0cc49 100644 --- a/spec/legacy_lib/insert/insert_donation_spec.rb +++ b/spec/legacy_lib/insert/insert_donation_spec.rb @@ -4,1212 +4,1212 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # rubocop:disable RSpec/MessageSpies, RSpec/NamedSubject, RSpec/MultipleExpectations,RSpec/MultipleMemoizedHelpers, RSpec/ExpectInHook -require 'rails_helper' +require "rails_helper" RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = nil describe InsertDonation do - describe '.with_stripe' do - before do - Houdini.payment_providers.stripe.connect = true - end - - include_context :shared_rd_donation_value_context - - describe 'param validation' do - before do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:transaction_created, any_args) - end - - it 'does basic validation' do # rubocop:disable RSpec/NoExpectationExample - validation_basic_validation do - described_class.with_stripe(designation: 34_124, dedication: 35_141, event_id: 'bad', campaign_id: 'bad') - end - end - - it 'errors out if token is invalid' do # rubocop:disable RSpec/NoExpectationExample - validation_invalid_token do - described_class.with_stripe(amount: 1, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) - end - end - - it 'errors out if token is unauthorized' do # rubocop:disable RSpec/NoExpectationExample - validation_unauthorized do - described_class.with_stripe(amount: charge_amount, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) - end - end - - it 'errors out if token is expired' do # rubocop:disable RSpec/NoExpectationExample - validation_expired do - described_class.with_stripe(amount: charge_amount, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) - end - end - - describe 'errors during find if' do - it 'supporter is invalid' do # rubocop:disable RSpec/NoExpectationExample - find_error_supporter do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: 55_555, - token: source_token.token) - end - end - - it 'nonprofit is invalid' do # rubocop:disable RSpec/NoExpectationExample - find_error_nonprofit do - described_class.with_stripe(amount: charge_amount, nonprofit_id: 55_555, supporter_id: supporter.id, - token: source_token.token) - end - end - - it 'campaign is invalid' do # rubocop:disable RSpec/NoExpectationExample - find_error_campaign do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, campaign_id: 5555) - end - end - - it 'event is invalid' do # rubocop:disable RSpec/NoExpectationExample - find_error_event do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, event_id: 5555) - end - end - - it 'profile is invalid' do # rubocop:disable RSpec/NoExpectationExample - find_error_profile do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, profile_id: 5555) - end - end - end - - describe 'errors during relationship comparison if' do - it 'supporter is deleted' do # rubocop:disable RSpec/NoExpectationExample - validation_supporter_deleted do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token) - end - end - - it 'event is deleted' do # rubocop:disable RSpec/NoExpectationExample - validation_event_deleted do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, event_id: event.id) - end - end - - it 'campaign is deleted' do # rubocop:disable RSpec/NoExpectationExample - validation_campaign_deleted do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, campaign_id: campaign.id) - end - end - - it 'supporter doesnt belong to nonprofit' do # rubocop:disable RSpec/NoExpectationExample - validation_supporter_not_with_nonprofit do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, - supporter_id: other_nonprofit_supporter.id, token: source_token.token) - end - end - - it 'campaign doesnt belong to nonprofit' do # rubocop:disable RSpec/NoExpectationExample - validation_campaign_not_with_nonprofit do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, campaign_id: other_campaign.id) - end - end - - it 'event doesnt belong to nonprofit' do # rubocop:disable RSpec/NoExpectationExample - validation_event_not_with_nonprofit do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token, event_id: other_event.id) - end - end - - it 'card doesnt belong to supporter' do # rubocop:disable RSpec/NoExpectationExample - validation_card_not_with_supporter do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: other_source_token.token) - end - end - end - end - - it 'charge returns failed' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:transaction_created, any_args) - handle_charge_failed do - described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - token: source_token.token) - end - end - - describe 'success' do - before do - before_each_success - allow(Houdini.event_publisher).to receive(:announce) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - end - - it 'process event donation' do # rubocop:disable RSpec/NoExpectationExample - process_event_donation do - described_class.with_stripe( - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: source_token.token, - event_id: event.id, - date: 1.day.from_now.to_s, - dedication: { - 'type' => 'honor', - 'name' => 'a name' - }, - designation: 'designation' - ) - end - end - - it 'process campaign donation' do - expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) - process_campaign_donation do - described_class.with_stripe( - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: source_token.token, - campaign_id: campaign.id, - date: 1.day.from_now.to_s, - dedication: { 'type' => 'honor', 'name' => 'a name' }, - designation: 'designation' - ) - end - end - - it 'processes general donation' do # rubocop:disable RSpec/NoExpectationExample - process_general_donation do - described_class.with_stripe( - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: source_token.token, - profile_id: profile.id, - date: 1.day.from_now.to_s, - dedication: { 'type' => 'honor', 'name' => 'a name' }, - designation: 'designation' - ) - end - end - end - - describe 'object event firing' do - # all the same for all the types of donations; see #603 - let(:created_time) { Time.current } - let(:common_builder) do - { 'supporter' => supporter.id, - 'nonprofit' => nonprofit.id } - end - - let(:common_builder_expanded) do - { - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded - } - end - - let(:common_builder_with_trx_id) do - common_builder.merge( - { - 'transaction' => match_houid('trx') - } - ) - end - - let(:common_builder_with_trx) do - common_builder.merge( - { - 'transaction' => transaction_builder - } - ) - end - - let(:np_builder_expanded) do - { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - } - end - - let(:supporter_builder_expanded) do - supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - end - - let(:transaction_builder) do - common_builder.merge( - { - 'id' => match_houid('trx'), - 'object' => 'transaction', - 'amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'created' => created_time.to_i, - 'subtransaction' => stripe_transaction_id_only, - 'payments' => [stripe_transaction_charge_id_only], - 'transaction_assignments' => [donation_id_only] - } - ) - end - - let(:transaction_builder_expanded) do - transaction_builder.merge( - common_builder_expanded, - { - 'subtransaction' => stripe_transaction_builder, - 'payments' => [stripe_transaction_charge_builder], - 'transaction_assignments' => [donation_builder] - } - ) - end - - let(:stripe_transaction_id_only) do - { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - } - end - - let(:stripe_transaction_builder) do - stripe_transaction_id_only.merge( - common_builder_with_trx_id, - { - 'initial_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - - 'net_amount' => { - 'cents' => 67, - 'currency' => 'usd' - }, - - 'payments' => [stripe_transaction_charge_id_only], - 'created' => created_time.to_i - } - ) - end - - let(:stripe_transaction_builder_expanded) do - stripe_transaction_builder.merge( - common_builder_with_trx, - common_builder_expanded, - { - 'payments' => [stripe_transaction_charge_builder] - } - ) - end - - let(:stripe_transaction_charge_id_only) do - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - } - end - - let(:stripe_transaction_charge_builder) do - stripe_transaction_charge_id_only.merge( - common_builder_with_trx_id, - { - 'gross_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'net_amount' => { - 'cents' => 67, - 'currency' => 'usd' - }, - 'fee_total' => { - 'cents' => -33, - 'currency' => 'usd' - }, - 'subtransaction' => stripe_transaction_id_only, - 'stripe_id' => /test_ch_\d+/, - 'created' => created_time.to_i - } - ) - end - - let(:stripe_transaction_charge_builder_expanded) do - stripe_transaction_charge_builder.merge( - common_builder_with_trx, - common_builder_expanded, - { - 'subtransaction' => stripe_transaction_builder - } - ) - end - - let(:donation_id_only) do - { - 'id' => match_houid('don'), - 'object' => 'donation', - 'type' => 'trx_assignment' - } - end - - let(:donation_builder) do - donation_id_only.merge(common_builder_with_trx_id, { - 'amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'designation' => 'designation', - 'dedication' => { - 'name' => 'a name', - 'type' => 'honor' - } - }) - end - - let(:donation_builder_expanded) do - donation_builder.merge(common_builder_with_trx, common_builder_expanded) - end - - describe 'events donations' do - describe 'general with_stripe create' do - subject do - process_event_donation do - described_class.with_stripe( - { - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - event_id: event.id, - token: source_token.token, - dedication: { 'name' => 'a name', 'type' => 'honor' }, - designation: 'designation' - - }.with_indifferent_access - ) - end - end - - before do - before_each_success - end - - it 'has fired transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :transaction_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'transaction.created', - 'data' => { - 'object' => transaction_builder_expanded - } - } - ) - subject - end - - it 'has fired stripe_transaction_charge.created' do - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_charge_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction_charge.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired payment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :payment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'payment.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired stripe_transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction.created', - 'data' => { - 'object' => stripe_transaction_builder_expanded - } - } - ) - - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired donation.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :donation_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'donation.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired trx_assignment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :trx_assignment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'trx_assignment.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - end - end - - describe 'general donations' do - subject do - process_general_donation do - described_class.with_stripe( - { - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: source_token.token, - profile_id: profile.id, - dedication: { 'name' => 'a name', 'type' => 'honor' }, - designation: 'designation' - - }.with_indifferent_access - ) - end - end - - before do - before_each_success - end - - it 'has fired transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :transaction_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'transaction.created', - 'data' => { - 'object' => transaction_builder_expanded - } - } - ) - subject - end - - it 'has fired stripe_transaction_charge.created' do - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_charge_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction_charge.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired payment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :payment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'payment.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired stripe_transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction.created', - 'data' => { - 'object' => stripe_transaction_builder_expanded - } - } - ) - - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired donation.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :donation_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'donation.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired trx_assignment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :trx_assignment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'trx_assignment.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - end - - describe 'campaign donations' do - subject do - expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) - process_campaign_donation do - described_class.with_stripe( - { - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: source_token.token, - dedication: { 'name' => 'a name', 'type' => 'honor' }, - designation: 'designation', - campaign_id: campaign.id - }.with_indifferent_access - ) - end - end - - before do - before_each_success - end - - it 'has fired transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :transaction_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'transaction.created', - 'data' => { - 'object' => transaction_builder_expanded - } - } - ) - subject - end - - it 'has fired stripe_transaction_charge.created' do - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_charge_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction_charge.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired payment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :payment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'payment.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired stripe_transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction.created', - 'data' => { - 'object' => stripe_transaction_builder_expanded - } - } - ) - - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired donation.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :donation_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'donation.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired trx_assignment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :trx_assignment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'trx_assignment.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - end - end - end - - describe '#with_sepa' do - include_context :shared_rd_donation_value_context - - describe 'saves donation' do - before do - before_each_sepa_success - end - - it 'process event donation' do # rubocop:disable RSpec/NoExpectationExample - process_event_donation(sepa: true) do - described_class.with_sepa( - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - direct_debit_detail_id: direct_debit_detail.id, - event_id: event.id, - date: 1.day.from_now.to_s, - dedication: { - 'type' => 'honor', - 'name' => 'a name' - }, - designation: 'designation' - ) - end - end - - it 'process campaign donation' do - allow(Houdini.event_publisher).to receive(:announce) - expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) - process_campaign_donation(sepa: true) do - described_class.with_sepa( - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - direct_debit_detail_id: direct_debit_detail.id, - campaign_id: campaign.id, - date: 1.day.from_now.to_s, - dedication: { - 'type' => 'honor', - 'name' => 'a name' - }, - designation: 'designation' - ) - end - end - - it 'processes general donation' do # rubocop:disable RSpec/NoExpectationExample - process_general_donation(sepa: true) do - described_class.with_sepa( - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - direct_debit_detail_id: direct_debit_detail.id, - profile_id: profile.id, - date: 1.day.from_now.to_s, - dedication: { - 'type' => 'honor', - 'name' => 'a name' - }, - designation: 'designation' - ) - end - end - end - end - - describe '.offsite' do - include_context :shared_rd_donation_value_context - describe 'failures' do - before do - expect(Houdini.event_publisher).to_not receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:offline_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:offline_transaction_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to_not receive(:announce).with(:transaction_created, any_args) - end - - it 'fails if amount is missing' do - expect do - described_class.offsite( - { - nonprofit_id: nonprofit.id, - supporter_id: supporter.id - }.with_indifferent_access - ) - end.to raise_error(ParamValidation::ValidationError) - end - end - - describe 'success' do - before do - allow(Houdini.event_publisher).to receive(:announce) - end - - describe 'general offsite create' do - subject do - described_class.offsite({ amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, - date: created_time.to_s }.with_indifferent_access) - end - - let(:created_time) { 1.day.from_now } - let(:common_builder) do - { 'supporter' => supporter.id, - 'nonprofit' => nonprofit.id } - end - - let(:common_builder_expanded) do - { - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded - } - end - - let(:common_builder_with_trx_id) do - common_builder.merge( - { - 'transaction' => match_houid('trx') - } - ) - end - - let(:common_builder_with_trx) do - common_builder.merge( - { - 'transaction' => transaction_builder - } - ) - end - - let(:np_builder_expanded) do - { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - } - end - - let(:supporter_builder_expanded) do - supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - end - - let(:transaction_builder) do - common_builder.merge( - { - 'id' => match_houid('trx'), - 'object' => 'transaction', - 'amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'created' => created_time.to_i, - 'subtransaction' => offline_transaction_id_only, - 'payments' => [offline_transaction_charge_id_only], - 'transaction_assignments' => [donation_id_only] - } - ) - end - - let(:transaction_builder_expanded) do - transaction_builder.merge( - common_builder_expanded, - { - 'subtransaction' => offline_transaction_builder, - 'payments' => [offline_transaction_charge_builder], - 'transaction_assignments' => [donation_builder] - } - ) - end - - let(:offline_transaction_id_only) do - { - 'id' => match_houid('offlinetrx'), - 'object' => 'offline_transaction', - 'type' => 'subtransaction' - } - end - - let(:offline_transaction_builder) do - offline_transaction_id_only.merge( - common_builder_with_trx_id, - { - 'initial_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - - 'net_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - - 'payments' => [offline_transaction_charge_id_only], - 'created' => created_time.to_i - } - ) - end - - let(:offline_transaction_builder_expanded) do - offline_transaction_builder.merge( - common_builder_with_trx, - common_builder_expanded, - { - 'payments' => [offline_transaction_charge_builder] - } - ) - end - - let(:offline_transaction_charge_id_only) do - { - 'id' => match_houid('offtrxchrg'), - 'object' => 'offline_transaction_charge', - 'type' => 'payment' - } - end - - let(:offline_transaction_charge_builder) do - offline_transaction_charge_id_only.merge( - common_builder_with_trx_id, - { - 'gross_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'net_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'fee_total' => { - 'cents' => 0, - 'currency' => 'usd' - }, - 'subtransaction' => offline_transaction_id_only, - 'created' => created_time.to_i - } - ) - end - - let(:offline_transaction_charge_builder_expanded) do - offline_transaction_charge_builder.merge( - common_builder_with_trx, - common_builder_expanded, - { - 'subtransaction' => offline_transaction_builder - } - ) - end - - let(:donation_id_only) do - { - 'id' => match_houid('don'), - 'object' => 'donation', - 'type' => 'trx_assignment' - } - end - - let(:donation_builder) do - donation_id_only.merge(common_builder_with_trx_id, { - 'amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'designation' => nil - }) - end - - let(:donation_builder_expanded) do - donation_builder.merge(common_builder_with_trx, common_builder_expanded) - end - - describe 'event publishing' do - it 'has fired transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :transaction_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'transaction.created', - 'data' => { - 'object' => transaction_builder_expanded - } - } - ) - subject - end - - it 'has fired offline_transaction_charge.created' do - expect(Houdini.event_publisher).to receive(:announce).with( - :offline_transaction_charge_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'offline_transaction_charge.created', - 'data' => { - 'object' => offline_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired payment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :payment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'payment.created', - 'data' => { - 'object' => offline_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired offline_transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :offline_transaction_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'offline_transaction.created', - 'data' => { - 'object' => offline_transaction_builder_expanded - } - } - ) - - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired donation.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :donation_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'donation.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - - it 'has fired trx_assignment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :trx_assignment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'trx_assignment.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - subject - end - end - end - end - end + describe ".with_stripe" do + before do + Houdini.payment_providers.stripe.connect = true + end + + include_context :shared_rd_donation_value_context + + describe "param validation" do + before do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:transaction_created, any_args) + end + + it "does basic validation" do # rubocop:disable RSpec/NoExpectationExample + validation_basic_validation do + described_class.with_stripe(designation: 34_124, dedication: 35_141, event_id: "bad", campaign_id: "bad") + end + end + + it "errors out if token is invalid" do # rubocop:disable RSpec/NoExpectationExample + validation_invalid_token do + described_class.with_stripe(amount: 1, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) + end + end + + it "errors out if token is unauthorized" do # rubocop:disable RSpec/NoExpectationExample + validation_unauthorized do + described_class.with_stripe(amount: charge_amount, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) + end + end + + it "errors out if token is expired" do # rubocop:disable RSpec/NoExpectationExample + validation_expired do + described_class.with_stripe(amount: charge_amount, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) + end + end + + describe "errors during find if" do + it "supporter is invalid" do # rubocop:disable RSpec/NoExpectationExample + find_error_supporter do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: 55_555, + token: source_token.token) + end + end + + it "nonprofit is invalid" do # rubocop:disable RSpec/NoExpectationExample + find_error_nonprofit do + described_class.with_stripe(amount: charge_amount, nonprofit_id: 55_555, supporter_id: supporter.id, + token: source_token.token) + end + end + + it "campaign is invalid" do # rubocop:disable RSpec/NoExpectationExample + find_error_campaign do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, campaign_id: 5555) + end + end + + it "event is invalid" do # rubocop:disable RSpec/NoExpectationExample + find_error_event do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, event_id: 5555) + end + end + + it "profile is invalid" do # rubocop:disable RSpec/NoExpectationExample + find_error_profile do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, profile_id: 5555) + end + end + end + + describe "errors during relationship comparison if" do + it "supporter is deleted" do # rubocop:disable RSpec/NoExpectationExample + validation_supporter_deleted do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token) + end + end + + it "event is deleted" do # rubocop:disable RSpec/NoExpectationExample + validation_event_deleted do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, event_id: event.id) + end + end + + it "campaign is deleted" do # rubocop:disable RSpec/NoExpectationExample + validation_campaign_deleted do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, campaign_id: campaign.id) + end + end + + it "supporter doesnt belong to nonprofit" do # rubocop:disable RSpec/NoExpectationExample + validation_supporter_not_with_nonprofit do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, + supporter_id: other_nonprofit_supporter.id, token: source_token.token) + end + end + + it "campaign doesnt belong to nonprofit" do # rubocop:disable RSpec/NoExpectationExample + validation_campaign_not_with_nonprofit do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, campaign_id: other_campaign.id) + end + end + + it "event doesnt belong to nonprofit" do # rubocop:disable RSpec/NoExpectationExample + validation_event_not_with_nonprofit do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token, event_id: other_event.id) + end + end + + it "card doesnt belong to supporter" do # rubocop:disable RSpec/NoExpectationExample + validation_card_not_with_supporter do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: other_source_token.token) + end + end + end + end + + it "charge returns failed" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:transaction_created, any_args) + handle_charge_failed do + described_class.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + token: source_token.token) + end + end + + describe "success" do + before do + before_each_success + allow(Houdini.event_publisher).to receive(:announce) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + end + + it "process event donation" do # rubocop:disable RSpec/NoExpectationExample + process_event_donation do + described_class.with_stripe( + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: source_token.token, + event_id: event.id, + date: 1.day.from_now.to_s, + dedication: { + "type" => "honor", + "name" => "a name" + }, + designation: "designation" + ) + end + end + + it "process campaign donation" do + expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) + process_campaign_donation do + described_class.with_stripe( + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: source_token.token, + campaign_id: campaign.id, + date: 1.day.from_now.to_s, + dedication: {"type" => "honor", "name" => "a name"}, + designation: "designation" + ) + end + end + + it "processes general donation" do # rubocop:disable RSpec/NoExpectationExample + process_general_donation do + described_class.with_stripe( + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: source_token.token, + profile_id: profile.id, + date: 1.day.from_now.to_s, + dedication: {"type" => "honor", "name" => "a name"}, + designation: "designation" + ) + end + end + end + + describe "object event firing" do + # all the same for all the types of donations; see #603 + let(:created_time) { Time.current } + let(:common_builder) do + {"supporter" => supporter.id, + "nonprofit" => nonprofit.id} + end + + let(:common_builder_expanded) do + { + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded + } + end + + let(:common_builder_with_trx_id) do + common_builder.merge( + { + "transaction" => match_houid("trx") + } + ) + end + + let(:common_builder_with_trx) do + common_builder.merge( + { + "transaction" => transaction_builder + } + ) + end + + let(:np_builder_expanded) do + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } + end + + let(:supporter_builder_expanded) do + supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + end + + let(:transaction_builder) do + common_builder.merge( + { + "id" => match_houid("trx"), + "object" => "transaction", + "amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "created" => created_time.to_i, + "subtransaction" => stripe_transaction_id_only, + "payments" => [stripe_transaction_charge_id_only], + "transaction_assignments" => [donation_id_only] + } + ) + end + + let(:transaction_builder_expanded) do + transaction_builder.merge( + common_builder_expanded, + { + "subtransaction" => stripe_transaction_builder, + "payments" => [stripe_transaction_charge_builder], + "transaction_assignments" => [donation_builder] + } + ) + end + + let(:stripe_transaction_id_only) do + { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + } + end + + let(:stripe_transaction_builder) do + stripe_transaction_id_only.merge( + common_builder_with_trx_id, + { + "initial_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + + "net_amount" => { + "cents" => 67, + "currency" => "usd" + }, + + "payments" => [stripe_transaction_charge_id_only], + "created" => created_time.to_i + } + ) + end + + let(:stripe_transaction_builder_expanded) do + stripe_transaction_builder.merge( + common_builder_with_trx, + common_builder_expanded, + { + "payments" => [stripe_transaction_charge_builder] + } + ) + end + + let(:stripe_transaction_charge_id_only) do + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + } + end + + let(:stripe_transaction_charge_builder) do + stripe_transaction_charge_id_only.merge( + common_builder_with_trx_id, + { + "gross_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "net_amount" => { + "cents" => 67, + "currency" => "usd" + }, + "fee_total" => { + "cents" => -33, + "currency" => "usd" + }, + "subtransaction" => stripe_transaction_id_only, + "stripe_id" => /test_ch_\d+/, + "created" => created_time.to_i + } + ) + end + + let(:stripe_transaction_charge_builder_expanded) do + stripe_transaction_charge_builder.merge( + common_builder_with_trx, + common_builder_expanded, + { + "subtransaction" => stripe_transaction_builder + } + ) + end + + let(:donation_id_only) do + { + "id" => match_houid("don"), + "object" => "donation", + "type" => "trx_assignment" + } + end + + let(:donation_builder) do + donation_id_only.merge(common_builder_with_trx_id, { + "amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "designation" => "designation", + "dedication" => { + "name" => "a name", + "type" => "honor" + } + }) + end + + let(:donation_builder_expanded) do + donation_builder.merge(common_builder_with_trx, common_builder_expanded) + end + + describe "events donations" do + describe "general with_stripe create" do + subject do + process_event_donation do + described_class.with_stripe( + { + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + event_id: event.id, + token: source_token.token, + dedication: {"name" => "a name", "type" => "honor"}, + designation: "designation" + + }.with_indifferent_access + ) + end + end + + before do + before_each_success + end + + it "has fired transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :transaction_created, { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "transaction.created", + "data" => { + "object" => transaction_builder_expanded + } + } + ) + subject + end + + it "has fired stripe_transaction_charge.created" do + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_charge_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction_charge.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired payment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :payment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "payment.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired stripe_transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction.created", + "data" => { + "object" => stripe_transaction_builder_expanded + } + } + ) + + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired donation.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :donation_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "donation.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired trx_assignment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :trx_assignment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "trx_assignment.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + end + end + + describe "general donations" do + subject do + process_general_donation do + described_class.with_stripe( + { + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: source_token.token, + profile_id: profile.id, + dedication: {"name" => "a name", "type" => "honor"}, + designation: "designation" + + }.with_indifferent_access + ) + end + end + + before do + before_each_success + end + + it "has fired transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :transaction_created, { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "transaction.created", + "data" => { + "object" => transaction_builder_expanded + } + } + ) + subject + end + + it "has fired stripe_transaction_charge.created" do + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_charge_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction_charge.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired payment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :payment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "payment.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired stripe_transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction.created", + "data" => { + "object" => stripe_transaction_builder_expanded + } + } + ) + + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired donation.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :donation_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "donation.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired trx_assignment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :trx_assignment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "trx_assignment.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + end + + describe "campaign donations" do + subject do + expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) + process_campaign_donation do + described_class.with_stripe( + { + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: source_token.token, + dedication: {"name" => "a name", "type" => "honor"}, + designation: "designation", + campaign_id: campaign.id + }.with_indifferent_access + ) + end + end + + before do + before_each_success + end + + it "has fired transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :transaction_created, { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "transaction.created", + "data" => { + "object" => transaction_builder_expanded + } + } + ) + subject + end + + it "has fired stripe_transaction_charge.created" do + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_charge_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction_charge.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired payment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :payment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "payment.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired stripe_transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction.created", + "data" => { + "object" => stripe_transaction_builder_expanded + } + } + ) + + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired donation.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :donation_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "donation.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired trx_assignment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :trx_assignment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "trx_assignment.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + end + end + end + + describe "#with_sepa" do + include_context :shared_rd_donation_value_context + + describe "saves donation" do + before do + before_each_sepa_success + end + + it "process event donation" do # rubocop:disable RSpec/NoExpectationExample + process_event_donation(sepa: true) do + described_class.with_sepa( + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + direct_debit_detail_id: direct_debit_detail.id, + event_id: event.id, + date: 1.day.from_now.to_s, + dedication: { + "type" => "honor", + "name" => "a name" + }, + designation: "designation" + ) + end + end + + it "process campaign donation" do + allow(Houdini.event_publisher).to receive(:announce) + expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) + process_campaign_donation(sepa: true) do + described_class.with_sepa( + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + direct_debit_detail_id: direct_debit_detail.id, + campaign_id: campaign.id, + date: 1.day.from_now.to_s, + dedication: { + "type" => "honor", + "name" => "a name" + }, + designation: "designation" + ) + end + end + + it "processes general donation" do # rubocop:disable RSpec/NoExpectationExample + process_general_donation(sepa: true) do + described_class.with_sepa( + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + direct_debit_detail_id: direct_debit_detail.id, + profile_id: profile.id, + date: 1.day.from_now.to_s, + dedication: { + "type" => "honor", + "name" => "a name" + }, + designation: "designation" + ) + end + end + end + end + + describe ".offsite" do + include_context :shared_rd_donation_value_context + describe "failures" do + before do + expect(Houdini.event_publisher).to_not receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:offline_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:offline_transaction_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to_not receive(:announce).with(:transaction_created, any_args) + end + + it "fails if amount is missing" do + expect do + described_class.offsite( + { + nonprofit_id: nonprofit.id, + supporter_id: supporter.id + }.with_indifferent_access + ) + end.to raise_error(ParamValidation::ValidationError) + end + end + + describe "success" do + before do + allow(Houdini.event_publisher).to receive(:announce) + end + + describe "general offsite create" do + subject do + described_class.offsite({amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, + date: created_time.to_s}.with_indifferent_access) + end + + let(:created_time) { 1.day.from_now } + let(:common_builder) do + {"supporter" => supporter.id, + "nonprofit" => nonprofit.id} + end + + let(:common_builder_expanded) do + { + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded + } + end + + let(:common_builder_with_trx_id) do + common_builder.merge( + { + "transaction" => match_houid("trx") + } + ) + end + + let(:common_builder_with_trx) do + common_builder.merge( + { + "transaction" => transaction_builder + } + ) + end + + let(:np_builder_expanded) do + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } + end + + let(:supporter_builder_expanded) do + supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + end + + let(:transaction_builder) do + common_builder.merge( + { + "id" => match_houid("trx"), + "object" => "transaction", + "amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "created" => created_time.to_i, + "subtransaction" => offline_transaction_id_only, + "payments" => [offline_transaction_charge_id_only], + "transaction_assignments" => [donation_id_only] + } + ) + end + + let(:transaction_builder_expanded) do + transaction_builder.merge( + common_builder_expanded, + { + "subtransaction" => offline_transaction_builder, + "payments" => [offline_transaction_charge_builder], + "transaction_assignments" => [donation_builder] + } + ) + end + + let(:offline_transaction_id_only) do + { + "id" => match_houid("offlinetrx"), + "object" => "offline_transaction", + "type" => "subtransaction" + } + end + + let(:offline_transaction_builder) do + offline_transaction_id_only.merge( + common_builder_with_trx_id, + { + "initial_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + + "net_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + + "payments" => [offline_transaction_charge_id_only], + "created" => created_time.to_i + } + ) + end + + let(:offline_transaction_builder_expanded) do + offline_transaction_builder.merge( + common_builder_with_trx, + common_builder_expanded, + { + "payments" => [offline_transaction_charge_builder] + } + ) + end + + let(:offline_transaction_charge_id_only) do + { + "id" => match_houid("offtrxchrg"), + "object" => "offline_transaction_charge", + "type" => "payment" + } + end + + let(:offline_transaction_charge_builder) do + offline_transaction_charge_id_only.merge( + common_builder_with_trx_id, + { + "gross_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "net_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "fee_total" => { + "cents" => 0, + "currency" => "usd" + }, + "subtransaction" => offline_transaction_id_only, + "created" => created_time.to_i + } + ) + end + + let(:offline_transaction_charge_builder_expanded) do + offline_transaction_charge_builder.merge( + common_builder_with_trx, + common_builder_expanded, + { + "subtransaction" => offline_transaction_builder + } + ) + end + + let(:donation_id_only) do + { + "id" => match_houid("don"), + "object" => "donation", + "type" => "trx_assignment" + } + end + + let(:donation_builder) do + donation_id_only.merge(common_builder_with_trx_id, { + "amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "designation" => nil + }) + end + + let(:donation_builder_expanded) do + donation_builder.merge(common_builder_with_trx, common_builder_expanded) + end + + describe "event publishing" do + it "has fired transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :transaction_created, { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "transaction.created", + "data" => { + "object" => transaction_builder_expanded + } + } + ) + subject + end + + it "has fired offline_transaction_charge.created" do + expect(Houdini.event_publisher).to receive(:announce).with( + :offline_transaction_charge_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "offline_transaction_charge.created", + "data" => { + "object" => offline_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired payment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :payment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "payment.created", + "data" => { + "object" => offline_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired offline_transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :offline_transaction_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "offline_transaction.created", + "data" => { + "object" => offline_transaction_builder_expanded + } + } + ) + + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired donation.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :donation_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "donation.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + + it "has fired trx_assignment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:offline_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :trx_assignment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "trx_assignment.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + subject + end + end + end + end + end end # rubocop:enable all diff --git a/spec/legacy_lib/insert/insert_duplicate_spec.rb b/spec/legacy_lib/insert/insert_duplicate_spec.rb index 32ed89e34a..8a4d473a08 100644 --- a/spec/legacy_lib/insert/insert_duplicate_spec.rb +++ b/spec/legacy_lib/insert/insert_duplicate_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertDuplicate do before(:all) do @@ -12,6 +12,7 @@ after(:all) do Timecop.return end + let(:nonprofit) { force_create(:nm_justice) } let(:profile) { force_create(:profile) } let(:dates) do @@ -25,22 +26,23 @@ } end - describe '.campaign' do + describe ".campaign" do def set_campaign_date(end_date) @end_date = end_date end - before(:each) do + before do set_campaign_date(dates[:ten_days_from_now]) end + let(:campaign) { force_create(:campaign, name: campaign_name, nonprofit: nonprofit, end_datetime: @end_date, slug: campaign_slug, goal_amount: 20_000, published: true, profile: profile) } let(:campaign_gift_option) { force_create(:campaign_gift_option, name: cgo_name, campaign: campaign) } - let(:cgo_name) { 'cgo name' } - let(:campaign_name) { 'campaign_name is so long that it must be shortened down' } - let(:copy_name) { 'campaign_name is so long that it must b (2020-05-05 copy) 00' } - let(:campaign_slug) { 'campaign_slug' } - let(:copy_slug) { 'campaign_slug_copy_00' } + let(:cgo_name) { "cgo name" } + let(:campaign_name) { "campaign_name is so long that it must be shortened down" } + let(:copy_name) { "campaign_name is so long that it must b (2020-05-05 copy) 00" } + let(:campaign_slug) { "campaign_slug" } + let(:copy_slug) { "campaign_slug_copy_00" } let(:common_result_attributes) do { nonprofit_id: nonprofit.id, @@ -82,32 +84,33 @@ def set_campaign_date(end_date) }.with_indifferent_access end - describe 'param validation' do - it 'does basic validation' do + describe "param validation" do + it "does basic validation" do expect { InsertDuplicate.campaign(nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :campaign_id, name: :required }, - { key: :campaign_id, name: :is_integer }, - { key: :profile_id, name: :required }, - { key: :profile_id, name: :is_integer }]) + expect_validation_errors(error.data, [{key: :campaign_id, name: :required}, + {key: :campaign_id, name: :is_integer}, + {key: :profile_id, name: :required}, + {key: :profile_id, name: :is_integer}]) end) end - it 'does campaign existence validation' do + it "does campaign existence validation" do expect { InsertDuplicate.campaign(999, 999) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :campaign_id }]) + expect_validation_errors(error.data, [{key: :campaign_id}]) end) end - it 'does profile existence validation' do + it "does profile existence validation" do expect { InsertDuplicate.campaign(campaign.id, 999) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :profile_id }]) + expect_validation_errors(error.data, [{key: :profile_id}]) end) end end - it 'copies a nonending campaign properly' do + + it "copies a nonending campaign properly" do set_campaign_date(nil) campaign_gift_option result = InsertDuplicate.campaign(campaign.id, profile.id) @@ -121,7 +124,7 @@ def set_campaign_date(end_date) validate_cgo(result) end - it 'copies a soon to finish campaign properly' do + it "copies a soon to finish campaign properly" do set_campaign_date(dates[:two_days_from_now]) campaign_gift_option result = InsertDuplicate.campaign(campaign.id, profile.id) @@ -135,7 +138,7 @@ def set_campaign_date(end_date) validate_cgo(result) end - it 'copies a finished campaign properly' do + it "copies a finished campaign properly" do set_campaign_date(dates[:two_days_ago]) campaign_gift_option result = InsertDuplicate.campaign(campaign.id, profile.id) @@ -149,7 +152,7 @@ def set_campaign_date(end_date) validate_cgo(result) end - it 'copies a future campaign properly' do + it "copies a future campaign properly" do campaign_gift_option result = InsertDuplicate.campaign(campaign.id, profile.id) expect(Campaign.count).to eq 2 @@ -168,17 +171,17 @@ def validate_cgo(new_campaign) new_cgo = new_campaign.campaign_gift_options.first expect(old_cgo.id).to_not eq new_cgo.id expect(old_cgo.campaign_id).to_not eq new_cgo.campaign_id - expect(old_cgo.attributes.except('id', 'campaign_id')).to eq new_cgo.attributes.except('id', 'campaign_id') + expect(old_cgo.attributes.except("id", "campaign_id")).to eq new_cgo.attributes.except("id", "campaign_id") end end - describe '.event' do + describe ".event" do def set_event_start_time(start_time, end_time) @start_time = start_time @end_time = end_time end - before(:each) do + before do set_event_start_time(dates[:ten_days_from_now], dates[:ten_days_from_now_plus_4_hours]) end @@ -187,13 +190,13 @@ def set_event_start_time(start_time, end_time) end let(:ticket_level) { force_create(:ticket_level, name: ticket_level_name, amount_dollars: 500, event: event) } - let(:event_discount) { force_create(:event_discount, code: 'code', event: event) } - let(:cgo_name) { 'cgo name' } - let(:ticket_level_name) { 'cgo name' } - let(:event_name) { 'campaign_name is so long that it must be shortened down' } - let(:copy_name) { 'campaign_name is so long that it must b (2020-05-05 copy) 00' } - let(:event_slug) { 'campaign_slug' } - let(:copy_slug) { 'campaign_slug_copy_00' } + let(:event_discount) { force_create(:event_discount, code: "code", event: event) } + let(:cgo_name) { "cgo name" } + let(:ticket_level_name) { "cgo name" } + let(:event_name) { "campaign_name is so long that it must be shortened down" } + let(:copy_name) { "campaign_name is so long that it must b (2020-05-05 copy) 00" } + let(:event_slug) { "campaign_slug" } + let(:copy_slug) { "campaign_slug_copy_00" } let(:common_result_attributes) do { nonprofit_id: nonprofit.id, @@ -213,12 +216,12 @@ def set_event_start_time(start_time, end_time) updated_at: Time.now, name: copy_name, slug: copy_slug, - address: '100 N Appleton St', - city: 'Appleton', + address: "100 N Appleton St", + city: "Appleton", directions: nil, location: nil, organizer_email: nil, - state_code: 'WI', + state_code: "WI", venue_name: nil, zip_code: nil, show_total_count: false, @@ -228,41 +231,41 @@ def set_event_start_time(start_time, end_time) }.with_indifferent_access end - describe 'param validation' do - it 'does basic validation' do + describe "param validation" do + it "does basic validation" do expect { InsertDuplicate.event(nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :event_id, name: :required }, - { key: :event_id, name: :is_integer }, - { key: :profile_id, name: :required }, - { key: :profile_id, name: :is_integer }]) + expect_validation_errors(error.data, [{key: :event_id, name: :required}, + {key: :event_id, name: :is_integer}, + {key: :profile_id, name: :required}, + {key: :profile_id, name: :is_integer}]) end) end - it 'does event existence validation' do + it "does event existence validation" do expect { InsertDuplicate.event(999, 999) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :event_id }]) + expect_validation_errors(error.data, [{key: :event_id}]) end) end - it 'does profile existence validation' do + it "does profile existence validation" do expect { InsertDuplicate.event(event.id, 999) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :profile_id }]) + expect_validation_errors(error.data, [{key: :profile_id}]) end) end end - it 'copies a soon to start event properly' do + it "copies a soon to start event properly" do set_event_start_time(dates[:two_days_from_now], dates[:two_days_from_now_plus_4_hours]) ticket_level event_discount result = InsertDuplicate.event(event.id, profile.id) expect(Event.count).to eq 2 - result.attributes['start_datetime'] = result.attributes['start_datetime'].to_datetime - result.attributes['end_datetime'] = result.attributes['end_datetime'].to_datetime + result.attributes["start_datetime"] = result.attributes["start_datetime"].to_datetime + result.attributes["end_datetime"] = result.attributes["end_datetime"].to_datetime expect(result.attributes.with_indifferent_access).to eq(common_result_attributes.merge( id: result.id, start_datetime: DateTime.new(2020, 5, 12), @@ -272,16 +275,16 @@ def set_event_start_time(start_time, end_time) validate_eds(result) end - it 'copies a finished event properly' do + it "copies a finished event properly" do set_event_start_time(dates[:two_days_ago], dates[:two_days_ago_plus_4_hours]) ticket_level event_discount result = InsertDuplicate.event(event.id, profile.id) expect(Event.count).to eq 2 - result.attributes['start_datetime'] = result.attributes['start_datetime'] + result.attributes["start_datetime"] = result.attributes["start_datetime"] - result.attributes['end_datetime'] = result.attributes['end_datetime'].to_datetime + result.attributes["end_datetime"] = result.attributes["end_datetime"].to_datetime expect(result.attributes.with_indifferent_access).to eq(common_result_attributes.merge( id: result.id, @@ -293,13 +296,13 @@ def set_event_start_time(start_time, end_time) validate_eds(result) end - it 'copies a future event properly' do + it "copies a future event properly" do ticket_level event_discount result = InsertDuplicate.event(event.id, profile.id) expect(Event.count).to eq 2 - result.attributes['start_datetime'] = result.attributes['start_datetime'].to_datetime - result.attributes['end_datetime'] = result.attributes['end_datetime'].to_datetime + result.attributes["start_datetime"] = result.attributes["start_datetime"].to_datetime + result.attributes["end_datetime"] = result.attributes["end_datetime"].to_datetime expect(result.attributes.with_indifferent_access).to eq(common_result_attributes.merge( id: result.id, start_datetime: event.start_datetime.to_time, @@ -316,7 +319,7 @@ def validate_tls(new_event) new_tl = new_event.ticket_levels.first expect(old_tl.id).to_not eq new_tl.id expect(old_tl.event_id).to_not eq new_tl.event_id - expect(old_tl.attributes.except('id', 'event_id')).to eq new_tl.attributes.except('id', 'event_id') + expect(old_tl.attributes.except("id", "event_id")).to eq new_tl.attributes.except("id", "event_id") end def validate_eds(new_event) @@ -327,7 +330,7 @@ def validate_eds(new_event) new_ed = new_event.event_discounts.first expect(old_ed.id).to_not eq new_ed.id expect(old_ed.event_id).to_not eq new_ed.event_id - expect(old_ed.attributes.except('id', 'event_id')).to eq new_ed.attributes.except('id', 'event_id') + expect(old_ed.attributes.except("id", "event_id")).to eq new_ed.attributes.except("id", "event_id") end end end diff --git a/spec/legacy_lib/insert/insert_payout_spec.rb b/spec/legacy_lib/insert/insert_payout_spec.rb index c27144c8e9..544a9e05e4 100644 --- a/spec/legacy_lib/insert/insert_payout_spec.rb +++ b/spec/legacy_lib/insert/insert_payout_spec.rb @@ -2,62 +2,63 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'support/payments_for_a_payout' +require "rails_helper" +require "support/payments_for_a_payout" describe InsertPayout do - let(:bank_name) { 'CHASE *1234' } + let(:bank_name) { "CHASE *1234" } let(:supporter) { force_create(:supporter) } - let(:user_email) { 'uzr@example.com' } - let(:user_ip) { '8.8.8.8' } + let(:user_email) { "uzr@example.com" } + let(:user_ip) { "8.8.8.8" } - describe '.with_stripe' do - describe 'param validation' do - it 'basic param validation' do + describe ".with_stripe" do + describe "param validation" do + it "basic param validation" do expect { InsertPayout.with_stripe(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :np_id, name: :required }, - { key: :np_id, name: :is_integer }, - { key: :stripe_account_id, name: :required }, - { key: :stripe_account_id, name: :not_blank }, - { key: :email, name: :required }, - { key: :email, name: :not_blank }, - { key: :user_ip, name: :required }, - { key: :user_ip, name: :not_blank }, - { key: :bank_name, name: :required }, - { key: :bank_name, name: :not_blank } - ]) + {key: :np_id, name: :required}, + {key: :np_id, name: :is_integer}, + {key: :stripe_account_id, name: :required}, + {key: :stripe_account_id, name: :not_blank}, + {key: :email, name: :required}, + {key: :email, name: :not_blank}, + {key: :user_ip, name: :required}, + {key: :user_ip, name: :not_blank}, + {key: :bank_name, name: :required}, + {key: :bank_name, name: :not_blank} + ]) end) end - it 'validates nonprofit' do - expect { InsertPayout.with_stripe(666, { stripe_account_id: 'valid', email: 'valid', user_ip: 'valid', bank_name: 'valid' }, nil) }.to(raise_error do |error| + it "validates nonprofit" do + expect { InsertPayout.with_stripe(666, {stripe_account_id: "valid", email: "valid", user_ip: "valid", bank_name: "valid"}, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :np_id }]) + expect_validation_errors(error.data, [{key: :np_id}]) end) end end - context 'when valid' do + context "when valid" do let(:stripe_helper) { StripeMockHelper.default_helper } - around(:each) do |example| - Timecop.freeze(2020, 5, 4) do + around do |example| + Timecop.freeze(2020, 5, 4) do StripeMockHelper.mock do example.run end end end - it 'handles no charges to payout' do + let(:user) { force_create(:user) } + + it "handles no charges to payout" do np = force_create(:nm_justice) - expect { InsertPayout.with_stripe(np.id, { stripe_account_id: 'valid', email: 'valid', user_ip: 'valid', bank_name: 'valid' }, nil) }.to(raise_error do |error| + expect { InsertPayout.with_stripe(np.id, {stripe_account_id: "valid", email: "valid", user_ip: "valid", bank_name: "valid"}, nil) }.to(raise_error do |error| expect(error).to be_a ArgumentError - expect(error.message).to eq 'No payments are available for disbursal on this account.' + expect(error.message).to eq "No payments are available for disbursal on this account." end) end - let(:user) { force_create(:user) } # Test one basic charge, one charge with a partial refund, and one charge with a full refund @@ -70,40 +71,42 @@ # Already paid out dispute # already paid out refund - context 'no date provided' do - include_context 'payments for a payout' do - let(:np) { force_create(:nm_justice, stripe_account_id: Stripe::Account.create['id'], vetted: true) } + context "no date provided" do + include_context "payments for a payout" do + let(:np) { force_create(:nm_justice, stripe_account_id: Stripe::Account.create["id"], vetted: true) } let(:date_for_marking) { Time.now } let(:ba) do InsertBankAccount.with_stripe(np, user, stripe_bank_account_token: StripeMockHelper.generate_bank_token, name: bank_name) end end - before(:each) do + before do ba end - let(:expected_totals) { { gross_amount: 5500, fee_total: -1200, net_amount: 4300, count: 8 } } - it 'works without a date provided' do + + let(:expected_totals) { {gross_amount: 5500, fee_total: -1200, net_amount: 4300, count: 8} } + + it "works without a date provided" do stripe_transfer_id = nil - expect(Stripe::Transfer).to receive(:create).with({ amount: expected_totals[:net_amount], - currency: 'usd', - recipient: 'self' }, - stripe_account: np.stripe_account_id) - .and_wrap_original { |m, *args| + expect(Stripe::Transfer).to receive(:create).with({amount: expected_totals[:net_amount], + currency: "usd", + recipient: "self"}, + stripe_account: np.stripe_account_id) + .and_wrap_original { |m, *args| i = m.call(*args) - stripe_transfer_id = i['id'] + stripe_transfer_id = i["id"] i } all_payments result = InsertPayout.with_stripe(np.id, stripe_account_id: np.stripe_account_id, - email: user_email, - user_ip: user_ip, - bank_name: bank_name) + email: user_email, + user_ip: user_ip, + bank_name: bank_name) expected_result = { net_amount: expected_totals[:net_amount], nonprofit_id: np.id, - status: 'pending', + status: "pending", fee_total: expected_totals[:fee_total], gross_amount: expected_totals[:gross_amount], email: user_email, @@ -112,20 +115,20 @@ user_ip: user_ip, ach_fee: 0, bank_name: bank_name, - updated_at: Time.now.strftime('%Y-%m-%d %H:%M:%S'), - created_at: Time.now.strftime('%Y-%m-%d %H:%M:%S') + updated_at: Time.now.strftime("%Y-%m-%d %H:%M:%S"), + created_at: Time.now.strftime("%Y-%m-%d %H:%M:%S") }.with_indifferent_access expect(Payout.count).to eq 1 resulted_payout = Payout.first expect(result.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id) - empty_db_attributes = { manual: nil, scheduled: nil, failure_message: nil } + empty_db_attributes = {manual: nil, scheduled: nil, failure_message: nil} expect(resulted_payout.attributes.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id).merge(empty_db_attributes) # validate which charges are makred @expect_marked[:charges].each do |c| c.reload - expect(c.status).to eq 'disbursed' + expect(c.status).to eq "disbursed" end # validate which refunds are marked @@ -138,26 +141,26 @@ # validate which disputes are marked @expect_marked[:disputes].each do |d| d.reload - expect(d.status).to eq 'lost_and_paid' + expect(d.status).to eq "lost_and_paid" end # validate payment payout records - expect(resulted_payout.payments.pluck('payments.id')).to eq @expect_marked[:payouts_records].collect(&:id) + expect(resulted_payout.payments.pluck("payments.id")).to eq @expect_marked[:payouts_records].collect(&:id) end - it 'fails properly when Stripe payout call fails' do - StripeMockHelper.prepare_error(Stripe::StripeError.new('Payout failed'), :new_transfer) + it "fails properly when Stripe payout call fails" do + StripeMockHelper.prepare_error(Stripe::StripeError.new("Payout failed"), :new_transfer) all_payments result = InsertPayout.with_stripe(np.id, stripe_account_id: np.stripe_account_id, - email: user_email, - user_ip: user_ip, - bank_name: bank_name) + email: user_email, + user_ip: user_ip, + bank_name: bank_name) expected_result = { net_amount: expected_totals[:net_amount], nonprofit_id: np.id, - status: 'failed', + status: "failed", fee_total: expected_totals[:fee_total], gross_amount: expected_totals[:gross_amount], email: user_email, @@ -166,21 +169,21 @@ user_ip: user_ip, ach_fee: 0, bank_name: bank_name, - updated_at: Time.now.strftime('%Y-%m-%d %H:%M:%S'), - created_at: Time.now.strftime('%Y-%m-%d %H:%M:%S') + updated_at: Time.now.strftime("%Y-%m-%d %H:%M:%S"), + created_at: Time.now.strftime("%Y-%m-%d %H:%M:%S") }.with_indifferent_access expect(Payout.count).to eq 1 resulted_payout = Payout.first expect(result.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id) - empty_db_attributes = { manual: nil, scheduled: nil, failure_message: 'Payout failed' } + empty_db_attributes = {manual: nil, scheduled: nil, failure_message: "Payout failed"} expect(resulted_payout.attributes.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id).merge(empty_db_attributes) # validate which charges are makred @expect_marked[:charges].each do |c| c.reload - expect(c.status).to eq 'available' + expect(c.status).to eq "available" end # validate which refunds are marked @@ -193,7 +196,7 @@ # validate which disputes are marked @expect_marked[:disputes].each do |d| d.reload - expect(d.status).to eq 'lost' + expect(d.status).to eq "lost" end # validate payment payout records @@ -201,38 +204,39 @@ end end - context 'previous date provided' do - include_context 'payments for a payout' do - let(:np) { force_create(:nm_justice, stripe_account_id: Stripe::Account.create['id'], vetted: true) } + context "previous date provided" do + include_context "payments for a payout" do + let(:np) { force_create(:nm_justice, stripe_account_id: Stripe::Account.create["id"], vetted: true) } let(:date_for_marking) { Time.now - 1.day } let(:ba) { InsertBankAccount.with_stripe(np, user, stripe_bank_account_token: StripeMockHelper.generate_bank_token, name: bank_name) } end - before(:each) do + before do ba end - let(:expected_totals) { { gross_amount: 3500, fee_total: -800, net_amount: 2700, count: 7 } } - it 'works with date provided' do + let(:expected_totals) { {gross_amount: 3500, fee_total: -800, net_amount: 2700, count: 7} } + + it "works with date provided" do stripe_transfer_id = nil - expect(Stripe::Transfer).to receive(:create).with({ amount: expected_totals[:net_amount], - currency: 'usd', - recipient: 'self' }, - stripe_account: np.stripe_account_id) - .and_wrap_original { |m, *args| + expect(Stripe::Transfer).to receive(:create).with({amount: expected_totals[:net_amount], + currency: "usd", + recipient: "self"}, + stripe_account: np.stripe_account_id) + .and_wrap_original { |m, *args| i = m.call(*args) - stripe_transfer_id = i['id'] + stripe_transfer_id = i["id"] i } all_payments - result = InsertPayout.with_stripe(np.id, { stripe_account_id: np.stripe_account_id, + result = InsertPayout.with_stripe(np.id, {stripe_account_id: np.stripe_account_id, email: user_email, user_ip: user_ip, - bank_name: bank_name }, date: Time.now - 1.day) + bank_name: bank_name}, date: Time.now - 1.day) expected_result = { net_amount: expected_totals[:net_amount], nonprofit_id: np.id, - status: 'pending', + status: "pending", fee_total: expected_totals[:fee_total], gross_amount: expected_totals[:gross_amount], email: user_email, @@ -241,20 +245,20 @@ user_ip: user_ip, ach_fee: 0, bank_name: bank_name, - updated_at: Time.now.strftime('%Y-%m-%d %H:%M:%S'), - created_at: Time.now.strftime('%Y-%m-%d %H:%M:%S') + updated_at: Time.now.strftime("%Y-%m-%d %H:%M:%S"), + created_at: Time.now.strftime("%Y-%m-%d %H:%M:%S") }.with_indifferent_access expect(Payout.count).to eq 1 resulted_payout = Payout.first expect(result.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id) - empty_db_attributes = { manual: nil, scheduled: nil, failure_message: nil } + empty_db_attributes = {manual: nil, scheduled: nil, failure_message: nil} expect(resulted_payout.attributes.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id).merge(empty_db_attributes) # validate which charges are makred @expect_marked[:charges].each do |c| c.reload - expect(c.status).to(eq('disbursed'), c.attributes.to_s) + expect(c.status).to(eq("disbursed"), c.attributes.to_s) end # validate which refunds are marked @@ -266,23 +270,23 @@ # validate which disputes are marked @expect_marked[:disputes].each do |d| d.reload - expect(d.status).to eq 'lost_and_paid' + expect(d.status).to eq "lost_and_paid" end end - it 'fails properly when Stripe payout call fails' do - StripeMockHelper.prepare_error(Stripe::StripeError.new('Payout failed'), :new_transfer) + it "fails properly when Stripe payout call fails" do + StripeMockHelper.prepare_error(Stripe::StripeError.new("Payout failed"), :new_transfer) all_payments - result = InsertPayout.with_stripe(np.id, { stripe_account_id: np.stripe_account_id, + result = InsertPayout.with_stripe(np.id, {stripe_account_id: np.stripe_account_id, email: user_email, user_ip: user_ip, - bank_name: bank_name }, date: Time.now - 1.day) + bank_name: bank_name}, date: Time.now - 1.day) expected_result = { net_amount: expected_totals[:net_amount], nonprofit_id: np.id, - status: 'failed', + status: "failed", fee_total: expected_totals[:fee_total], gross_amount: expected_totals[:gross_amount], email: user_email, @@ -291,21 +295,21 @@ user_ip: user_ip, ach_fee: 0, bank_name: bank_name, - updated_at: Time.now.strftime('%Y-%m-%d %H:%M:%S'), - created_at: Time.now.strftime('%Y-%m-%d %H:%M:%S') + updated_at: Time.now.strftime("%Y-%m-%d %H:%M:%S"), + created_at: Time.now.strftime("%Y-%m-%d %H:%M:%S") }.with_indifferent_access expect(Payout.count).to eq 1 resulted_payout = Payout.first expect(result.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id) - empty_db_attributes = { manual: nil, scheduled: nil, failure_message: 'Payout failed' } + empty_db_attributes = {manual: nil, scheduled: nil, failure_message: "Payout failed"} expect(resulted_payout.attributes.with_indifferent_access).to eq expected_result.merge(id: resulted_payout.id).merge(empty_db_attributes) # validate which charges are makred @expect_marked[:charges].each do |c| c.reload - expect(c.status).to eq 'available' + expect(c.status).to eq "available" end # validate which refunds are marked @@ -317,7 +321,7 @@ # validate which disputes are marked @expect_marked[:disputes].each do |d| d.reload - expect(d.status).to eq 'lost' + expect(d.status).to eq "lost" end # validate payment payout records diff --git a/spec/legacy_lib/insert/insert_recurring_donation_spec.rb b/spec/legacy_lib/insert/insert_recurring_donation_spec.rb index 1eaf2ce888..bb5c763bab 100644 --- a/spec/legacy_lib/insert/insert_recurring_donation_spec.rb +++ b/spec/legacy_lib/insert/insert_recurring_donation_spec.rb @@ -2,748 +2,752 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertRecurringDonation do - describe '.with_stripe' do - before do - Houdini.payment_providers.stripe.connect = true - end + describe ".with_stripe" do + before do + Houdini.payment_providers.stripe.connect = true + end + include_context :shared_rd_donation_value_context - it 'does basic validation' do - validation_basic_validation { InsertRecurringDonation.with_stripe(designation: 34_124, dedication: 35_141, event_id: 'bad', campaign_id: 'bad') } + it "does basic validation" do + validation_basic_validation { InsertRecurringDonation.with_stripe(designation: 34_124, dedication: 35_141, event_id: "bad", campaign_id: "bad") } end - it 'does recurring donation validation' do + it "does recurring donation validation" do expect do InsertRecurringDonation.with_stripe(amount: 1, nonprofit_id: 1, supporter_id: 1, token: fake_uuid, - recurring_donation: { interval: 'not number', start_date: 'not_date', time_unit: 4, paydate: 'faf' }) - end .to raise_error { |e| - expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [ - { key: :interval, name: :is_integer }, - { key: :start_date, name: :can_be_date }, - { key: :time_unit, name: :included_in }, - { key: :paydate, name: :is_integer } - ]) - } + recurring_donation: {interval: "not number", start_date: "not_date", time_unit: 4, paydate: "faf"}) + end.to raise_error { |e| + expect(e).to be_a ParamValidation::ValidationError + expect_validation_errors(e.data, [ + {key: :interval, name: :is_integer}, + {key: :start_date, name: :can_be_date}, + {key: :time_unit, name: :included_in}, + {key: :paydate, name: :is_integer} + ]) + } end - it 'does paydate validation min' do + it "does paydate validation min" do expect do InsertRecurringDonation.with_stripe(amount: 1, nonprofit_id: 1, supporter_id: 1, token: fake_uuid, - recurring_donation: { paydate: '0' }) - end .to raise_error { |e| - expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [ - { key: :paydate, name: :min } - ]) - } + recurring_donation: {paydate: "0"}) + end.to raise_error { |e| + expect(e).to be_a ParamValidation::ValidationError + expect_validation_errors(e.data, [ + {key: :paydate, name: :min} + ]) + } end - it 'does paydate validation max' do + it "does paydate validation max" do expect do InsertRecurringDonation.with_stripe(amount: 1, nonprofit_id: 1, supporter_id: 1, token: fake_uuid, - recurring_donation: { paydate: '29' }) - end .to raise_error { |e| - expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [ - { key: :paydate, name: :max } - ]) - } + recurring_donation: {paydate: "29"}) + end.to raise_error { |e| + expect(e).to be_a ParamValidation::ValidationError + expect_validation_errors(e.data, [ + {key: :paydate, name: :max} + ]) + } end - it 'errors out if token is invalid' do + it "errors out if token is invalid" do validation_invalid_token { InsertRecurringDonation.with_stripe(amount: 1, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) } end - it 'errors out if token is unauthorized' do + it "errors out if token is unauthorized" do validation_unauthorized { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) } end - it 'errors out if token is expired' do + it "errors out if token is expired" do validation_expired { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: 1, supporter_id: 1, token: fake_uuid) } end - describe 'errors during find if' do - it 'supporter is invalid' do + describe "errors during find if" do + it "supporter is invalid" do find_error_supporter { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: 55_555, token: source_token.token) } end - it 'nonprofit is invalid' do + it "nonprofit is invalid" do find_error_nonprofit { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: 55_555, supporter_id: supporter.id, token: source_token.token) } end - it 'campaign is invalid' do + it "campaign is invalid" do find_error_campaign { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: 5555) } end - it 'event is invalid' do + it "event is invalid" do find_error_event { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: 5555) } end - it 'profile is invalid' do + it "profile is invalid" do find_error_profile { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, profile_id: 5555) } end end - describe 'errors during relationship comparison if' do - it 'event is deleted' do + describe "errors during relationship comparison if" do + it "event is deleted" do validation_event_deleted { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } end - it 'campaign is deleted' do + it "campaign is deleted" do validation_campaign_deleted { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id) } end - it 'supporter is deleted' do + it "supporter is deleted" do validation_supporter_deleted { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token) } end - it 'supporter doesnt belong to nonprofit' do + it "supporter doesnt belong to nonprofit" do validation_supporter_not_with_nonprofit { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: other_nonprofit_supporter.id, token: source_token.token) } end - it 'campaign doesnt belong to nonprofit' do + it "campaign doesnt belong to nonprofit" do validation_campaign_not_with_nonprofit { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: other_campaign.id) } end - it 'event doesnt belong to nonprofit' do + it "event doesnt belong to nonprofit" do validation_event_not_with_nonprofit { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: other_event.id) } end - it 'card doesnt belong to supporter' do + it "card doesnt belong to supporter" do validation_card_not_with_supporter { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: other_source_token.token) } end end - it 'charge returns failed' do + it "charge returns failed" do handle_charge_failed { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token) } end - describe 'success' do - before(:each) do + describe "success" do + before do allow(SecureRandom).to receive(:uuid).and_return(default_edit_token) - allow(Houdini.event_publisher).to receive(:announce) + allow(Houdini.event_publisher).to receive(:announce) end - describe 'charge happens' do - before(:each) do + + describe "charge happens" do + before do before_each_success end - it 'process event donation' do - process_event_donation(recurring_donation: { paydate: nil, interval: 1, time_unit: 'year', start_date: Time.current.beginning_of_day }) { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, date: (Time.now + 1.day).to_s, dedication: {'type' => 'honor', 'name' => 'a name'}, designation: 'designation', recurring_donation: { time_unit: 'year' }) } + + it "process event donation" do + process_event_donation(recurring_donation: {paydate: nil, interval: 1, time_unit: "year", start_date: Time.current.beginning_of_day}) { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, date: (Time.now + 1.day).to_s, dedication: {"type" => "honor", "name" => "a name"}, designation: "designation", recurring_donation: {time_unit: "year"}) } end - it 'process campaign donation' do + it "process campaign donation" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) - process_campaign_donation(recurring_donation: { paydate: nil, interval: 2, time_unit: 'month', start_date: Time.current.beginning_of_day }) { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: {'type' => 'honor', 'name' => 'a name'}, designation: 'designation', recurring_donation: { interval: 2 }) } + process_campaign_donation(recurring_donation: {paydate: nil, interval: 2, time_unit: "month", start_date: Time.current.beginning_of_day}) { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: {"type" => "honor", "name" => "a name"}, designation: "designation", recurring_donation: {interval: 2}) } end - it 'processes general donation with no recurring donation hash' do - process_general_donation(recurring_donation: { paydate: Time.now.day, interval: 1, time_unit: 'month', start_date: Time.now.beginning_of_day }) do - InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, profile_id: profile.id, date: Time.now.to_s, dedication: {'type' => 'honor', 'name' => 'a name'}, designation: 'designation') + it "processes general donation with no recurring donation hash" do + process_general_donation(recurring_donation: {paydate: Time.now.day, interval: 1, time_unit: "month", start_date: Time.now.beginning_of_day}) do + InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, profile_id: profile.id, date: Time.now.to_s, dedication: {"type" => "honor", "name" => "a name"}, designation: "designation") end end - describe 'object event firing' do - # all the same for all the types of donations; see #603 - let(:created_time) { Time.current } - let(:common_builder) do - { 'supporter' => supporter.id, - 'nonprofit' => nonprofit.id } - end - - let(:common_builder_expanded) do - { - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded - } - end - - let(:common_builder_with_trx_id) do - common_builder.merge( - { - 'transaction' => match_houid('trx') - } - ) - end - - let(:common_builder_with_trx) do - common_builder.merge( - { - 'transaction' => transaction_builder - } - ) - end - - let(:np_builder_expanded) do - { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - } - end - - let(:supporter_builder_expanded) do - supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - end - - let(:transaction_builder) do - common_builder.merge( - { - 'id' => match_houid('trx'), - 'object' => 'transaction', - 'amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'created' => created_time.to_i, - 'subtransaction' => stripe_transaction_id_only, - 'payments' => [stripe_transaction_charge_id_only], - 'transaction_assignments' => [donation_id_only] - } - ) - end - - let(:transaction_builder_expanded) do - transaction_builder.merge( - common_builder_expanded, - { - 'subtransaction' => stripe_transaction_builder, - 'payments' => [stripe_transaction_charge_builder], - 'transaction_assignments' => [donation_builder] - } - ) - end - - let(:stripe_transaction_id_only) do - { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - } - end - - let(:stripe_transaction_builder) do - stripe_transaction_id_only.merge( - common_builder_with_trx_id, - { - 'initial_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - - 'net_amount' => { - 'cents' => 67, - 'currency' => 'usd' - }, - - 'payments' => [stripe_transaction_charge_id_only], - 'created' => created_time.to_i - } - ) - end - - let(:stripe_transaction_builder_expanded) do - stripe_transaction_builder.merge( - common_builder_with_trx, - common_builder_expanded, - { - 'payments' => [stripe_transaction_charge_builder] - } - ) - end - - let(:stripe_transaction_charge_id_only) do - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - } - end - - let(:stripe_transaction_charge_builder) do - stripe_transaction_charge_id_only.merge( - common_builder_with_trx_id, - { - 'gross_amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'net_amount' => { - 'cents' => 67, - 'currency' => 'usd' - }, - 'fee_total' => { - 'cents' => -33, - 'currency' => 'usd' - }, - 'subtransaction' => stripe_transaction_id_only, - 'stripe_id' => /test_ch_\d+/, - 'created' => created_time.to_i - } - ) - end - - let(:stripe_transaction_charge_builder_expanded) do - stripe_transaction_charge_builder.merge( - common_builder_with_trx, - common_builder_expanded, - { - 'subtransaction' => stripe_transaction_builder - } - ) - end - - let(:donation_id_only) do - { - 'id' => match_houid('don'), - 'object' => 'donation', - 'type' => 'trx_assignment' - } - end - - let(:donation_builder) do - donation_id_only.merge(common_builder_with_trx_id, { - 'amount' => { - 'cents' => charge_amount, - 'currency' => 'usd' - }, - 'designation' => 'designation', - 'dedication' => { - 'name' => 'a name', - 'type' => 'honor' - } - }) - end - - let(:donation_builder_expanded) do - donation_builder.merge(common_builder_with_trx, common_builder_expanded) - end - - let(:recurrence_builder_expanded) do - - end - - - describe 'general donations' do - subject do - process_general_donation(recurring_donation: { paydate: Time.now.day, interval: 1, time_unit: 'month', start_date: Time.now.beginning_of_day }) do - described_class.with_stripe( - { - amount: charge_amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: source_token.token, - profile_id: profile.id, - dedication: { 'name' => 'a name', 'type' => 'honor' }, - designation: 'designation' - - }.with_indifferent_access - ) - end - end - - it 'has fired transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :transaction_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'transaction.created', - 'data' => { - 'object' => transaction_builder_expanded - } - } - ) - - expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) - subject - end - - it 'has fired stripe_transaction_charge.created' do - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_charge_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction_charge.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) - subject - end - - it 'has fired payment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :payment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'payment.created', - 'data' => { - 'object' => stripe_transaction_charge_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - subject - end - - it 'has fired stripe_transaction.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :stripe_transaction_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'stripe_transaction.created', - 'data' => { - 'object' => stripe_transaction_builder_expanded - } - } - ) - - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) - subject - end - - it 'has fired donation.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :donation_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'donation.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) - subject - end - - it 'has fired trx_assignment.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with( - :trx_assignment_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'trx_assignment.created', - 'data' => { - 'object' => donation_builder_expanded - } - } - ) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) - subject - end - - it 'has fired recurrence.created' do - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'recurrence.created', - 'data' => { - 'object' => common_builder_expanded.merge({ - 'object' => 'recurrence', - 'id' => match_houid('recur'), - 'start_date' => Time.new(2020, 5, 4).utc.to_i, - 'recurrences' => [ - { - 'start' => Time.new(2020, 5, 4).utc.to_i, - 'interval' => 1, - 'type' => 'monthly' - }], - 'invoice_template' => { - 'supporter' => supporter.id, - 'amount' => {'cents' => charge_amount, 'currency' => 'usd'}, - 'payment_method' => {'type' => 'stripe'}, - 'trx_assignments' => [ - { - 'assignment_object' => 'donation', - 'dedication' => { 'name' => 'a name', 'type' => 'honor', 'note' => nil}, - 'designation' => 'designation', - 'amount' => {'cents' => charge_amount, 'currency' => 'usd'} - }] - } - }) - }}) - subject - end - end - - # describe 'campaign donations' do - # subject do - # expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) - # process_campaign_donation do - # described_class.with_stripe( - # { - # amount: charge_amount, - # nonprofit_id: nonprofit.id, - # supporter_id: supporter.id, - # token: source_token.token, - # dedication: { 'name' => 'a name', 'type' => 'honor' }, - # designation: 'designation', - # campaign_id: campaign.id - # }.with_indifferent_access - # ) - # end - # end - - # before do - # before_each_success - # end - - # it 'has fired transaction.created' do - # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with( - # :transaction_created, { - # 'id' => match_houid('objevt'), - # 'object' => 'object_event', - # 'type' => 'transaction.created', - # 'data' => { - # 'object' => transaction_builder_expanded - # } - # } - # ) - # subject - # end - - # it 'has fired stripe_transaction_charge.created' do - # expect(Houdini.event_publisher).to receive(:announce).with( - # :stripe_transaction_charge_created, - # { - # 'id' => match_houid('objevt'), - # 'object' => 'object_event', - # 'type' => 'stripe_transaction_charge.created', - # 'data' => { - # 'object' => stripe_transaction_charge_builder_expanded - # } - # } - # ) - # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - # subject - # end - - # it 'has fired payment.created' do - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with( - # :payment_created, - # { - # 'id' => match_houid('objevt'), - # 'object' => 'object_event', - # 'type' => 'payment.created', - # 'data' => { - # 'object' => stripe_transaction_charge_builder_expanded - # } - # } - # ) - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - - # subject - # end - - # it 'has fired stripe_transaction.created' do - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with( - # :stripe_transaction_created, - # { - # 'id' => match_houid('objevt'), - # 'object' => 'object_event', - # 'type' => 'stripe_transaction.created', - # 'data' => { - # 'object' => stripe_transaction_builder_expanded - # } - # } - # ) - - # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - # subject - # end - - # it 'has fired donation.created' do - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with( - # :donation_created, - # { - # 'id' => match_houid('objevt'), - # 'object' => 'object_event', - # 'type' => 'donation.created', - # 'data' => { - # 'object' => donation_builder_expanded - # } - # } - # ) - # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - # subject - # end - - # it 'has fired trx_assignment.created' do - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) - # expect(Houdini.event_publisher).to receive(:announce).with( - # :trx_assignment_created, - # { - # 'id' => match_houid('objevt'), - # 'object' => 'object_event', - # 'type' => 'trx_assignment.created', - # 'data' => { - # 'object' => donation_builder_expanded - # } - # } - # ) - # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) - # subject - # end - # end - end + describe "object event firing" do + # all the same for all the types of donations; see #603 + let(:created_time) { Time.current } + let(:common_builder) do + {"supporter" => supporter.id, + "nonprofit" => nonprofit.id} + end + + let(:common_builder_expanded) do + { + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded + } + end + + let(:common_builder_with_trx_id) do + common_builder.merge( + { + "transaction" => match_houid("trx") + } + ) + end + + let(:common_builder_with_trx) do + common_builder.merge( + { + "transaction" => transaction_builder + } + ) + end + + let(:np_builder_expanded) do + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } + end + + let(:supporter_builder_expanded) do + supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + end + + let(:transaction_builder) do + common_builder.merge( + { + "id" => match_houid("trx"), + "object" => "transaction", + "amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "created" => created_time.to_i, + "subtransaction" => stripe_transaction_id_only, + "payments" => [stripe_transaction_charge_id_only], + "transaction_assignments" => [donation_id_only] + } + ) + end + + let(:transaction_builder_expanded) do + transaction_builder.merge( + common_builder_expanded, + { + "subtransaction" => stripe_transaction_builder, + "payments" => [stripe_transaction_charge_builder], + "transaction_assignments" => [donation_builder] + } + ) + end + + let(:stripe_transaction_id_only) do + { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + } + end + + let(:stripe_transaction_builder) do + stripe_transaction_id_only.merge( + common_builder_with_trx_id, + { + "initial_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + + "net_amount" => { + "cents" => 67, + "currency" => "usd" + }, + + "payments" => [stripe_transaction_charge_id_only], + "created" => created_time.to_i + } + ) + end + + let(:stripe_transaction_builder_expanded) do + stripe_transaction_builder.merge( + common_builder_with_trx, + common_builder_expanded, + { + "payments" => [stripe_transaction_charge_builder] + } + ) + end + + let(:stripe_transaction_charge_id_only) do + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + } + end + + let(:stripe_transaction_charge_builder) do + stripe_transaction_charge_id_only.merge( + common_builder_with_trx_id, + { + "gross_amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "net_amount" => { + "cents" => 67, + "currency" => "usd" + }, + "fee_total" => { + "cents" => -33, + "currency" => "usd" + }, + "subtransaction" => stripe_transaction_id_only, + "stripe_id" => /test_ch_\d+/, + "created" => created_time.to_i + } + ) + end + + let(:stripe_transaction_charge_builder_expanded) do + stripe_transaction_charge_builder.merge( + common_builder_with_trx, + common_builder_expanded, + { + "subtransaction" => stripe_transaction_builder + } + ) + end + + let(:donation_id_only) do + { + "id" => match_houid("don"), + "object" => "donation", + "type" => "trx_assignment" + } + end + + let(:donation_builder) do + donation_id_only.merge(common_builder_with_trx_id, { + "amount" => { + "cents" => charge_amount, + "currency" => "usd" + }, + "designation" => "designation", + "dedication" => { + "name" => "a name", + "type" => "honor" + } + }) + end + + let(:donation_builder_expanded) do + donation_builder.merge(common_builder_with_trx, common_builder_expanded) + end + + let(:recurrence_builder_expanded) do + end + + describe "general donations" do + subject do + process_general_donation(recurring_donation: {paydate: Time.now.day, interval: 1, time_unit: "month", start_date: Time.now.beginning_of_day}) do + described_class.with_stripe( + { + amount: charge_amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: source_token.token, + profile_id: profile.id, + dedication: {"name" => "a name", "type" => "honor"}, + designation: "designation" + + }.with_indifferent_access + ) + end + end + + it "has fired transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :transaction_created, { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "transaction.created", + "data" => { + "object" => transaction_builder_expanded + } + } + ) + + expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) + subject + end + + it "has fired stripe_transaction_charge.created" do + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_charge_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction_charge.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) + subject + end + + it "has fired payment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :payment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "payment.created", + "data" => { + "object" => stripe_transaction_charge_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + subject + end + + it "has fired stripe_transaction.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :stripe_transaction_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "stripe_transaction.created", + "data" => { + "object" => stripe_transaction_builder_expanded + } + } + ) + + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) + subject + end + + it "has fired donation.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :donation_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "donation.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) + subject + end + + it "has fired trx_assignment.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with( + :trx_assignment_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "trx_assignment.created", + "data" => { + "object" => donation_builder_expanded + } + } + ) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, any_args) + subject + end + + it "has fired recurrence.created" do + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_created, { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "recurrence.created", + "data" => { + "object" => common_builder_expanded.merge({ + "object" => "recurrence", + "id" => match_houid("recur"), + "start_date" => Time.new(2020, 5, 4).utc.to_i, + "recurrences" => [ + { + "start" => Time.new(2020, 5, 4).utc.to_i, + "interval" => 1, + "type" => "monthly" + } + ], + "invoice_template" => { + "supporter" => supporter.id, + "amount" => {"cents" => charge_amount, "currency" => "usd"}, + "payment_method" => {"type" => "stripe"}, + "trx_assignments" => [ + { + "assignment_object" => "donation", + "dedication" => {"name" => "a name", "type" => "honor", "note" => nil}, + "designation" => "designation", + "amount" => {"cents" => charge_amount, "currency" => "usd"} + } + ] + } + }) + } + }) + subject + end + end + + # describe 'campaign donations' do + # subject do + # expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args) + # process_campaign_donation do + # described_class.with_stripe( + # { + # amount: charge_amount, + # nonprofit_id: nonprofit.id, + # supporter_id: supporter.id, + # token: source_token.token, + # dedication: { 'name' => 'a name', 'type' => 'honor' }, + # designation: 'designation', + # campaign_id: campaign.id + # }.with_indifferent_access + # ) + # end + # end + + # before do + # before_each_success + # end + + # it 'has fired transaction.created' do + # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with( + # :transaction_created, { + # 'id' => match_houid('objevt'), + # 'object' => 'object_event', + # 'type' => 'transaction.created', + # 'data' => { + # 'object' => transaction_builder_expanded + # } + # } + # ) + # subject + # end + + # it 'has fired stripe_transaction_charge.created' do + # expect(Houdini.event_publisher).to receive(:announce).with( + # :stripe_transaction_charge_created, + # { + # 'id' => match_houid('objevt'), + # 'object' => 'object_event', + # 'type' => 'stripe_transaction_charge.created', + # 'data' => { + # 'object' => stripe_transaction_charge_builder_expanded + # } + # } + # ) + # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + # subject + # end + + # it 'has fired payment.created' do + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with( + # :payment_created, + # { + # 'id' => match_houid('objevt'), + # 'object' => 'object_event', + # 'type' => 'payment.created', + # 'data' => { + # 'object' => stripe_transaction_charge_builder_expanded + # } + # } + # ) + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + + # subject + # end + + # it 'has fired stripe_transaction.created' do + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with( + # :stripe_transaction_created, + # { + # 'id' => match_houid('objevt'), + # 'object' => 'object_event', + # 'type' => 'stripe_transaction.created', + # 'data' => { + # 'object' => stripe_transaction_builder_expanded + # } + # } + # ) + + # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + # subject + # end + + # it 'has fired donation.created' do + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with( + # :donation_created, + # { + # 'id' => match_houid('objevt'), + # 'object' => 'object_event', + # 'type' => 'donation.created', + # 'data' => { + # 'object' => donation_builder_expanded + # } + # } + # ) + # expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + # subject + # end + + # it 'has fired trx_assignment.created' do + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_charge_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:payment_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:stripe_transaction_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with(:donation_created, any_args) + # expect(Houdini.event_publisher).to receive(:announce).with( + # :trx_assignment_created, + # { + # 'id' => match_houid('objevt'), + # 'object' => 'object_event', + # 'type' => 'trx_assignment.created', + # 'data' => { + # 'object' => donation_builder_expanded + # } + # } + # ) + # expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args) + # subject + # end + # end + end end - describe 'future charge' do - before(:each) do + describe "future charge" do + before do before_each_success(false) end - it 'processes general donation' do - process_general_donation(expect_payment: false, expect_charge: false, recurring_donation: { paydate: (Time.now + 5.days).day, interval: 1, time_unit: 'month', start_date: (Time.now + 5.days).beginning_of_day }) do - InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, profile_id: profile.id, date: (Time.now + 1.day).to_s, dedication: {'type' => 'honor', 'name' => 'a name'}, designation: 'designation', recurring_donation: { start_date: (Time.now + 5.days).to_s }) + it "processes general donation" do + process_general_donation(expect_payment: false, expect_charge: false, recurring_donation: {paydate: (Time.now + 5.days).day, interval: 1, time_unit: "month", start_date: (Time.now + 5.days).beginning_of_day}) do + InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, profile_id: profile.id, date: (Time.now + 1.day).to_s, dedication: {"type" => "honor", "name" => "a name"}, designation: "designation", recurring_donation: {start_date: (Time.now + 5.days).to_s}) end end end end - - end - describe '.convert_donation_to_recurring_donation' do - describe 'wonderful testing Eric' do - before(:each) { Timecop.freeze(2020, 4, 29) } - after(:each) { Timecop.return } - let(:nonprofit) { force_create(:nm_justice, state_code_slug: 'wi', city_slug: 'city', slug: 'sluggster') } + describe ".convert_donation_to_recurring_donation" do + describe "wonderful testing Eric" do + before { Timecop.freeze(2020, 4, 29) } + after { Timecop.return } + + let(:nonprofit) { force_create(:nm_justice, state_code_slug: "wi", city_slug: "city", slug: "sluggster") } let(:profile) { force_create(:profile, user: force_create(:user)) } let(:supporter) { force_create(:supporter, nonprofit: nonprofit) } let(:card) { force_create(:card, holder: supporter) } let(:campaign) { force_create(:campaign, profile: profile, nonprofit: nonprofit) } let(:event) { force_create(:event, profile: profile, nonprofit: nonprofit) } let!(:donation) { force_create(:donation, nonprofit: nonprofit, supporter: supporter, amount: 4000, card: card, campaign: campaign, event: event) } - let!(:payment) { force_create(:payment, donation: donation, kind: 'Donation') } + let!(:payment) { force_create(:payment, donation: donation, kind: "Donation") } - it 'param validation' do + it "param validation" do expect { InsertRecurringDonation.convert_donation_to_recurring_donation(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :donation_id, name: :required }, { key: :donation_id, name: :is_integer }]) + expect_validation_errors(error.data, [{key: :donation_id, name: :required}, {key: :donation_id, name: :is_integer}]) end) end - it 'rejects invalid donation' do + it "rejects invalid donation" do expect { InsertRecurringDonation.convert_donation_to_recurring_donation(5555) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :donation_id }]) + expect_validation_errors(error.data, [{key: :donation_id}]) end) end - it 'accepts proper information' do + it "accepts proper information" do Timecop.freeze(2020, 5, 4) do rd = InsertRecurringDonation.convert_donation_to_recurring_donation(donation.id) # this needs some serious improvement - expected_rd = { id: rd.id, - donation_id: donation.id, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - updated_at: Time.now, - created_at: Time.now, - active: true, - n_failures: 0, - interval: 1, - time_unit: 'month', - start_date: donation.created_at.beginning_of_day, - paydate: 28, - profile_id: nil, - cancelled_at: nil, - cancelled_by: nil, - amount: 4000, - anonymous: nil, - card_id: nil, - campaign_id: nil, - failure_message: nil, - end_date: nil, - email: nil, - origin_url: nil }.with_indifferent_access - - expect(rd.attributes.except('edit_token')).to eq(expected_rd) + expected_rd = {id: rd.id, + donation_id: donation.id, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + updated_at: Time.now, + created_at: Time.now, + active: true, + n_failures: 0, + interval: 1, + time_unit: "month", + start_date: donation.created_at.beginning_of_day, + paydate: 28, + profile_id: nil, + cancelled_at: nil, + cancelled_by: nil, + amount: 4000, + anonymous: nil, + card_id: nil, + campaign_id: nil, + failure_message: nil, + end_date: nil, + email: nil, + origin_url: nil}.with_indifferent_access + + expect(rd.attributes.except("edit_token")).to eq(expected_rd) expect(rd.edit_token).to_not be_falsey expect(rd.donation.recurring).to eq true - expect(rd.donation.payment.kind).to eq 'RecurringDonation' + expect(rd.donation.payment.kind).to eq "RecurringDonation" end end end - describe 'test for earlier in the month' do - before(:each) { Timecop.freeze(2020, 4, 5) } - after(:each) { Timecop.return } - let(:nonprofit) { force_create(:nm_justice, state_code_slug: 'wi', city_slug: 'city', slug: 'sluggster') } + describe "test for earlier in the month" do + before { Timecop.freeze(2020, 4, 5) } + after { Timecop.return } + + let(:nonprofit) { force_create(:nm_justice, state_code_slug: "wi", city_slug: "city", slug: "sluggster") } let(:profile) { force_create(:profile, user: force_create(:user)) } let(:supporter) { force_create(:supporter, nonprofit: nonprofit) } let(:card) { force_create(:card, holder: supporter) } @@ -751,39 +755,40 @@ let(:event) { force_create(:event, profile: profile, nonprofit: nonprofit) } let!(:donation) { force_create(:donation, nonprofit: nonprofit, supporter: supporter, amount: 4000, card: card, campaign: campaign, event: event) } - let!(:payment) { force_create(:payment, donation: donation, kind: 'Donation') } - it 'works when the date is earlier in the month' do + let!(:payment) { force_create(:payment, donation: donation, kind: "Donation") } + + it "works when the date is earlier in the month" do Timecop.freeze(2020, 4, 29) do rd = InsertRecurringDonation.convert_donation_to_recurring_donation(donation.id) # this needs some serious improvement - expected_rd = { id: rd.id, - donation_id: donation.id, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - updated_at: Time.now, - created_at: Time.now, - active: true, - n_failures: 0, - interval: 1, - time_unit: 'month', - start_date: donation.created_at.beginning_of_day, - paydate: 5, - profile_id: nil, - cancelled_at: nil, - cancelled_by: nil, - amount: 4000, - anonymous: nil, - card_id: nil, - campaign_id: nil, - failure_message: nil, - end_date: nil, - email: nil, - origin_url: nil }.with_indifferent_access - expect(rd.attributes.except('edit_token')).to eq(expected_rd) + expected_rd = {id: rd.id, + donation_id: donation.id, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + updated_at: Time.now, + created_at: Time.now, + active: true, + n_failures: 0, + interval: 1, + time_unit: "month", + start_date: donation.created_at.beginning_of_day, + paydate: 5, + profile_id: nil, + cancelled_at: nil, + cancelled_by: nil, + amount: 4000, + anonymous: nil, + card_id: nil, + campaign_id: nil, + failure_message: nil, + end_date: nil, + email: nil, + origin_url: nil}.with_indifferent_access + expect(rd.attributes.except("edit_token")).to eq(expected_rd) expect(rd.donation.recurring).to eq true - expect(rd.donation.payment.kind).to eq 'RecurringDonation' + expect(rd.donation.payment.kind).to eq "RecurringDonation" expect(rd.edit_token).to_not be_falsey end diff --git a/spec/legacy_lib/insert/insert_refunds_spec.rb b/spec/legacy_lib/insert/insert_refunds_spec.rb index 652c570e34..53e43dd2cd 100644 --- a/spec/legacy_lib/insert/insert_refunds_spec.rb +++ b/spec/legacy_lib/insert/insert_refunds_spec.rb @@ -2,395 +2,395 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertRefunds do - let!(:nonprofit) { create(:nm_justice) } - let!(:supporter) { create(:supporter, nonprofit: nonprofit) } + let!(:nonprofit) { create(:nm_justice) } + let!(:supporter) { create(:supporter, nonprofit: nonprofit) } - let!(:payment) do - force_create( - :payment, - gross_amount: 500, - net_amount: CalculateFees.for_single_amount(500) + 500, - fee_total: CalculateFees.for_single_amount(500), - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter, - refund_total: 0 - ) - end + let!(:payment) do + force_create( + :payment, + gross_amount: 500, + net_amount: CalculateFees.for_single_amount(500) + 500, + fee_total: CalculateFees.for_single_amount(500), + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter, + refund_total: 0 + ) + end - let!(:charge) do - create( - :charge, - payment: payment, - stripe_charge_id: 'ch_s0m3th1ng', - nonprofit: nonprofit, - supporter: supporter, - amount: 500 - ) - end + let!(:charge) do + create( + :charge, + payment: payment, + stripe_charge_id: "ch_s0m3th1ng", + nonprofit: nonprofit, + supporter: supporter, + amount: 500 + ) + end - before do - trx = supporter.transactions.build(amount: 500) - trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: 500), - payments: [ - build(:subtransaction_payment, paymentable: create(:stripe_charge, payment: payment)) - ] - ) - trx.save! - trx - end + before do + trx = supporter.transactions.build(amount: 500) + trx.build_subtransaction( + subtransactable: StripeTransaction.new(amount: 500), + payments: [ + build(:subtransaction_payment, paymentable: create(:stripe_charge, payment: payment)) + ] + ) + trx.save! + trx + end - describe '.with_stripe' do - context 'when invalid' do - it 'raises an error with an invalid charge' do - charge.update(stripe_charge_id: 'xxx') - expect { described_class.with_stripe(charge, amount: 1) }.to raise_error(ParamValidation::ValidationError) - end + describe ".with_stripe" do + context "when invalid" do + it "raises an error with an invalid charge" do + charge.update(stripe_charge_id: "xxx") + expect { described_class.with_stripe(charge, amount: 1) }.to raise_error(ParamValidation::ValidationError) + end - it 'sets a failure message an error with an invalid amount' do - charge.update(amount: 0) - expect { described_class.with_stripe(charge, amount: 0) }.to raise_error(ParamValidation::ValidationError) - end + it "sets a failure message an error with an invalid amount" do + charge.update(amount: 0) + expect { described_class.with_stripe(charge, amount: 0) }.to raise_error(ParamValidation::ValidationError) + end - it 'returns err if refund amount is greater than payment gross minus payment refund total' do - expect { described_class.with_stripe(charge, 'amount' => 600) }.to raise_error(RuntimeError) - end - end + it "returns err if refund amount is greater than payment gross minus payment refund total" do + expect { described_class.with_stripe(charge, "amount" => 600) }.to raise_error(RuntimeError) + end + end - context 'when valid' do - let(:result) { described_class.with_stripe(charge, 'amount' => 100) } + context "when valid" do + let(:result) { described_class.with_stripe(charge, "amount" => 100) } - let(:retrieved_stripe_charge) { double } - let(:stripe_charge_refunds) { double } - let(:created_stripe_charge_refund) { double } + let(:retrieved_stripe_charge) { double } + let(:stripe_charge_refunds) { double } + let(:created_stripe_charge_refund) { double } - before do - allow(Stripe::Charge) - .to receive(:retrieve) - .with('ch_s0m3th1ng') - .and_return(retrieved_stripe_charge) - allow(retrieved_stripe_charge) - .to receive(:refunds) - .and_return(stripe_charge_refunds) - allow(stripe_charge_refunds) - .to receive(:create) - .with({ 'amount' => 100, 'refund_application_fee' => true, 'reverse_transfer' => true }) - .and_return(created_stripe_charge_refund) - allow(created_stripe_charge_refund) - .to receive(:id) - .and_return('re_f@k3') - end + before do + allow(Stripe::Charge) + .to receive(:retrieve) + .with("ch_s0m3th1ng") + .and_return(retrieved_stripe_charge) + allow(retrieved_stripe_charge) + .to receive(:refunds) + .and_return(stripe_charge_refunds) + allow(stripe_charge_refunds) + .to receive(:create) + .with({"amount" => 100, "refund_application_fee" => true, "reverse_transfer" => true}) + .and_return(created_stripe_charge_refund) + allow(created_stripe_charge_refund) + .to receive(:id) + .and_return("re_f@k3") + end - it 'sets the stripe refund id' do - expect(result['refund']['stripe_refund_id']).to match(/^re_/) - end + it "sets the stripe refund id" do + expect(result["refund"]["stripe_refund_id"]).to match(/^re_/) + end - it 'creates a negative payment for the refund with the gross amount' do - expect(result['payment']['gross_amount']).to eq(-100) - end + it "creates a negative payment for the refund with the gross amount" do + expect(result["payment"]["gross_amount"]).to eq(-100) + end - it 'creates a negative payment for the refund with the net amount' do - expect(result['payment']['net_amount']).to eq(-109) - end + it "creates a negative payment for the refund with the net amount" do + expect(result["payment"]["net_amount"]).to eq(-109) + end - it 'updates the payment_id on the refund' do - expect(result['refund']['payment_id']).to eq(result['payment']['id']) - end + it "updates the payment_id on the refund" do + expect(result["refund"]["payment_id"]).to eq(result["payment"]["id"]) + end - it 'increments the payment refund total by the gross amount' do - result - expect(payment.reload['refund_total']).to eq(100) - end + it "increments the payment refund total by the gross amount" do + result + expect(payment.reload["refund_total"]).to eq(100) + end - it 'sets the payment supporter id' do - expect(result['payment']['supporter_id']).to eq(supporter['id']) - end + it "sets the payment supporter id" do + expect(result["payment"]["supporter_id"]).to eq(supporter["id"]) + end - describe 'event publishing' do - let(:event_publisher) { double } - let(:expected_event) do - { - 'data' => { - 'object' => { - 'created' => kind_of(Numeric), - 'fee_total' => { - 'cents' => -9, 'currency' => nonprofit.currency - }, - 'gross_amount' => { - 'cents' => -100, 'currency' => nonprofit.currency - }, - 'id' => match_houid('striperef'), - 'stripe_id' => kind_of(String), - 'net_amount' => { - 'cents' => -109, 'currency' => nonprofit.currency - }, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'stripe_transaction_refund', - 'subtransaction' => { - 'created' => kind_of(Numeric), - 'id' => match_houid('stripetrx'), - 'initial_amount' => { - 'cents' => 500, 'currency' => nonprofit.currency - }, - 'net_amount' => { - 'cents' => 432, 'currency' => nonprofit.currency - }, - 'nonprofit' => nonprofit.id, - 'object' => 'stripe_transaction', - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, - { - 'id' => match_houid('striperef'), - 'object' => 'stripe_transaction_refund', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'subtransaction' - }, - 'supporter' => { - 'anonymous' => supporter.anonymous, - 'deleted' => supporter.deleted, - 'id' => supporter.id, - 'merged_into' => supporter.merged_into, - 'name' => supporter.name, - 'nonprofit' => nonprofit.id, - 'object' => 'supporter', - 'organization' => supporter.organization, - 'phone' => supporter.phone, - 'supporter_addresses' => [kind_of(Numeric)] - }, - 'transaction' => { - 'amount' => { - 'cents' => 400, 'currency' => nonprofit.currency - }, - 'created' => kind_of(Numeric), - 'id' => match_houid('trx'), - 'nonprofit' => nonprofit.id, - 'object' => 'transaction', - 'subtransaction' => { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - }, - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, { - 'id' => match_houid('striperef'), - 'object' => 'stripe_transaction_refund', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction_assignments' => [] - }, - 'type' => 'payment' - } - }, - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'event_type' - } - end + describe "event publishing" do + let(:event_publisher) { double } + let(:expected_event) do + { + "data" => { + "object" => { + "created" => kind_of(Numeric), + "fee_total" => { + "cents" => -9, "currency" => nonprofit.currency + }, + "gross_amount" => { + "cents" => -100, "currency" => nonprofit.currency + }, + "id" => match_houid("striperef"), + "stripe_id" => kind_of(String), + "net_amount" => { + "cents" => -109, "currency" => nonprofit.currency + }, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "stripe_transaction_refund", + "subtransaction" => { + "created" => kind_of(Numeric), + "id" => match_houid("stripetrx"), + "initial_amount" => { + "cents" => 500, "currency" => nonprofit.currency + }, + "net_amount" => { + "cents" => 432, "currency" => nonprofit.currency + }, + "nonprofit" => nonprofit.id, + "object" => "stripe_transaction", + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, + { + "id" => match_houid("striperef"), + "object" => "stripe_transaction_refund", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "subtransaction" + }, + "supporter" => { + "anonymous" => supporter.anonymous, + "deleted" => supporter.deleted, + "id" => supporter.id, + "merged_into" => supporter.merged_into, + "name" => supporter.name, + "nonprofit" => nonprofit.id, + "object" => "supporter", + "organization" => supporter.organization, + "phone" => supporter.phone, + "supporter_addresses" => [kind_of(Numeric)] + }, + "transaction" => { + "amount" => { + "cents" => 400, "currency" => nonprofit.currency + }, + "created" => kind_of(Numeric), + "id" => match_houid("trx"), + "nonprofit" => nonprofit.id, + "object" => "transaction", + "subtransaction" => { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + }, + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, { + "id" => match_houid("striperef"), + "object" => "stripe_transaction_refund", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction_assignments" => [] + }, + "type" => "payment" + } + }, + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "event_type" + } + end - let(:expected_transaction_event) do - { - 'data' => { - 'object' => { - 'amount' => { - 'cents' => 400, - 'currency' => nonprofit.currency - }, - 'created' => kind_of(Numeric), - 'id' => match_houid('trx'), - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'transaction', - 'subtransaction' => { - 'created' => kind_of(Numeric), - 'id' => match_houid('stripetrx'), - 'initial_amount' => { - 'cents' => 500, - 'currency' => nonprofit.currency - }, - 'net_amount' => { - 'cents' => 432, - 'currency' => nonprofit.currency - }, - 'nonprofit' => nonprofit.id, - 'object' => 'stripe_transaction', - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, { - 'id' => match_houid('striperef'), - 'object' => 'stripe_transaction_refund', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'subtransaction' - }, - 'payments' => [ - { - 'created' => kind_of(Numeric), - 'fee_total' => { - 'cents' => 41, - 'currency' => nonprofit.currency - }, - 'gross_amount' => { - 'cents' => 500, - 'currency' => nonprofit.currency - }, - 'id' => match_houid('stripechrg'), - 'net_amount' => { - 'cents' => 541, - 'currency' => nonprofit.currency - }, - 'nonprofit' => nonprofit.id, - 'object' => 'stripe_transaction_charge', - 'stripe_id' => 'ch_s0m3th1ng', - 'subtransaction' => { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - }, - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'payment' - }, { - 'created' => kind_of(Numeric), - 'fee_total' => { - 'cents' => -9, - 'currency' => nonprofit.currency - }, - 'gross_amount' => { - 'cents' => -100, - 'currency' => nonprofit.currency - }, - 'id' => match_houid('striperef'), - 'net_amount' => { - 'cents' => -109, - 'currency' => nonprofit.currency - }, - 'nonprofit' => nonprofit.id, - 'object' => 'stripe_transaction_refund', - 'stripe_id' => 're_f@k3', - 'subtransaction' => { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - }, - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'payment' - } - ], - 'supporter' => { - 'anonymous' => false, - 'deleted' => false, - 'id' => supporter.id, - 'merged_into' => nil, - 'name' => supporter.name, - 'nonprofit' => nonprofit.id, - 'object' => 'supporter', - 'organization' => nil, - 'phone' => nil, - 'supporter_addresses' => [kind_of(Numeric)] - }, - 'transaction_assignments' => [] - } - }, - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'transaction.updated' - } - end + let(:expected_transaction_event) do + { + "data" => { + "object" => { + "amount" => { + "cents" => 400, + "currency" => nonprofit.currency + }, + "created" => kind_of(Numeric), + "id" => match_houid("trx"), + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "transaction", + "subtransaction" => { + "created" => kind_of(Numeric), + "id" => match_houid("stripetrx"), + "initial_amount" => { + "cents" => 500, + "currency" => nonprofit.currency + }, + "net_amount" => { + "cents" => 432, + "currency" => nonprofit.currency + }, + "nonprofit" => nonprofit.id, + "object" => "stripe_transaction", + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, { + "id" => match_houid("striperef"), + "object" => "stripe_transaction_refund", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "subtransaction" + }, + "payments" => [ + { + "created" => kind_of(Numeric), + "fee_total" => { + "cents" => 41, + "currency" => nonprofit.currency + }, + "gross_amount" => { + "cents" => 500, + "currency" => nonprofit.currency + }, + "id" => match_houid("stripechrg"), + "net_amount" => { + "cents" => 541, + "currency" => nonprofit.currency + }, + "nonprofit" => nonprofit.id, + "object" => "stripe_transaction_charge", + "stripe_id" => "ch_s0m3th1ng", + "subtransaction" => { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + }, + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "payment" + }, { + "created" => kind_of(Numeric), + "fee_total" => { + "cents" => -9, + "currency" => nonprofit.currency + }, + "gross_amount" => { + "cents" => -100, + "currency" => nonprofit.currency + }, + "id" => match_houid("striperef"), + "net_amount" => { + "cents" => -109, + "currency" => nonprofit.currency + }, + "nonprofit" => nonprofit.id, + "object" => "stripe_transaction_refund", + "stripe_id" => "re_f@k3", + "subtransaction" => { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + }, + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "payment" + } + ], + "supporter" => { + "anonymous" => false, + "deleted" => false, + "id" => supporter.id, + "merged_into" => nil, + "name" => supporter.name, + "nonprofit" => nonprofit.id, + "object" => "supporter", + "organization" => nil, + "phone" => nil, + "supporter_addresses" => [kind_of(Numeric)] + }, + "transaction_assignments" => [] + } + }, + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "transaction.updated" + } + end - before do - allow(Houdini) - .to receive(:event_publisher) - .and_return(event_publisher) + before do + allow(Houdini) + .to receive(:event_publisher) + .and_return(event_publisher) - allow(event_publisher) - .to receive(:announce) - .with(:payment_created, anything) + allow(event_publisher) + .to receive(:announce) + .with(:payment_created, anything) - allow(event_publisher) - .to receive(:announce) - .with(:stripe_transaction_refund_created, anything) + allow(event_publisher) + .to receive(:announce) + .with(:stripe_transaction_refund_created, anything) - allow(event_publisher) - .to receive(:announce) - .with(:transaction_refunded, anything) + allow(event_publisher) + .to receive(:announce) + .with(:transaction_refunded, anything) - allow(event_publisher) - .to receive(:announce) - .with(:transaction_updated, anything) + allow(event_publisher) + .to receive(:announce) + .with(:transaction_updated, anything) - allow(event_publisher) - .to receive(:announce) - .with(:create_refund, anything) + allow(event_publisher) + .to receive(:announce) + .with(:create_refund, anything) - result - end + result + end - it 'publishes that a transaction was updated' do - expected_transaction_event['type'] = 'transaction.updated' - expect(event_publisher) - .to have_received(:announce) - .with(:transaction_updated, expected_transaction_event) - end + it "publishes that a transaction was updated" do + expected_transaction_event["type"] = "transaction.updated" + expect(event_publisher) + .to have_received(:announce) + .with(:transaction_updated, expected_transaction_event) + end - it 'publishes that a transaction was refunded' do - expected_transaction_event['type'] = 'transaction.refunded' - expect(event_publisher) - .to have_received(:announce) - .with(:transaction_refunded, expected_transaction_event) - end + it "publishes that a transaction was refunded" do + expected_transaction_event["type"] = "transaction.refunded" + expect(event_publisher) + .to have_received(:announce) + .with(:transaction_refunded, expected_transaction_event) + end - it 'publishes that a stripe_transaction_refund was created' do - expected_event['type'] = 'stripe_transaction_refund.created' - expect(event_publisher) - .to have_received(:announce) - .with(:stripe_transaction_refund_created, expected_event) - end + it "publishes that a stripe_transaction_refund was created" do + expected_event["type"] = "stripe_transaction_refund.created" + expect(event_publisher) + .to have_received(:announce) + .with(:stripe_transaction_refund_created, expected_event) + end - it 'publishes that a payment was created' do - expected_event['type'] = 'payment.created' - expect(event_publisher) - .to have_received(:announce) - .with(:payment_created, expected_event) - end + it "publishes that a payment was created" do + expected_event["type"] = "payment.created" + expect(event_publisher) + .to have_received(:announce) + .with(:payment_created, expected_event) + end - it 'publishes that a refund was created' do - expect(event_publisher) - .to have_received(:announce) - .with(:create_refund, kind_of(Refund)) - end - end - end - end + it "publishes that a refund was created" do + expect(event_publisher) + .to have_received(:announce) + .with(:create_refund, kind_of(Refund)) + end + end + end + end end diff --git a/spec/legacy_lib/insert/insert_source_token_spec.rb b/spec/legacy_lib/insert/insert_source_token_spec.rb index 7ba94e724b..8ee51c5fc5 100644 --- a/spec/legacy_lib/insert/insert_source_token_spec.rb +++ b/spec/legacy_lib/insert/insert_source_token_spec.rb @@ -2,46 +2,51 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertSourceToken do - describe '.create_record' do + describe ".create_record" do let(:event) { force_create(:event, end_datetime: Time.now + 1.day) } - describe 'param validation' do - it 'validates tokenizable' do + + describe "param validation" do + it "validates tokenizable" do expect { InsertSourceToken.create_record(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :tokenizable, name: :required }]) + expect_validation_errors(error.data, [{key: :tokenizable, name: :required}]) end) end - it 'validates params' do - expect { InsertSourceToken.create_record(nil, event: '', expiration_time: 'j', max_uses: 'j') }.to(raise_error do |error| + it "validates params" do + expect { InsertSourceToken.create_record(nil, event: "", expiration_time: "j", max_uses: "j") }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :tokenizable, name: :required }, - { key: :event, name: :is_a }, - { key: :expiration_time, name: :is_integer }, - { key: :expiration_time, name: :min }, - { key: :max_uses, name: :is_integer }, - { key: :max_uses, name: :min } - ]) + {key: :tokenizable, name: :required}, + {key: :event, name: :is_a}, + {key: :expiration_time, name: :is_integer}, + {key: :expiration_time, name: :min}, + {key: :max_uses, name: :is_integer}, + {key: :max_uses, name: :min} + ]) end) end end - describe 'handles default' do - it 'without event' do + + describe "handles default" do + it "without event" do Timecop.freeze(2025, 4, 5) do ouruuid = nil tokenizable = Card.create! - expect(SecureRandom).to receive(:uuid).and_wrap_original { |m| ouruuid = m.call; ouruuid } + expect(SecureRandom).to receive(:uuid).and_wrap_original { |m| + ouruuid = m.call + ouruuid + } result = InsertSourceToken.create_record(tokenizable) expected = { tokenizable_id: tokenizable.id, - tokenizable_type: 'Card', + tokenizable_type: "Card", token: ouruuid, expiration: Time.now.since(20.minutes), created_at: Time.now, @@ -57,17 +62,15 @@ end end - it 'with event' do + it "with event" do Timecop.freeze(2025, 4, 5) do - ouruuid = nil - tokenizable = Card.create! result = InsertSourceToken.create_record(tokenizable, event: event) expected = { tokenizable_id: tokenizable.id, - tokenizable_type: 'Card', + tokenizable_type: "Card", expiration: Time.now + 1.day + 20.days, created_at: Time.now, updated_at: Time.now, @@ -76,51 +79,47 @@ event_id: event.id }.with_indifferent_access - expect(result.attributes.except('token')).to eq expected + expect(result.attributes.except("token")).to eq expected - expect(SourceToken.last.attributes.except('token')).to eq expected + expect(SourceToken.last.attributes.except("token")).to eq expected expect(result[:token]).to be_a String end end end - describe 'handles passed in data' do - it 'without event' do - Timecop.freeze(2025, 4, 5) do - ouruuid = nil + describe "handles passed in data" do + it "without event" do + Timecop.freeze(2025, 4, 5) do tokenizable = Card.create! result = InsertSourceToken.create_record(tokenizable, max_uses: 50, expiration_time: 3600) - expected = { tokenizable_id: tokenizable.id, - tokenizable_type: 'Card', - expiration: Time.now.since(1.hour), - created_at: Time.now, - updated_at: Time.now, - total_uses: 0, - max_uses: 50, - event_id: nil }.with_indifferent_access + expected = {tokenizable_id: tokenizable.id, + tokenizable_type: "Card", + expiration: Time.now.since(1.hour), + created_at: Time.now, + updated_at: Time.now, + total_uses: 0, + max_uses: 50, + event_id: nil}.with_indifferent_access expect(result.attributes.with_indifferent_access.except(:token)).to eq expected - - expect(SourceToken.last.attributes.except('token')).to eq expected + expect(SourceToken.last.attributes.except("token")).to eq expected expect(result.token).to be_a String end end - it 'with event' do + it "with event" do Timecop.freeze(2025, 4, 5) do - ouruuid = nil - tokenizable = Card.create! result = InsertSourceToken.create_record(tokenizable, max_uses: 50, expiration_time: 3600, event: event) expected = { tokenizable_id: tokenizable.id, - tokenizable_type: 'Card', + tokenizable_type: "Card", expiration: Time.now.since(1.day).since(1.hour), created_at: Time.now, updated_at: Time.now, @@ -130,7 +129,7 @@ }.with_indifferent_access expect(result.attributes.with_indifferent_access.except(:token)).to eq expected - expect(SourceToken.last.attributes.except('token')).to eq expected + expect(SourceToken.last.attributes.except("token")).to eq expected expect(result.token).to be_a String end end diff --git a/spec/legacy_lib/insert/insert_supporter_notes_spec.rb b/spec/legacy_lib/insert/insert_supporter_notes_spec.rb index 1e8f35f12c..c29016cdea 100644 --- a/spec/legacy_lib/insert/insert_supporter_notes_spec.rb +++ b/spec/legacy_lib/insert/insert_supporter_notes_spec.rb @@ -2,36 +2,37 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertSupporterNotes do include_context :shared_rd_donation_value_context - let(:content) { "CONTENT"} - let(:content_2) {"CONTENT 2"} - let(:sn_first) {SupporterNote.first } - let(:sn_last) {SupporterNote.last } - it '.create' do - InsertSupporterNotes.create({supporter: supporter, user: user, content: content}, + let(:content) { "CONTENT" } + let(:content_2) { "CONTENT 2" } + let(:sn_first) { SupporterNote.first } + let(:sn_last) { SupporterNote.last } + + it ".create" do + InsertSupporterNotes.create({supporter: supporter, user: user, content: content}, {supporter: supporter, user: user, content: content_2}) expect(SupporterNote.count).to eq 2 - expect(sn_first.attributes.except('id')).to eq({ - 'content' => content, - 'user_id' => user.id, - 'deleted' => false, - 'supporter_id' => supporter.id, - 'created_at' => Time.now, - 'updated_at' => Time.now + expect(sn_first.attributes.except("id")).to eq({ + "content" => content, + "user_id" => user.id, + "deleted" => false, + "supporter_id" => supporter.id, + "created_at" => Time.now, + "updated_at" => Time.now }) expect(sn_first.activities.count).to eq 1 - expect(sn_last.attributes.except('id')).to eq({ - 'content' => content_2, - 'user_id' => user.id, - 'deleted' => false, - 'supporter_id' => supporter.id, - 'created_at' => Time.now, - 'updated_at' => Time.now + expect(sn_last.attributes.except("id")).to eq({ + "content" => content_2, + "user_id" => user.id, + "deleted" => false, + "supporter_id" => supporter.id, + "created_at" => Time.now, + "updated_at" => Time.now }) expect(sn_last.activities.count).to eq 1 end diff --git a/spec/legacy_lib/insert/insert_tag_joins_spec.rb b/spec/legacy_lib/insert/insert_tag_joins_spec.rb index 23c6e7839d..1204738b24 100644 --- a/spec/legacy_lib/insert/insert_tag_joins_spec.rb +++ b/spec/legacy_lib/insert/insert_tag_joins_spec.rb @@ -2,80 +2,79 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -describe 'InsertTagJoins.in_bulk' do - context 'parameter validation' do - it 'should validate parameters' do - response = InsertTagJoins.in_bulk(nil, nil, 'no', nil) +describe "InsertTagJoins.in_bulk" do + context "parameter validation" do + it "should validate parameters" do + response = InsertTagJoins.in_bulk(nil, nil, "no", nil) errors = response[:json][:errors] expect(errors.length).to eq(6) expect(response[:status]).to eq :unprocessable_entity expect_validation_errors(errors, [ - { key: :np_id, name: :required }, - { key: :np_id, name: :is_integer }, - { key: :profile_id, name: :required }, - { key: :profile_id, name: :is_integer }, - { key: :supporter_ids, name: :is_array }, - { key: :tag_data, name: :required } - ]) + {key: :np_id, name: :required}, + {key: :np_id, name: :is_integer}, + {key: :profile_id, name: :required}, + {key: :profile_id, name: :is_integer}, + {key: :supporter_ids, name: :is_array}, + {key: :tag_data, name: :required} + ]) end - context 'requiring db' do + context "requiring db" do before do @nonprofit = force_create(:nm_justice) @profile = force_create(:profile) end - it 'nonprofit must be valid' do + it "nonprofit must be valid" do response = InsertTagJoins.in_bulk(@nonprofit.id + 1, @profile.id, [1], []) expect(response[:status]).to eq :unprocessable_entity expect(response[:json][:error]).to include("Nonprofit #{@nonprofit.id + 1} is not valid") end - it 'profile must be valid' do + it "profile must be valid" do response = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id + 1, [1], []) expect(response[:status]).to eq :unprocessable_entity expect(response[:json][:error]).to include("Profile #{@profile.id + 1} is not valid") end - it 'supporters if empty should do nothing' do + it "supporters if empty should do nothing" do response = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, [], []) expect(response).to eq(successful_json(0, 0)) end end end - context 'supporters tags' do - before(:each) do + context "supporters tags" do + before do @nonprofit = force_create(:nm_justice) @profile = force_create(:profile) @other_nonprofit = force_create(:fv_poverty) @random_supporter = create(:supporter, nonprofit: @other_nonprofit) - @delete_tags = [20, 40, 60] @add_tags = [25, 35] @supporters = { np_supporter_with_add: { - creation_hash: { nonprofit: @nonprofit }, + creation_hash: {nonprofit: @nonprofit}, tag_ids: [65, 75, 85] }, np_supporter_with_tags_to_delete: { - creation_hash: { nonprofit: @nonprofit }, + creation_hash: {nonprofit: @nonprofit}, tag_ids: [40, 75, 85] }, np_supporter_with_no_changes: { - creation_hash: { nonprofit: @nonprofit }, + creation_hash: {nonprofit: @nonprofit}, tag_ids: @add_tags }, np_supporter_with_some_of_both: { - creation_hash: { nonprofit: @nonprofit }, + creation_hash: {nonprofit: @nonprofit}, tag_ids: [20, 35] }, supporter_from_other_np: { - creation_hash: { nonprofit: @other_nonprofit }, + creation_hash: {nonprofit: @other_nonprofit}, tag_ids: [100, 150, 200] } @@ -114,59 +113,59 @@ end end - it 'invalid nonprofit-supporter combo returns okay' do + it "invalid nonprofit-supporter combo returns okay" do results = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, [@supporters[:supporter_from_other_np][:entity].id], {}) expect(results).to eq(successful_json(0, 0)) end - it 'strips tags which dont belong to nonprofit' do + it "strips tags which dont belong to nonprofit" do results = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, [@supporters[:np_supporter_with_add][:entity].id], - create_tag_data([100], [150])) + create_tag_data([100], [150])) expect(results).to eq(successful_json(0, 0)) - expect(TagJoin.where('supporter_id = ? and tag_definition_id = ?', @supporters[:np_supporter_with_add][:entity].id, 100).count).to eq 0 + expect(TagJoin.where("supporter_id = ? and tag_definition_id = ?", @supporters[:np_supporter_with_add][:entity].id, 100).count).to eq 0 end - it 'delete' do + it "delete" do expect(TagJoin.count).to eq 13 @supporters[:np_supporter_with_some_of_both][:entity].id - results = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, - [@supporters[:np_supporter_with_some_of_both][:entity].id, @supporters[:np_supporter_with_tags_to_delete][:entity].id, @supporters[:np_supporter_with_add][:entity].id, @supporters[:supporter_from_other_np][:entity].id, @supporters[:np_supporter_with_no_changes][:entity].id], - create_tag_data(@add_tags, @delete_tags)) + InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, + [@supporters[:np_supporter_with_some_of_both][:entity].id, @supporters[:np_supporter_with_tags_to_delete][:entity].id, @supporters[:np_supporter_with_add][:entity].id, @supporters[:supporter_from_other_np][:entity].id, @supporters[:np_supporter_with_no_changes][:entity].id], + create_tag_data(@add_tags, @delete_tags)) - expect(TagJoin.where('supporter_id = ? ', @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 + expect(TagJoin.where("supporter_id = ? ", @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 - expect(TagJoin.where('supporter_id = ?', @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 + expect(TagJoin.where("supporter_id = ?", @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 - expect(TagJoin.where('supporter_id = ?', @supporters[:np_supporter_with_tags_to_delete][:entity].id).count).to eq 4 + expect(TagJoin.where("supporter_id = ?", @supporters[:np_supporter_with_tags_to_delete][:entity].id).count).to eq 4 - expect(TagJoin.where('supporter_id = ?', @supporters[:supporter_from_other_np][:entity].id).count).to eq 3 + expect(TagJoin.where("supporter_id = ?", @supporters[:supporter_from_other_np][:entity].id).count).to eq 3 - expect(TagJoin.where('supporter_id = ?', @supporters[:np_supporter_with_no_changes][:entity].id).count).to eq 2 + expect(TagJoin.where("supporter_id = ?", @supporters[:np_supporter_with_no_changes][:entity].id).count).to eq 2 expect(TagJoin.count).to eq 16 end - it 'id, updated_at, created_at changes are stripped' do + it "id, updated_at, created_at changes are stripped" do invalid_id = 10_000_000 Timecop.freeze(2020, 9, 1, 12, 0, 0) do results = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, - [@supporters[:np_supporter_with_add][:entity].id], - [{ tag_definition_id: 25, selected: true, id: invalid_id, created_at: Time.now.ago(3000), updated_at: Time.now.ago(2999) }]) - expected = { tag_definition_id: 25, created_at: Time.now, updated_at: Time.now, supporter_id: @supporters[:np_supporter_with_add][:entity].id }.with_indifferent_access + [@supporters[:np_supporter_with_add][:entity].id], + [{tag_definition_id: 25, selected: true, id: invalid_id, created_at: Time.now.ago(3000), updated_at: Time.now.ago(2999)}]) + expected = {tag_definition_id: 25, created_at: Time.now, updated_at: Time.now, supporter_id: @supporters[:np_supporter_with_add][:entity].id}.with_indifferent_access expect(results).to eq(successful_json(1, 0)) - result_tag = @supporters[:np_supporter_with_add][:entity].tag_joins.where('tag_definition_id = ?', 25).first + result_tag = @supporters[:np_supporter_with_add][:entity].tag_joins.where("tag_definition_id = ?", 25).first - expect(result_tag.attributes.with_indifferent_access.reject { |k, _| k == 'id' }).to eq(expected) + expect(result_tag.attributes.with_indifferent_access.reject { |k, _| k == "id" }).to eq(expected) expect(result_tag.attributes[:id]).to_not eq invalid_id end end - it 'add_to_one' do + it "add_to_one" do expect(TagJoin.count).to eq 13 np_supporter_with_add_tags = @supporters[:np_supporter_with_add][:entity].tag_joins.to_a @@ -175,37 +174,37 @@ Timecop.travel(20) do results = InsertTagJoins.in_bulk(@nonprofit.id, @profile.id, - [ - @supporters[:np_supporter_with_add][:entity].id, # add 2 - @supporters[:np_supporter_with_no_changes][:entity], # update 2 - @supporters[:np_supporter_with_some_of_both][:entity].id - ], # add 2, delete 1 - create_tag_data(@add_tags, @delete_tags)) + [ + @supporters[:np_supporter_with_add][:entity].id, # add 2 + @supporters[:np_supporter_with_no_changes][:entity], # update 2 + @supporters[:np_supporter_with_some_of_both][:entity].id + ], # add 2, delete 1 + create_tag_data(@add_tags, @delete_tags)) expect(results).to eq(successful_json(6, 1)) expect(@supporters[:np_supporter_with_no_changes][:entity].tag_joins).to match_array(np_supporter_with_no_changes_tags) - expect(TagJoin.where('supporter_id = ? ', @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 + expect(TagJoin.where("supporter_id = ? ", @supporters[:np_supporter_with_add][:entity].id).count).to eq 5 - original_db_pairs = get_original_and_db(np_supporter_with_add_tags, TagJoin.where('supporter_id = ? and tag_definition_id in (?)', - @supporters[:np_supporter_with_add][:entity].id, - @supporters[:np_supporter_with_add][:tag_ids]).pluck(:id)) + original_db_pairs = get_original_and_db(np_supporter_with_add_tags, TagJoin.where("supporter_id = ? and tag_definition_id in (?)", + @supporters[:np_supporter_with_add][:entity].id, + @supporters[:np_supporter_with_add][:tag_ids]).pluck(:id)) original_db_pairs.each do |orig, db| expect(orig.attributes.length).to eq(db.attributes.length) expect(orig.attributes).to eq(db.attributes) end - expect(TagJoin.where('supporter_id = ?', @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 + expect(TagJoin.where("supporter_id = ?", @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2 - original_db_pairs = get_original_and_db(np_supporter_with_some_of_both_tags, TagJoin.where('supporter_id = ? and tag_definition_id in (?)', - @supporters[:np_supporter_with_some_of_both][:entity].id, - [35]).pluck(:id)) + original_db_pairs = get_original_and_db(np_supporter_with_some_of_both_tags, TagJoin.where("supporter_id = ? and tag_definition_id in (?)", + @supporters[:np_supporter_with_some_of_both][:entity].id, + [35]).pluck(:id)) original_db_pairs.each do |orig, db| expect(orig.attributes.length).to eq(db.attributes.length) - expect(orig.attributes.reject { |key, _value| key == 'updated_at' }).to eq(db.attributes.reject { |key, _value| key == 'updated_at' }) - expect(orig.attributes['updated_at']).to be < db.attributes['updated_at'] + expect(orig.attributes.reject { |key, _value| key == "updated_at" }).to eq(db.attributes.reject { |key, _value| key == "updated_at" }) + expect(orig.attributes["updated_at"]).to be < db.attributes["updated_at"] end expect(TagJoin.count).to eq 15 @@ -222,10 +221,10 @@ def get_original_and_db(original_items, ids_to_verify) end def successful_json(inserted, deleted) - { json: { inserted_count: inserted, removed_count: deleted }, status: :ok } + {json: {inserted_count: inserted, removed_count: deleted}, status: :ok} end def create_tag_data(tags_to_add = [], tags_to_delete = []) - tags_to_add.map { |tag| { tag_definition_id: tag, selected: true } } + tags_to_delete.map { |tag| { tag_definition_id: tag, selected: false } } + tags_to_add.map { |tag| {tag_definition_id: tag, selected: true} } + tags_to_delete.map { |tag| {tag_definition_id: tag, selected: false} } end end diff --git a/spec/legacy_lib/insert/insert_tickets_spec.rb b/spec/legacy_lib/insert/insert_tickets_spec.rb index e27112db5a..c26612b16f 100644 --- a/spec/legacy_lib/insert/insert_tickets_spec.rb +++ b/spec/legacy_lib/insert/insert_tickets_spec.rb @@ -2,12 +2,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe InsertTickets do before do Houdini.payment_providers.stripe.connect = true end + include_context :shared_rd_donation_value_context # @param [Object] data @@ -22,7 +23,7 @@ def generate_expected_tickets(data = {}) fee_total: -1 * data[:payment_fee_total], gross_amount: amount, id: data[:payment_id] || 55_555, - kind: data[:kind] || 'Ticket', + kind: data[:kind] || "Ticket", net_amount: amount - data[:payment_fee_total], nonprofit_id: data[:nonprofit].id, refund_total: 0, @@ -66,7 +67,7 @@ def generate_expected_tickets(data = {}) failure_message: nil, payment_id: data[:payment_id] || 55_555, nonprofit_id: data[:nonprofit].id, - status: 'pending', + status: "pending", profile_id: nil, supporter_id: data[:supporter].id, @@ -112,83 +113,83 @@ def success_expectations tickets } end - describe '.create' do - it 'does basic validation' do + describe ".create" do + it "does basic validation" do expect do - InsertTickets.create(event_discount_id: 'etheht', - kind: 'blah', - token: 'none') - end .to raise_error { |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [ - { key: :tickets, name: :required }, - { key: :tickets, name: :is_array }, - { key: :nonprofit_id, name: :required }, - { key: :nonprofit_id, name: :is_reference }, - { key: :supporter_id, name: :required }, - { key: :supporter_id, name: :is_reference }, - { key: :event_discount_id, name: :is_reference }, - { key: :kind, name: :included_in }, - { key: :token, name: :format }, - { key: :event_id, name: :is_reference }, - { key: :event_id, name: :required } - ]) - } + InsertTickets.create(event_discount_id: "etheht", + kind: "blah", + token: "none") + end.to raise_error { |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, [ + {key: :tickets, name: :required}, + {key: :tickets, name: :is_array}, + {key: :nonprofit_id, name: :required}, + {key: :nonprofit_id, name: :is_reference}, + {key: :supporter_id, name: :required}, + {key: :supporter_id, name: :is_reference}, + {key: :event_discount_id, name: :is_reference}, + {key: :kind, name: :included_in}, + {key: :token, name: :format}, + {key: :event_id, name: :is_reference}, + {key: :event_id, name: :required} + ]) + } # test that the quantity ticket_level validation works (it really doesn't very well) expect do - InsertTickets.create(event_discount_id: 'etheht', - kind: 'blah', - token: 'none', tickets: 2, offsite_payment: 'bhb') - end .to raise_error { |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [ - { key: :tickets, name: :is_array }, - { key: :nonprofit_id, name: :required }, - { key: :nonprofit_id, name: :is_reference }, - { key: :supporter_id, name: :required }, - { key: :supporter_id, name: :is_reference }, - { key: :event_id, name: :is_reference }, - { key: :event_id, name: :required }, - { key: :event_discount_id, name: :is_reference }, - { key: :kind, name: :included_in }, - { key: :token, name: :format }, - { key: :offsite_payment, name: :is_hash } - ]) - } + InsertTickets.create(event_discount_id: "etheht", + kind: "blah", + token: "none", tickets: 2, offsite_payment: "bhb") + end.to raise_error { |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, [ + {key: :tickets, name: :is_array}, + {key: :nonprofit_id, name: :required}, + {key: :nonprofit_id, name: :is_reference}, + {key: :supporter_id, name: :required}, + {key: :supporter_id, name: :is_reference}, + {key: :event_id, name: :is_reference}, + {key: :event_id, name: :required}, + {key: :event_discount_id, name: :is_reference}, + {key: :kind, name: :included_in}, + {key: :token, name: :format}, + {key: :offsite_payment, name: :is_hash} + ]) + } end - it 'validates the ticket hashes' do + it "validates the ticket hashes" do expect do InsertTickets.create(nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - event_id: event.id, - tickets: [{ quantity: 1, ticket_level_id: 1 }, {}]) - end .to raise_error { |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [ - { key: :quantity, name: :is_integer }, - { key: :quantity, name: :min }, - { key: :quantity, name: :required }, - { key: :ticket_level_id, name: :is_reference }, - { key: :ticket_level_id, name: :required } - ]) - } + supporter_id: supporter.id, + event_id: event.id, + tickets: [{quantity: 1, ticket_level_id: 1}, {}]) + end.to raise_error { |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, [ + {key: :quantity, name: :is_integer}, + {key: :quantity, name: :min}, + {key: :quantity, name: :required}, + {key: :ticket_level_id, name: :is_reference}, + {key: :ticket_level_id, name: :required} + ]) + } end - it 'validates the offsite_payment hash' do + it "validates the offsite_payment hash" do expect do InsertTickets.create(nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - event_id: event.id, - tickets: [{ quantity: 1, ticket_level_id: 1 }], - offsite_payment: { kind: 'not in list' }) - end .to raise_error { |error| - expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [ - { key: :kind, name: :included_in } - ]) - } + supporter_id: supporter.id, + event_id: event.id, + tickets: [{quantity: 1, ticket_level_id: 1}], + offsite_payment: {kind: "not in list"}) + end.to raise_error { |error| + expect(error).to be_a ParamValidation::ValidationError + expect_validation_errors(error.data, [ + {key: :kind, name: :included_in} + ]) + } end # it 'errors out if token is invalid' do @@ -207,88 +208,87 @@ def success_expectations # validation_card_not_with_supporter {InsertTickets.create(tickets:[{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: other_source_token.token, event_id: event.id)} # end - describe 'errors during find if' do - it 'supporter is invalid' do - find_error_supporter { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: nonprofit.id, supporter_id: 55_555, token: source_token.token, event_id: event.id) } + describe "errors during find if" do + it "supporter is invalid" do + find_error_supporter { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: 55_555, token: source_token.token, event_id: event.id) } end - it 'nonprofit is invalid' do - find_error_nonprofit { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: 55_555, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } + it "nonprofit is invalid" do + find_error_nonprofit { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: 55_555, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } end - it 'event is invalid' do - find_error_event { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: 5555) } + it "event is invalid" do + find_error_event { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: 5555) } end end - describe 'errors during relationship comparison if' do - it 'supporter is deleted' do - validation_supporter_deleted { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } + describe "errors during relationship comparison if" do + it "supporter is deleted" do + validation_supporter_deleted { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } end - it 'ticket level is deleted' do + it "ticket level is deleted" do ticket_level.deleted = true ticket_level.save! - expect { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) }.to raise_error { |error| + expect { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :tickets }]) - expect(error.message).to include 'deleted' + expect_validation_errors(error.data, [{key: :tickets}]) + expect(error.message).to include "deleted" expect(error.message).to include "Ticket level #{ticket_level.id}" } end - it 'event is deleted' do - validation_event_deleted { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } + it "event is deleted" do + validation_event_deleted { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) } end - it 'supporter doesnt belong to nonprofit' do - validation_supporter_not_with_nonprofit { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: nonprofit.id, supporter_id: other_nonprofit_supporter.id, token: source_token.token, event_id: event.id) } + it "supporter doesnt belong to nonprofit" do + validation_supporter_not_with_nonprofit { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: other_nonprofit_supporter.id, token: source_token.token, event_id: event.id) } end - it 'event doesnt belong to nonprofit' do - validation_event_not_with_nonprofit { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: other_ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: other_event.id) } + it "event doesnt belong to nonprofit" do + validation_event_not_with_nonprofit { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: other_ticket_level.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: other_event.id) } end - it 'event discount doesnt belong to event' do - expect { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, event_discount_id: other_event_discount.id) }.to raise_error { |e| + it "event discount doesnt belong to event" do + expect { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, event_discount_id: other_event_discount.id) }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :event_discount_id }]) + expect_validation_errors(e.data, [{key: :event_discount_id}]) expect(e.message).to include "Event discount #{other_event_discount.id}" expect(e.message).to include "event #{event.id}" } end end - it 'verify ticket not available raises properly' do + it "verify ticket not available raises properly" do expected_error = NotEnoughQuantityError.new(TicketLevel, nil, nil, nil) expect(QueryTicketLevels).to receive(:verify_tickets_available).and_raise(expected_error) - expect { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) }.to raise_error(expected_error) + expect { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id) }.to raise_error(expected_error) end - describe 'gross_amount > 0' do - before(:each) do + describe "gross_amount > 0" do + before do # for simplicity, we mock this to $20.00 no matter the ticket choices expect(QueryTicketLevels).to receive(:gross_amount_from_tickets).at_least(:once).at_most(:twice).and_return(1600) end - describe 'and kind == offsite' do - it 'errors without current_user' do - expect { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, 'kind' => 'offsite') }.to raise_error { |e| + describe "and kind == offsite" do + it "errors without current_user" do + expect { InsertTickets.create(:tickets => [{quantity: 1, ticket_level_id: ticket_level.id}], :nonprofit_id => nonprofit.id, :supporter_id => supporter.id, :token => source_token.token, :event_id => event.id, "kind" => "offsite") }.to raise_error { |e| expect(e).to be_a AuthenticationError } end - it 'errors with unauthorized current_user' do + it "errors with unauthorized current_user" do expect(QueryRoles).to receive(:is_authorized_for_nonprofit?).with(user.id, nonprofit.id).and_return(false) - expect { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, kind: 'offsite', current_user: user) }.to raise_error { |e| + expect { InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, kind: "offsite", current_user: user) }.to raise_error { |e| expect(e).to be_a AuthenticationError } end - it 'succeeds' do + it "succeeds" do success_expectations expect(QueryRoles).to receive(:is_authorized_for_nonprofit?).with(user.id, nonprofit.id).and_return true - result = nil expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, any_args).ordered expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) @@ -299,29 +299,29 @@ def success_expectations expect(Houdini.event_publisher).to receive(:announce).with(:ticket_purchase_created, any_args).ordered expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args).ordered expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args).ordered - result = InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, kind: 'offsite', offsite_payment: { kind: 'check', check_number: 'fake_checknumber' }, current_user: user) - - expected = generate_expected_tickets(payment_id: result['payment'].id, - nonprofit: nonprofit, - supporter: supporter, - event: event, - gross_amount: 1600, - kind: 'OffsitePayment', - offsite_payment: { id: result['offsite_payment'].id, kind: 'check', check_number: 'fake_checknumber' }, - tickets: [{ - id: result['tickets'][0]['id'], - quantity: 1, - ticket_level_id: ticket_level.id - }]) - expect(result['payment'].attributes).to eq expected[:payment] - expect(result['offsite_payment'].attributes).to eq expected[:offsite_payment] - expect(result['tickets'].map(&:attributes)[0]).to eq expected[:tickets][0] + result = InsertTickets.create(tickets: [{quantity: 1, ticket_level_id: ticket_level.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, kind: "offsite", offsite_payment: {kind: "check", check_number: "fake_checknumber"}, current_user: user) + + expected = generate_expected_tickets(payment_id: result["payment"].id, + nonprofit: nonprofit, + supporter: supporter, + event: event, + gross_amount: 1600, + kind: "OffsitePayment", + offsite_payment: {id: result["offsite_payment"].id, kind: "check", check_number: "fake_checknumber"}, + tickets: [{ + id: result["tickets"][0]["id"], + quantity: 1, + ticket_level_id: ticket_level.id + }]) + expect(result["payment"].attributes).to eq expected[:payment] + expect(result["offsite_payment"].attributes).to eq expected[:offsite_payment] + expect(result["tickets"].map(&:attributes)[0]).to eq expected[:tickets][0] end end - describe 'and kind == charge || nil' do + describe "and kind == charge || nil" do let(:basic_valid_ticket_input) do - { tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }, { quantity: 2, ticket_level_id: ticket_level2.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, event_id: event.id } + {tickets: [{quantity: 1, ticket_level_id: ticket_level.id}, {quantity: 2, ticket_level_id: ticket_level2.id}], nonprofit_id: nonprofit.id, supporter_id: supporter.id, event_id: event.id} end let(:include_fake_token) do basic_valid_ticket_input.merge(token: fake_uuid) @@ -331,61 +331,61 @@ def success_expectations basic_valid_ticket_input.merge(token: source_token.token) end - describe 'kind == charge' do - it 'token is invalid' do - validation_invalid_token { InsertTickets.create(include_fake_token.merge(kind: 'charge')) } + describe "kind == charge" do + it "token is invalid" do + validation_invalid_token { InsertTickets.create(include_fake_token.merge(kind: "charge")) } end - it 'errors out if token is unauthorized' do - validation_unauthorized { InsertTickets.create(include_fake_token.merge(kind: 'charge')) } + it "errors out if token is unauthorized" do + validation_unauthorized { InsertTickets.create(include_fake_token.merge(kind: "charge")) } end - it 'errors out if token is expired' do - validation_expired { InsertTickets.create(include_fake_token.merge(kind: 'charge')) } + it "errors out if token is expired" do + validation_expired { InsertTickets.create(include_fake_token.merge(kind: "charge")) } end - it 'card doesnt belong to supporter' do - validation_card_not_with_supporter { InsertTickets.create(include_fake_token.merge(kind: 'charge', token: other_source_token.token)) } + it "card doesnt belong to supporter" do + validation_card_not_with_supporter { InsertTickets.create(include_fake_token.merge(kind: "charge", token: other_source_token.token)) } end end - describe 'kind == nil' do - it 'token is invalid' do + describe "kind == nil" do + it "token is invalid" do validation_invalid_token { InsertTickets.create(include_fake_token) } end - it 'errors out if token is unauthorized' do + it "errors out if token is unauthorized" do validation_unauthorized { InsertTickets.create(include_fake_token) } end - it 'errors out if token is expired' do + it "errors out if token is expired" do validation_expired { InsertTickets.create(include_fake_token) } end - it 'card doesnt belong to supporter' do - validation_card_not_with_supporter { InsertTickets.create(include_fake_token.merge(kind: 'charge', token: other_source_token.token)) } + it "card doesnt belong to supporter" do + validation_card_not_with_supporter { InsertTickets.create(include_fake_token.merge(kind: "charge", token: other_source_token.token)) } end end - it 'handles charge failed' do + it "handles charge failed" do handle_charge_failed { InsertTickets.create(include_valid_token) } end - it 'succeeds' do + it "succeeds" do success end - it 'succeeds if offsite_donation is there with empty kind' do - success(offsite_donation: { kind: nil }) + it "succeeds if offsite_donation is there with empty kind" do + success(offsite_donation: {kind: nil}) end def success(other_elements = {}) expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) - nonprofit.stripe_account_id = Stripe::Account.create['id'] + nonprofit.stripe_account_id = Stripe::Account.create["id"] nonprofit.save! - card.stripe_customer_id = 'some other id' + card.stripe_customer_id = "some other id" card.save! success_expectations @@ -404,9 +404,9 @@ def success(other_elements = {}) expect(Houdini.event_publisher).to receive(:announce).with(:trx_assignment_created, any_args).ordered expect(Houdini.event_publisher).to receive(:announce).with(:transaction_created, any_args).ordered expect(InsertCharge).to receive(:with_stripe).with( - kind: 'Ticket', + kind: "Ticket", towards: event.name, - metadata: { kind: 'Ticket', event_id: event.id, nonprofit_id: nonprofit.id }, + metadata: {kind: "Ticket", event_id: event.id, nonprofit_id: nonprofit.id}, statement: "Tickets #{event.name}", amount: 1600, nonprofit_id: nonprofit.id, @@ -415,51 +415,51 @@ def success(other_elements = {}) ).and_call_original stripe_charge_id = nil - expect(Stripe::Charge).to receive(:create).with({ application_fee: 66, + expect(Stripe::Charge).to receive(:create).with({application_fee: 66, customer: card.stripe_customer_id, amount: 1600, - currency: 'usd', - description: 'Tickets The event of Wonders', - statement_descriptor: 'Tickets The event of W', - metadata: { kind: 'Ticket', event_id: event.id, nonprofit_id: nonprofit.id } }, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| + currency: "usd", + description: "Tickets The event of Wonders", + statement_descriptor: "Tickets The event of W", + metadata: {kind: "Ticket", event_id: event.id, nonprofit_id: nonprofit.id}}, {stripe_account: nonprofit.stripe_account_id}).and_wrap_original { |m, *args| a = m.call(*args) - stripe_charge_id = a['id'] + stripe_charge_id = a["id"] a } result = InsertTickets.create(include_valid_token.merge(event_discount_id: event_discount.id)) expected = generate_expected_tickets( - { gross_amount: 1600, - payment_fee_total: 66, - payment_id: result['payment'].id, - nonprofit: nonprofit, - supporter: supporter, - event: event, - charge_id: result['charge'].id, - stripe_charge_id: stripe_charge_id, - event_discount_id: event_discount.id, - card: card, - tickets: [{ - id: result['tickets'][0]['id'], - quantity: 1, - ticket_level_id: ticket_level.id - }, - { - id: result['tickets'][0]['id'], - quantity: 2, - ticket_level_id: ticket_level2.id - }] }.merge(other_elements) + {gross_amount: 1600, + payment_fee_total: 66, + payment_id: result["payment"].id, + nonprofit: nonprofit, + supporter: supporter, + event: event, + charge_id: result["charge"].id, + stripe_charge_id: stripe_charge_id, + event_discount_id: event_discount.id, + card: card, + tickets: [{ + id: result["tickets"][0]["id"], + quantity: 1, + ticket_level_id: ticket_level.id + }, + { + id: result["tickets"][0]["id"], + quantity: 2, + ticket_level_id: ticket_level2.id + }]}.merge(other_elements) ) - expect(result['payment'].attributes).to eq expected[:payment] - expect(result['charge'].attributes).to eq expected[:charge] - expect(result['tickets'].map(&:attributes)[0]).to eq expected[:tickets][0] + expect(result["payment"].attributes).to eq expected[:payment] + expect(result["charge"].attributes).to eq expected[:charge] + expect(result["tickets"].map(&:attributes)[0]).to eq expected[:tickets][0] end end - it 'errors where kind == free and positive gross_amount' do - expect { InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, 'kind' => 'free') }.to raise_error { |e| + it "errors where kind == free and positive gross_amount" do + expect { InsertTickets.create(:tickets => [{quantity: 1, ticket_level_id: ticket_level.id}], :nonprofit_id => nonprofit.id, :supporter_id => supporter.id, :token => source_token.token, :event_id => event.id, "kind" => "free") }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :kind }]) + expect_validation_errors(e.data, [{key: :kind}]) expect(e.message).to eq "Ticket costs money but you didn't pay." } end diff --git a/spec/legacy_lib/mailchimp_spec.rb b/spec/legacy_lib/mailchimp_spec.rb index 20ca26aaa2..05014bbcf1 100644 --- a/spec/legacy_lib/mailchimp_spec.rb +++ b/spec/legacy_lib/mailchimp_spec.rb @@ -2,31 +2,31 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Mailchimp do - describe '.hard_sync_list' do + describe ".hard_sync_list" do let(:ret_val) do - [{ id: 'on_both', email_address: 'on_both@email.com' }, - { id: 'on_mailchimp', email_address: 'on_mailchimp@email.com' }] + [{id: "on_both", email_address: "on_both@email.com"}, + {id: "on_mailchimp", email_address: "on_mailchimp@email.com"}] end let(:np) { force_create(:nm_justice) } let(:tag_definition) { force_create(:tag_definition, nonprofit: np) } - let(:email_list) { force_create(:email_list, mailchimp_list_id: 'list_id', tag_definition: tag_definition, nonprofit: np, list_name: 'temp') } - let(:supporter_on_both) { force_create(:supporter, nonprofit: np, email: 'on_BOTH@email.com') } - let(:supporter_on_local) { force_create(:supporter, nonprofit: np, email: 'on_local@email.com') } + let(:email_list) { force_create(:email_list, mailchimp_list_id: "list_id", tag_definition: tag_definition, nonprofit: np, list_name: "temp") } + let(:supporter_on_both) { force_create(:supporter, nonprofit: np, email: "on_BOTH@email.com") } + let(:supporter_on_local) { force_create(:supporter, nonprofit: np, email: "on_local@email.com") } let(:tag_join) { force_create(:tag_join, tag_definition: tag_definition, supporter: supporter_on_both) } let(:tag_join2) { force_create(:tag_join, tag_definition: tag_definition, supporter: supporter_on_local) } - it 'excepts when excepting' do + it "excepts when excepting" do expect(Mailchimp).to receive(:get_list_mailchimp_subscribers).with(email_list).and_raise expect { Mailchimp.generate_batch_ops_for_hard_sync(email_list) }.to raise_error end - it 'passes' do + it "passes" do tag_join tag_join2 email_list @@ -37,12 +37,12 @@ expect(result).to contain_exactly( { - method: 'POST', - path: 'lists/list_id/members', - body: { email_address: supporter_on_local.email, status: 'subscribed' }.to_json + method: "POST", + path: "lists/list_id/members", + body: {email_address: supporter_on_local.email, status: "subscribed"}.to_json }, - method: 'DELETE', - path: 'lists/list_id/members/on_mailchimp' + method: "DELETE", + path: "lists/list_id/members/on_mailchimp" ) end end diff --git a/spec/legacy_lib/merge_supporters_spec.rb b/spec/legacy_lib/merge_supporters_spec.rb index 26d7edb57a..59028a6d54 100644 --- a/spec/legacy_lib/merge_supporters_spec.rb +++ b/spec/legacy_lib/merge_supporters_spec.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true -require 'rails_helper' +require "rails_helper" describe MergeSupporters do - describe '.update_associations' do - around(:each) do |e| + describe ".update_associations" do + around do |e| Timecop.freeze(2020, 3, 4) do e.run end @@ -22,28 +22,28 @@ let(:old_supporter2) { force_create(:supporter, nonprofit: np) } let(:new_supporter) { force_create(:supporter, nonprofit: np) } - let(:supporter_note) { force_create(:supporter_note, supporter: old_supporter1, content: 'feoatheoiath') } + let(:supporter_note) { force_create(:supporter_note, supporter: old_supporter1, content: "feoatheoiath") } - let(:tag_definition) { force_create(:tag_definition, nonprofit: np, name: 'something') } - let(:tag_definition2) { force_create(:tag_definition, nonprofit: np, name: 'something2') } - let(:tag_definition3) { force_create(:tag_definition, nonprofit: np, name: 'something3') } + let(:tag_definition) { force_create(:tag_definition, nonprofit: np, name: "something") } + let(:tag_definition2) { force_create(:tag_definition, nonprofit: np, name: "something2") } + let(:tag_definition3) { force_create(:tag_definition, nonprofit: np, name: "something3") } let(:tag_on_1) { force_create(:tag_join, tag_definition: tag_definition, supporter_id: old_supporter1.id) } let(:tag_on_2) { force_create(:tag_join, tag_definition: tag_definition2, supporter_id: old_supporter2.id) } let(:tag_on_both) { [old_supporter1, old_supporter2].each { |i| force_create(:tag_join, tag_definition: tag_definition3, supporter_id: i.id) } } - let(:custom_field_definition) { force_create(:custom_field_definition, nonprofit: np, name: 'cfm1') } - let(:custom_field_definition2) { force_create(:custom_field_definition, nonprofit: np, name: 'cfm2') } - let(:custom_field_definition3) { force_create(:custom_field_definition, nonprofit: np, name: 'cfm3') } + let(:custom_field_definition) { force_create(:custom_field_definition, nonprofit: np, name: "cfm1") } + let(:custom_field_definition2) { force_create(:custom_field_definition, nonprofit: np, name: "cfm2") } + let(:custom_field_definition3) { force_create(:custom_field_definition, nonprofit: np, name: "cfm3") } - let(:cfj_on_1) { force_create(:custom_field_join, supporter: old_supporter1, custom_field_definition: custom_field_definition, value: 'cfj_on_1') } - let(:cfj_on_2) { force_create(:custom_field_join, supporter: old_supporter2, custom_field_definition: custom_field_definition2, value: 'cfj_on_2') } - let(:cfj_on_3) { force_create(:custom_field_join, supporter: old_supporter1, custom_field_definition: custom_field_definition3, value: 'old_cfj') } - let(:cfj_on_4) { force_create(:custom_field_join, supporter: old_supporter2, custom_field_definition: custom_field_definition3, value: 'new_cfj', created_at: Time.now + 1.day) } + let(:cfj_on_1) { force_create(:custom_field_join, supporter: old_supporter1, custom_field_definition: custom_field_definition, value: "cfj_on_1") } + let(:cfj_on_2) { force_create(:custom_field_join, supporter: old_supporter2, custom_field_definition: custom_field_definition2, value: "cfj_on_2") } + let(:cfj_on_3) { force_create(:custom_field_join, supporter: old_supporter1, custom_field_definition: custom_field_definition3, value: "old_cfj") } + let(:cfj_on_4) { force_create(:custom_field_join, supporter: old_supporter2, custom_field_definition: custom_field_definition3, value: "new_cfj", created_at: Time.now + 1.day) } let(:profile) { force_create(:profile) } - before(:each) do + before do np old_supporter1 old_supporter2 @@ -51,7 +51,7 @@ supporter_note end - it 'merges everything properly with tags and cfjs on both' do + it "merges everything properly with tags and cfjs on both" do tag_on_1 tag_on_2 tag_on_both @@ -79,7 +79,7 @@ expect(new_supporter.supporter_notes.first.id).to eq supporter_note.id end - it 'merges with tags and cfjs on first' do + it "merges with tags and cfjs on first" do tag_on_1 cfj_on_1 cfj_on_3 @@ -102,7 +102,7 @@ expect(new_supporter.supporter_notes.first.id).to eq supporter_note.id end - it 'merges with tags and cfjs on second' do + it "merges with tags and cfjs on second" do tag_on_2 cfj_on_2 cfj_on_4 @@ -124,7 +124,7 @@ expect(new_supporter.supporter_notes.first.id).to eq supporter_note.id end - it 'merges with tags and cfjs on neighter' do + it "merges with tags and cfjs on neighter" do MergeSupporters.update_associations([old_supporter1.id, old_supporter2.id], new_supporter.id, np.id, profile.id) old_supporter1.reload old_supporter2.reload diff --git a/spec/legacy_lib/name_copy_naming_algorithm_spec.rb b/spec/legacy_lib/name_copy_naming_algorithm_spec.rb index df44039c49..c13542375a 100644 --- a/spec/legacy_lib/name_copy_naming_algorithm_spec.rb +++ b/spec/legacy_lib/name_copy_naming_algorithm_spec.rb @@ -2,13 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe NameCopyNamingAlgorithm do - describe '.create_copy_name' do + describe ".create_copy_name" do before(:all) do Timecop.freeze(2020, 5, 4) end + after(:all) do Timecop.return end @@ -17,35 +18,36 @@ def set_name(name) @name = name end - let(:short_name) { 'short name' } - let(:short_name_copy_today) { 'short name (2020-05-04 copy) 00' } - let(:short_name_copy_today_plus_1) { 'short name (2020-05-04 copy) 01' } - let(:short_name_copy_yesterday) { 'short name (2020-05-03 copy) 00' } - let(:short_name_copy_today_base) { 'short name (2020-05-04 copy)' } + let(:short_name) { "short name" } + let(:short_name_copy_today) { "short name (2020-05-04 copy) 00" } + let(:short_name_copy_today_plus_1) { "short name (2020-05-04 copy) 01" } + let(:short_name_copy_yesterday) { "short name (2020-05-03 copy) 00" } + let(:short_name_copy_today_base) { "short name (2020-05-04 copy)" } - let(:long_name) { 'campaign_name is so long that it must be shortened down' } + let(:long_name) { "campaign_name is so long that it must be shortened down" } let(:long_name_copy_today) { "#{long_name_copy_today_base} 00" } let(:long_name_copy_today_plus_1) { "#{long_name_copy_today_base} 01" } - let(:long_name_copy_yesterday) { 'campaign_name is so long that it must b (2020-05-03 copy) 00' } - let(:long_name_copy_today_base) { 'campaign_name is so long that it must b (2020-05-04 copy)' } + let(:long_name_copy_yesterday) { "campaign_name is so long that it must b (2020-05-03 copy) 00" } + let(:long_name_copy_today_base) { "campaign_name is so long that it must b (2020-05-04 copy)" } let(:nonprofit) { force_create(:nm_justice) } - describe 'events' do + describe "events" do let(:event) { force_create(:event, name: @name, nonprofit: nonprofit) } let(:event2) { force_create(:event, name: @name2, nonprofit: nonprofit) } let(:events_at_max_copies) do (0..30).collect do |i| - force_create(:event, name: "#{@copy_base} #{format('%02d', i)}", nonprofit: nonprofit) + force_create(:event, name: "#{@copy_base} #{format("%02d", i)}", nonprofit: nonprofit) end end let(:algo) { NameCopyNamingAlgorithm.new(Event, nonprofit.id) } - describe 'short event names' do - it 'not a copy' do + + describe "short event names" do + it "not a copy" do @name = short_name event expect(algo.create_copy_name(@name)).to eq short_name_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = short_name @name2 = short_name_copy_today event @@ -54,7 +56,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_name_copy_today_plus_1 end - it 'one copy yesterday exists' do + it "one copy yesterday exists" do @name = short_name_copy_yesterday @name2 = short_name event @@ -63,18 +65,18 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_name_copy_today end - it 'has 30 as max copies' do + it "has 30 as max copies" do expect(algo.max_copies).to eq 30 end end - describe 'long event names' do - it 'not a copy' do + describe "long event names" do + it "not a copy" do @name = long_name event expect(algo.create_copy_name(@name)).to eq long_name_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = long_name @name2 = long_name_copy_today event @@ -83,7 +85,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq long_name_copy_today_plus_1 end - it 'one copy yesterday exists' do + it "one copy yesterday exists" do @name = long_name_copy_yesterday @name2 = long_name event @@ -92,23 +94,24 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq long_name_copy_today end - it 'has 30 as max copies' do + it "has 30 as max copies" do expect(algo.max_copies).to eq 30 end end end - describe 'campaigns' do + describe "campaigns" do let(:campaign) { force_create(:campaign, name: @name, nonprofit: nonprofit) } let(:campaign2) { force_create(:campaign, name: @name2, nonprofit: nonprofit) } let(:algo) { NameCopyNamingAlgorithm.new(Campaign, nonprofit.id) } - describe 'short campaign names' do - it 'not a copy' do + + describe "short campaign names" do + it "not a copy" do @name = short_name campaign expect(algo.create_copy_name(@name)).to eq short_name_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = short_name @name2 = short_name_copy_today campaign @@ -117,7 +120,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_name_copy_today_plus_1 end - it 'one copy yesterday exists' do + it "one copy yesterday exists" do @name = short_name_copy_yesterday @name2 = short_name campaign @@ -127,13 +130,13 @@ def set_name(name) end end - describe 'long campaign names' do - it 'not a copy' do + describe "long campaign names" do + it "not a copy" do @name = long_name campaign expect(algo.create_copy_name(@name)).to eq long_name_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = long_name @name2 = long_name_copy_today campaign @@ -142,7 +145,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq long_name_copy_today_plus_1 end - it 'one copy yesterday exists' do + it "one copy yesterday exists" do @name = long_name_copy_yesterday @name2 = long_name campaign diff --git a/spec/legacy_lib/nonprofit_creation_spec.rb b/spec/legacy_lib/nonprofit_creation_spec.rb index 85c4b64ae8..91f9419607 100644 --- a/spec/legacy_lib/nonprofit_creation_spec.rb +++ b/spec/legacy_lib/nonprofit_creation_spec.rb @@ -3,113 +3,113 @@ # # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe NonprofitCreation do - subject { described_class.new(result, options).call } - - let(:result) do - { - nonprofit: { - name: 'My Nonprofit', - state_code: 'IN', - city: ' Indianapolis', - website: 'https://www.mynonprofit.org', - email: 'mynonprofit@email.com', - phone: '5561999999999' - }, - user: { - name: 'User Name', - email: 'username@email.com', - password: 'P@ssw0rd!' - } - } - end - let(:options) { { confirm_admin: true } } - - describe 'command side effects' do - it { is_expected.to include(success: true, messages: ["Nonprofit #{Nonprofit.last.id} successfully created."]) } - end - - describe 'created nonprofit' do - subject do - super() - Nonprofit.find_by(name: 'My Nonprofit') - end - - let(:expected_attributes) do - { - state_code: 'IN', - city: ' Indianapolis', - website: 'https://www.mynonprofit.org', - email: 'mynonprofit@email.com', - phone: '5561999999999' - } - end - - it { is_expected.to have_attributes(expected_attributes) } - end - - describe 'created user' do - subject do - super() - User.find_by(email: 'username@email.com') - end - - it { is_expected.to_not be_super_admin } - it { is_expected.to be_confirmed } - - it { is_expected.to have_attributes(name: 'User Name') } - end - - describe 'super_admin_option' do - subject do - super() - User.find_by(email: 'anotherusername@email.com') - end - - before do - result[:user][:email] = 'anotherusername@email.com' - end - - let(:options) { { super_admin: true, confirm_user: false } } - - it { is_expected.to be_super_admin } - it { is_expected.to_not be_confirmed } - end - - context 'when nonprofit can not be saved' do - before do - result[:user][:email] = nil - end - - let(:expected_error_result) do - { - success: false, - messages: [ - "Error creating user: Email can't be blank", - 'Error creating user: Email is invalid' - ] - } - end - - it { is_expected.to eq(expected_error_result) } - end - - context 'when nonprofit state is not in the US' do - before do - result[:nonprofit][:state_code] = 'KK' - end - - let(:expected_error_result) do - { - success: false, - messages: [ - 'Error creating nonprofit: State code must be a US two-letter state code' - ] - } - end - - it { is_expected.to eq(expected_error_result) } - end + subject { described_class.new(result, options).call } + + let(:result) do + { + nonprofit: { + name: "My Nonprofit", + state_code: "IN", + city: "\tIndianapolis", + website: "https://www.mynonprofit.org", + email: "mynonprofit@email.com", + phone: "5561999999999" + }, + user: { + name: "User Name", + email: "username@email.com", + password: "P@ssw0rd!" + } + } + end + let(:options) { {confirm_admin: true} } + + describe "command side effects" do + it { is_expected.to include(success: true, messages: ["Nonprofit #{Nonprofit.last.id} successfully created."]) } + end + + describe "created nonprofit" do + subject do + super() + Nonprofit.find_by(name: "My Nonprofit") + end + + let(:expected_attributes) do + { + state_code: "IN", + city: "\tIndianapolis", + website: "https://www.mynonprofit.org", + email: "mynonprofit@email.com", + phone: "5561999999999" + } + end + + it { is_expected.to have_attributes(expected_attributes) } + end + + describe "created user" do + subject do + super() + User.find_by(email: "username@email.com") + end + + it { is_expected.to_not be_super_admin } + it { is_expected.to be_confirmed } + + it { is_expected.to have_attributes(name: "User Name") } + end + + describe "super_admin_option" do + subject do + super() + User.find_by(email: "anotherusername@email.com") + end + + before do + result[:user][:email] = "anotherusername@email.com" + end + + let(:options) { {super_admin: true, confirm_user: false} } + + it { is_expected.to be_super_admin } + it { is_expected.to_not be_confirmed } + end + + context "when nonprofit can not be saved" do + before do + result[:user][:email] = nil + end + + let(:expected_error_result) do + { + success: false, + messages: [ + "Error creating user: Email can't be blank", + "Error creating user: Email is invalid" + ] + } + end + + it { is_expected.to eq(expected_error_result) } + end + + context "when nonprofit state is not in the US" do + before do + result[:nonprofit][:state_code] = "KK" + end + + let(:expected_error_result) do + { + success: false, + messages: [ + "Error creating nonprofit: State code must be a US two-letter state code" + ] + } + end + + it { is_expected.to eq(expected_error_result) } + end end diff --git a/spec/legacy_lib/numeric_spec.rb b/spec/legacy_lib/numeric_spec.rb index f062b660ff..e0be3ed3a5 100644 --- a/spec/legacy_lib/numeric_spec.rb +++ b/spec/legacy_lib/numeric_spec.rb @@ -3,95 +3,95 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require_relative '../../app/legacy_lib/numeric' +require_relative "../../app/legacy_lib/numeric" describe Numeric do - describe '#floor_for_delta' do - it 'rejects non integers' do - expect { 2.floor_for_delta('test') }.to raise_error(ArgumentError) + describe "#floor_for_delta" do + it "rejects non integers" do + expect { 2.floor_for_delta("test") }.to raise_error(ArgumentError) expect { 2.floor_for_delta(2.3) }.to raise_error(ArgumentError) end - it 'rejects negative integers' do + it "rejects negative integers" do expect { 2.floor_for_delta(-1) }.to raise_error(ArgumentError) end - it 'handles on -25' do - expect(-25.floor_for_delta(25)).to eq -25 + it "handles on -25" do + expect(-25.floor_for_delta(25)).to eq(-25) end - it 'handles on -24.5' do - expect(-24.5.floor_for_delta(25)).to eq -25 + it "handles on -24.5" do + expect(-24.5.floor_for_delta(25)).to eq(-25) end - it 'handles on -1' do - expect(-1.floor_for_delta(25)).to eq -25 + it "handles on -1" do + expect(-1.floor_for_delta(25)).to eq(-25) end - it 'handles on 0' do + it "handles on 0" do expect(0.floor_for_delta(25)).to eq 0 end - it 'handles on .5' do + it "handles on .5" do expect(0.5.floor_for_delta(25)).to eq 0 end - it 'handles on 1' do + it "handles on 1" do expect(1.floor_for_delta(25)).to eq 0 end - it 'handles on 25' do + it "handles on 25" do expect(25.floor_for_delta(25)).to eq 25 end - it 'handles on 25.5' do + it "handles on 25.5" do expect(25.5.floor_for_delta(25)).to eq 25 end end - describe '#ceil_for_delta' do - it 'rejects non integers' do - expect { 2.ceil_for_delta('test') }.to raise_error(ArgumentError) + describe "#ceil_for_delta" do + it "rejects non integers" do + expect { 2.ceil_for_delta("test") }.to raise_error(ArgumentError) expect { 2.ceil_for_delta(2.3) }.to raise_error(ArgumentError) end - it 'rejects negative integers' do + it "rejects negative integers" do expect { 2.ceil_for_delta(-1) }.to raise_error(ArgumentError) end - it 'handles on -25.5' do - expect(-25.5.ceil_for_delta(25)).to eq -25 + it "handles on -25.5" do + expect(-25.5.ceil_for_delta(25)).to eq(-25) end - it 'handles on -25' do - expect(-25.ceil_for_delta(25)).to eq -25 + it "handles on -25" do + expect(-25.ceil_for_delta(25)).to eq(-25) end - it 'handles on -24.5' do + it "handles on -24.5" do expect(-24.5.ceil_for_delta(25)).to eq 0 end - it 'handles on -1' do + it "handles on -1" do expect(-1.ceil_for_delta(25)).to eq 0 end - it 'handles on 0' do + it "handles on 0" do expect(0.ceil_for_delta(25)).to eq 0 end - it 'handles on .5' do + it "handles on .5" do expect(0.5.ceil_for_delta(25)).to eq 25 end - it 'handles on 1' do + it "handles on 1" do expect(1.ceil_for_delta(25)).to eq 25 end - it 'handles on 25' do + it "handles on 25" do expect(25.ceil_for_delta(25)).to eq 25 end - it 'handles on 25.5' do + it "handles on 25.5" do expect(25.ceil_for_delta(25)).to eq 25 end end diff --git a/spec/legacy_lib/pay_recurring_donation_spec.rb b/spec/legacy_lib/pay_recurring_donation_spec.rb index 4d930bb622..1517413af8 100644 --- a/spec/legacy_lib/pay_recurring_donation_spec.rb +++ b/spec/legacy_lib/pay_recurring_donation_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'timecop' +require "rails_helper" +require "timecop" describe PayRecurringDonation do before(:all) do @@ -13,7 +13,7 @@ let(:today) { Time.current.to_date } - describe '.with_donation', pending: true do + describe ".with_donation", pending: true do # describe 'create a valid charge and payment when due' do # # end @@ -64,7 +64,7 @@ # end end - describe '.pay_all_due_with_stripe', pending: true do + describe ".pay_all_due_with_stripe", pending: true do # it 'queues a job to pay each due recurring donation' do # Timecop.freeze(Time.parse("2020-02-01").utc) do # VCR.use_cassette('PayRecurringDonation/pay_all_due_with_stripe') do @@ -80,19 +80,19 @@ # end end - describe '.ULTIMATE_VERIFICATION' do - it 'returns false' do - Timecop.freeze(Time.parse('2020-02-01').utc) do - expect(PayRecurringDonation.ULTIMATE_VERIFICATION('2020-02-02', true, true, false, 'run_dangerously')).to be_falsey - expect(PayRecurringDonation.ULTIMATE_VERIFICATION('2020-02-01', false, true, false, 'run_dangerously')).to be_falsey - expect(PayRecurringDonation.ULTIMATE_VERIFICATION('2020-02-01', true, false, false, 'run_dangerously')).to be_falsey - expect(PayRecurringDonation.ULTIMATE_VERIFICATION('2020-02-01', true, true, true, 'run_dangerously')).to be_falsey - expect(PayRecurringDonation.ULTIMATE_VERIFICATION('2020-02-01', true, true, false, 'rd')).to be_falsey + describe ".ULTIMATE_VERIFICATION" do + it "returns false" do + Timecop.freeze(Time.parse("2020-02-01").utc) do + expect(PayRecurringDonation.ULTIMATE_VERIFICATION("2020-02-02", true, true, false, "run_dangerously")).to be_falsey + expect(PayRecurringDonation.ULTIMATE_VERIFICATION("2020-02-01", false, true, false, "run_dangerously")).to be_falsey + expect(PayRecurringDonation.ULTIMATE_VERIFICATION("2020-02-01", true, false, false, "run_dangerously")).to be_falsey + expect(PayRecurringDonation.ULTIMATE_VERIFICATION("2020-02-01", true, true, true, "run_dangerously")).to be_falsey + expect(PayRecurringDonation.ULTIMATE_VERIFICATION("2020-02-01", true, true, false, "rd")).to be_falsey end end - it 'returns true' do - Timecop.freeze(Time.parse('2020-02-01').utc) do - expect(PayRecurringDonation.ULTIMATE_VERIFICATION('2020-02-01', true, true, false, 'run dangerously')).to be_truthy + it "returns true" do + Timecop.freeze(Time.parse("2020-02-01").utc) do + expect(PayRecurringDonation.ULTIMATE_VERIFICATION("2020-02-01", true, true, false, "run dangerously")).to be_truthy end end end diff --git a/spec/legacy_lib/query/billing_plans_spec.rb b/spec/legacy_lib/query/billing_plans_spec.rb index 13aee03434..850b83e48e 100644 --- a/spec/legacy_lib/query/billing_plans_spec.rb +++ b/spec/legacy_lib/query/billing_plans_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe BillingPlans do let(:percentage) { 0.34 } @@ -14,38 +14,38 @@ force_create(:nm_justice) end - describe '.get_percentage_fee' do - describe 'param validation' do - it 'rejects non-integers' do - expect { BillingPlans.get_percentage_fee('not an integer') }.to (raise_error do |error| + describe ".get_percentage_fee" do + describe "param validation" do + it "rejects non-integers" do + expect { BillingPlans.get_percentage_fee("not an integer") }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error.data, [{ key: :nonprofit_id, name: :is_integer }]) + expect_validation_errors(error.data, [{key: :nonprofit_id, name: :is_integer}]) end) end - it 'rejects invalid nonprofits' do - expect { BillingPlans.get_percentage_fee(55_555) }.to (raise_error do |error| + it "rejects invalid nonprofits" do + expect { BillingPlans.get_percentage_fee(55_555) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error.data, [{ key: :nonprofit_id }]) + expect_validation_errors(error.data, [{key: :nonprofit_id}]) end) end end - it 'returns 0 when no billing_subscription' do + it "returns 0 when no billing_subscription" do result = BillingPlans.get_percentage_fee(nonprofit.id) expect(result).to eq 0 end # TODO: not sure this is what we actually want? - it 'returns 0 when billing plan is invalid' do - bs = force_create(:billing_subscription, billing_plan: nil, nonprofit: nonprofit) + it "returns 0 when billing plan is invalid" do + force_create(:billing_subscription, billing_plan: nil, nonprofit: nonprofit) result = BillingPlans.get_percentage_fee(nonprofit.id) expect(result).to eq(0) end - it 'returns percentage when billing subscription exists' do - bs = force_create(:billing_subscription, billing_plan: billing_plan, nonprofit: nonprofit) + it "returns percentage when billing subscription exists" do + force_create(:billing_subscription, billing_plan: billing_plan, nonprofit: nonprofit) result = BillingPlans.get_percentage_fee(nonprofit.id) expect(result).to eq 0.34 diff --git a/spec/legacy_lib/query/query_campaign_gifts_spec.rb b/spec/legacy_lib/query/query_campaign_gifts_spec.rb index 206116283f..2aed565e19 100644 --- a/spec/legacy_lib/query/query_campaign_gifts_spec.rb +++ b/spec/legacy_lib/query/query_campaign_gifts_spec.rb @@ -2,17 +2,17 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QueryCampaignGifts do GIFT_LEVEL_ONE_TIME = 1111 GIFT_LEVEL_RECURRING = 5585 GIFT_LEVEL_CHANGED_RECURRING = 5512 - CAMPAIGN_GIFT_OPTION_NAME = 'theowthoinv' + CAMPAIGN_GIFT_OPTION_NAME = "theowthoinv" let(:np) { force_create(:nm_justice) } let(:supporter1) { force_create(:supporter, nonprofit: np) } let(:supporter2) { force_create(:supporter, nonprofit: np) } - let(:campaign) { force_create(:campaign, nonprofit: np, slug: 'slug stuff') } + let(:campaign) { force_create(:campaign, nonprofit: np, slug: "slug stuff") } let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, name: CAMPAIGN_GIFT_OPTION_NAME, amount_one_time: GIFT_LEVEL_ONE_TIME, amount_recurring: GIFT_LEVEL_RECURRING) } let(:campaign_gift1) { force_create(:campaign_gift, campaign_gift_option: campaign_gift_option, donation: donation1) } let(:donation1) { force_create(:donation, amount: GIFT_LEVEL_ONE_TIME, campaign: campaign, supporter: supporter1) } @@ -41,22 +41,22 @@ QueryCampaignGifts.report_metrics(campaign.id) end - before(:each) do + before do init_all end - it 'counts gift donations properly' do + it "counts gift donations properly" do glm = gift_level_match data = glm[:data] expect(data).to eq([ - { - 'name' => CAMPAIGN_GIFT_OPTION_NAME, - 'total_donations' => 2, - 'total_one_time' => GIFT_LEVEL_ONE_TIME, - 'total_recurring' => GIFT_LEVEL_RECURRING - } - ]) + { + "name" => CAMPAIGN_GIFT_OPTION_NAME, + "total_donations" => 2, + "total_one_time" => GIFT_LEVEL_ONE_TIME, + "total_recurring" => GIFT_LEVEL_RECURRING + } + ]) end end diff --git a/spec/legacy_lib/query/query_campaign_metrics_spec.rb b/spec/legacy_lib/query/query_campaign_metrics_spec.rb index 7a1ff4a8ea..6c58a90733 100644 --- a/spec/legacy_lib/query/query_campaign_metrics_spec.rb +++ b/spec/legacy_lib/query/query_campaign_metrics_spec.rb @@ -2,10 +2,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QueryCampaignMetrics do - describe 'calculates your metrics plus children' do + describe "calculates your metrics plus children" do let(:nonprofit) { force_create(:nm_justice) } let(:campaign) { force_create(:campaign, nonprofit: nonprofit, show_total_count: false, show_total_raised: false, goal_amount: 16_000) } let(:campaign_child) { force_create(:campaign, nonprofit: nonprofit, parent_campaign: campaign, show_total_count: true, show_total_raised: true, goal_amount: 8000) } @@ -19,8 +19,8 @@ let(:payment2) { force_create(:payment, donation: donation2, gross_amount: 2000) } let(:donation3) { force_create(:donation, campaign: campaign_child, amount: 2000) } - let(:payment3) { force_create(:payment, donation: donation3, gross_amount: 4000, kind: 'RecurringPayment') } - let(:payment3_1) { force_create(:payment, donation: donation3, gross_amount: 2000, kind: 'RecurringPayment') } + let(:payment3) { force_create(:payment, donation: donation3, gross_amount: 4000, kind: "RecurringPayment") } + let(:payment3_1) { force_create(:payment, donation: donation3, gross_amount: 2000, kind: "RecurringPayment") } let(:donation4) { force_create(:donation, campaign: campaign_child_2, amount: 8000) } let(:payment4) { force_create(:payment, donation: donation4, gross_amount: 8000) } @@ -33,7 +33,7 @@ payment4 end - let (:campaign_metric) do + let(:campaign_metric) do payments QueryCampaignMetrics.on_donations(campaign.id) end @@ -48,28 +48,28 @@ QueryCampaignMetrics.on_donations(campaign_child_2.id) end - it 'campaign metric is valid' do - expect(campaign_metric['supporters_count']).to eq 4 - expect(campaign_metric['total_raised']).to eq 15_000 - expect(campaign_metric['goal_amount']).to eq 16_000 - expect(campaign_metric['show_total_count']).to eq false - expect(campaign_metric['show_total_raised']).to eq false + it "campaign metric is valid" do + expect(campaign_metric["supporters_count"]).to eq 4 + expect(campaign_metric["total_raised"]).to eq 15_000 + expect(campaign_metric["goal_amount"]).to eq 16_000 + expect(campaign_metric["show_total_count"]).to eq false + expect(campaign_metric["show_total_raised"]).to eq false end - it 'campaign child metric is valid' do - expect(campaign_child_metric['supporters_count']).to eq 1 - expect(campaign_child_metric['total_raised']).to eq 4000 - expect(campaign_child_metric['goal_amount']).to eq 8000 - expect(campaign_child_metric['show_total_count']).to eq true - expect(campaign_child_metric['show_total_raised']).to eq true + it "campaign child metric is valid" do + expect(campaign_child_metric["supporters_count"]).to eq 1 + expect(campaign_child_metric["total_raised"]).to eq 4000 + expect(campaign_child_metric["goal_amount"]).to eq 8000 + expect(campaign_child_metric["show_total_count"]).to eq true + expect(campaign_child_metric["show_total_raised"]).to eq true end - it 'campaign child 2metric is valid' do - expect(campaign_child_2_metric['supporters_count']).to eq 1 - expect(campaign_child_2_metric['total_raised']).to eq 8000 - expect(campaign_child_2_metric['goal_amount']).to eq 4000 - expect(campaign_child_2_metric['show_total_count']).to eq true - expect(campaign_child_2_metric['show_total_raised']).to eq true + it "campaign child 2metric is valid" do + expect(campaign_child_2_metric["supporters_count"]).to eq 1 + expect(campaign_child_2_metric["total_raised"]).to eq 8000 + expect(campaign_child_2_metric["goal_amount"]).to eq 4000 + expect(campaign_child_2_metric["show_total_count"]).to eq true + expect(campaign_child_2_metric["show_total_raised"]).to eq true end end end diff --git a/spec/legacy_lib/query/query_donations_spec.rb b/spec/legacy_lib/query/query_donations_spec.rb index 6dfdedce6d..0087738271 100644 --- a/spec/legacy_lib/query/query_donations_spec.rb +++ b/spec/legacy_lib/query/query_donations_spec.rb @@ -2,31 +2,31 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QueryDonations do - describe 'campaign_export' do + describe "campaign_export" do let(:nonprofit) { force_create(:nm_justice) } let(:supporter) { force_create(:supporter) } - let(:profile_email) { 'something@profile_email.com' } + let(:profile_email) { "something@profile_email.com" } let(:profile) do u = force_create(:user, email: profile_email) - profile = force_create(:profile, user: u) + force_create(:profile, user: u) end let(:campaign) { force_create(:campaign, nonprofit: nonprofit, show_total_count: false, show_total_raised: false, goal_amount: 16_000, profile: profile) } - let(:profile_email1) { 'something1@profile_email.com' } + let(:profile_email1) { "something1@profile_email.com" } let(:profile1) do u = force_create(:user, email: profile_email1) - profile = force_create(:profile, user: u) + force_create(:profile, user: u) end let(:campaign_child) { force_create(:campaign, nonprofit: nonprofit, parent_campaign: campaign, show_total_count: true, show_total_raised: true, goal_amount: 8000, profile: profile1) } - let(:profile_email2) { 'something2@profile_email.com' } + let(:profile_email2) { "something2@profile_email.com" } let(:profile2) do u = force_create(:user, email: profile_email2) - profile = force_create(:profile, user: u) + force_create(:profile, user: u) end let(:campaign_child_2) { force_create(:campaign, nonprofit: nonprofit, parent_campaign: campaign, show_total_count: true, show_total_raised: true, goal_amount: 4000, profile: profile2) } @@ -37,8 +37,8 @@ let(:payment2) { force_create(:payment, donation: donation2, gross_amount: 2000, supporter: supporter) } let(:donation3) { force_create(:donation, campaign: campaign_child, amount: 2000, supporter: supporter) } - let(:payment3) { force_create(:payment, donation: donation3, gross_amount: 4000, kind: 'RecurringPayment', supporter: supporter) } - let(:payment3_1) { force_create(:payment, donation: donation3, gross_amount: 2000, kind: 'RecurringPayment', supporter: supporter) } + let(:payment3) { force_create(:payment, donation: donation3, gross_amount: 4000, kind: "RecurringPayment", supporter: supporter) } + let(:payment3_1) { force_create(:payment, donation: donation3, gross_amount: 2000, kind: "RecurringPayment", supporter: supporter) } let(:recurring) { force_create(:recurring_donation, donation: donation3, amount: 2000, supporter: supporter) } let(:donation4) { force_create(:donation, campaign: campaign_child_2, amount: 8000, supporter: supporter) } @@ -53,25 +53,25 @@ payment4 end - let (:campaign_export) do + let(:campaign_export) do payments QueryDonations.campaign_export(campaign.id) end - it 'payment amounts get the first payment, not additional ones' do + it "payment amounts get the first payment, not additional ones" do export = vector_to_hash(campaign_export) - expect(export.map { |i| i['Amount'] }).to match_array(['$10.00', '$20.00', '$40.00', '$80.00']) + expect(export.map { |i| i["Amount"] }).to match_array(["$10.00", "$20.00", "$40.00", "$80.00"]) end - it 'includes the campaign ids' do + it "includes the campaign ids" do export = vector_to_hash(campaign_export) - expect(export.map { |i| i['Campaign Id'] }).to match_array([campaign.id, campaign.id, campaign_child.id, campaign_child_2.id]) + expect(export.map { |i| i["Campaign Id"] }).to match_array([campaign.id, campaign.id, campaign_child.id, campaign_child_2.id]) end - it 'includes user email' do + it "includes user email" do export = vector_to_hash(campaign_export) - expect(export.map { |i| i['Campaign Creator Email'] }).to match_array([profile_email, profile_email, profile_email1, profile_email2]) + expect(export.map { |i| i["Campaign Creator Email"] }).to match_array([profile_email, profile_email, profile_email1, profile_email2]) end end diff --git a/spec/legacy_lib/query/query_payments_spec.rb b/spec/legacy_lib/query/query_payments_spec.rb index 0991cdc0f9..3038422e53 100644 --- a/spec/legacy_lib/query/query_payments_spec.rb +++ b/spec/legacy_lib/query/query_payments_spec.rb @@ -2,39 +2,40 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'support/payments_for_a_payout' +require "rails_helper" +require "support/payments_for_a_payout" describe QueryPayments do - before :each do - @nonprofit = force_create(:nm_justice, name: 'npo1', id: 515152) - @supporters = [force_create(:supporter, name: 'supporter-0', nonprofit: @nonprofit), - force_create(:supporter, name: 'supporter-1', nonprofit: @nonprofit)] + before do + @nonprofit = force_create(:nm_justice, name: "npo1", id: 515152) + @supporters = [force_create(:supporter, name: "supporter-0", nonprofit: @nonprofit), + force_create(:supporter, name: "supporter-1", nonprofit: @nonprofit)] @payments = [force_create(:payment, gross_amount: 1000, fee_total: 99, net_amount: 901, supporter: @supporters[0], nonprofit: @nonprofit), - force_create(:payment, gross_amount: 2000, fee_total: 22, net_amount: 1978, supporter: @supporters[1], nonprofit: @nonprofit)] - @bank_account = force_create(:bank_account, name: 'bank1', nonprofit: @nonprofit) + force_create(:payment, gross_amount: 2000, fee_total: 22, net_amount: 1978, supporter: @supporters[1], nonprofit: @nonprofit)] + @bank_account = force_create(:bank_account, name: "bank1", nonprofit: @nonprofit) end - describe '.ids_for_payout' do - before(:each) do + describe ".ids_for_payout" do + before do Timecop.freeze(2020, 5, 5) end - after(:each) do + + after do Timecop.return end - describe 'no date provided' do - include_context 'payments for a payout' do + describe "no date provided" do + include_context "payments for a payout" do let(:np) { @nonprofit } let(:date_for_marking) { Time.now } end - it 'np is invalid' do + it "np is invalid" do expect(QueryPayments.ids_for_payout(686_826_812_658_102_751_098_754)).to eq [] end - it 'works without a date provided' do + it "works without a date provided" do all_payments result = QueryPayments.ids_for_payout(np.id) @@ -59,17 +60,17 @@ end end - describe 'with date provided' do - include_context 'payments for a payout' do + describe "with date provided" do + include_context "payments for a payout" do let(:np) { @nonprofit } let(:date_for_marking) { Time.now - 1.day } end - it 'np is invalid' do + it "np is invalid" do expect(QueryPayments.ids_for_payout(686_826_812_658_102_751_098_754)).to eq [] end - it 'works with a date provided' do + it "works with a date provided" do all_payments result = QueryPayments.ids_for_payout(np.id, date: Time.now - 1.day) @@ -95,57 +96,57 @@ end end - describe '.get_payout_total' do - include_context 'payments for a payout' do + describe ".get_payout_total" do + include_context "payments for a payout" do let(:np) { @nonprofit } let(:date_for_marking) { Time.now } end - it 'gives empty payout result if no payments provided' do + it "gives empty payout result if no payments provided" do result = QueryPayments.get_payout_totals([]) - expected = { 'gross_amount' => 0, 'fee_total' => 0, 'net_amount' => 0 } + expected = {"gross_amount" => 0, "fee_total" => 0, "net_amount" => 0} expect(result).to eq expected end - it 'gives correct payout info' do + it "gives correct payout info" do all_payments result = QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(np.id)) - expected = { gross_amount: 5500, fee_total: -1200, net_amount: 4300, count: 8 }.with_indifferent_access + expected = {gross_amount: 5500, fee_total: -1200, net_amount: 4300, count: 8}.with_indifferent_access expect(result.with_indifferent_access).to eq expected end end - describe '.for_payout' do - before(:each) do - gross = @payments.map { |h| h['gross_amount'] }.sum - fees = @payments.map { |h| h['fee_total'] }.sum - net = @payments.map { |h| h['net_amount'] }.sum + describe ".for_payout" do + before do + gross = @payments.map { |h| h["gross_amount"] }.sum + fees = @payments.map { |h| h["fee_total"] }.sum + net = @payments.map { |h| h["net_amount"] }.sum @payout = force_create(:payout, gross_amount: gross, fee_total: fees, net_amount: net, nonprofit: @nonprofit) @payment_payouts = @payments.map { |p| force_create(:payment_payout, payment: p, payout: @payout) } - @result = QueryPayments.for_payout(@nonprofit['id'], @payout['id']) + @result = QueryPayments.for_payout(@nonprofit["id"], @payout["id"]) end - it 'sets the correct headers' do + it "sets the correct headers" do expect(@result.first).to eq(%w[date gross_total fee_total net_total bank_name status]) end - it 'sets the correct payout data' do + it "sets the correct payout data" do expect(@result[1].count).to eq(6) # TODO end - it 'sets the payment headers', pending: true do - expect(@result[3]).to eq(['Date', 'Gross Amount', 'Fee Total', 'Net Amount', 'Type', 'Payment ID', 'Last Name', 'First Name', 'Full Name', 'Organization', 'Email', 'Phone', 'Address', 'City', 'State', 'Postal Code', 'Country', 'Anonymous?', 'Designation', 'Honorarium/Memorium', 'Comment', 'Campaign', 'Campaign Gift Level', 'Event']) + it "sets the payment headers", pending: true do + expect(@result[3]).to eq(["Date", "Gross Amount", "Fee Total", "Net Amount", "Type", "Payment ID", "Last Name", "First Name", "Full Name", "Organization", "Email", "Phone", "Address", "City", "State", "Postal Code", "Country", "Anonymous?", "Designation", "Honorarium/Memorium", "Comment", "Campaign", "Campaign Gift Level", "Event"]) end - it 'sets the correct payment data', pending: true do + it "sets the correct payment data", pending: true do expect(@result[4].count).to eq 24 end end - describe '.for_export_enumerable' do - it 'finishes two payment export' do + describe ".for_export_enumerable" do + it "finishes two payment export" do rows = QueryPayments.for_export_enumerable(@nonprofit.id, {}).to_a headers = MockHelpers.payment_export_headers @@ -155,18 +156,18 @@ end end - describe '.full_search' do + describe ".full_search" do include_context :shared_rd_donation_value_context - before(:each) do - nonprofit.stripe_account_id = Stripe::Account.create['id'] + before do + nonprofit.stripe_account_id = Stripe::Account.create["id"] nonprofit.save! - card.stripe_customer_id = 'some other id' + card.stripe_customer_id = "some other id" cust = Stripe::Customer.create - card.stripe_customer_id = cust['id'] + card.stripe_customer_id = cust["id"] card.save! expect(Stripe::Charge).to receive(:create).exactly(3).times.and_wrap_original { |m, *args| a = m.call(*args) - @stripe_charge_id = a['id'] + @stripe_charge_id = a["id"] a } end @@ -180,14 +181,14 @@ def generate_donation(h) date = h[:date] amount = h[:amount] - input = { amount: amount, - nonprofit_id: nonprofit.id, - supporter_id: supporter.id, - token: token, + input = {amount: amount, + nonprofit_id: nonprofit.id, + supporter_id: supporter.id, + token: token, - date: date, - dedication: {'type' => 'honor', 'name' => 'a name'}, - designation: 'designation' } + date: date, + dedication: {"type" => "honor", "name" => "a name"}, + designation: "designation"} input[:event_id] = h[:event_id] if h[:event_id] input[:campaign_id] = h[:campaign_id] if h[:campaign_id] @@ -195,42 +196,42 @@ def generate_donation(h) InsertDonation.with_stripe(input) end - describe 'general donations' do + describe "general donations" do let(:donation_result_yesterday) do generate_donation(amount: charge_amount_small, - token: source_tokens[0].token, - date: (Time.now - 1.day).to_s) + token: source_tokens[0].token, + date: (Time.now - 1.day).to_s) end let(:donation_result_today) do generate_donation(amount: charge_amount_medium, - token: source_tokens[1].token, + token: source_tokens[1].token, - date: Time.now.to_s) + date: Time.now.to_s) end let(:donation_result_tomorrow) do generate_donation(amount: charge_amount_large, - token: source_tokens[2].token, - date: (Time.now - 1.day).to_s) + token: source_tokens[2].token, + date: (Time.now - 1.day).to_s) end - let (:first_refund_of_yesterday) do - charge = donation_result_yesterday['charge'] + let(:first_refund_of_yesterday) do + charge = donation_result_yesterday["charge"] - InsertRefunds.with_stripe(charge.attributes, { amount: 100 }.with_indifferent_access) + InsertRefunds.with_stripe(charge.attributes, {amount: 100}.with_indifferent_access) end let(:second_refund_of_yesterday) do - charge = donation_result_yesterday['charge'] + charge = donation_result_yesterday["charge"] - InsertRefunds.with_stripe(charge.attributes, { amount: 50 }.with_indifferent_access) + InsertRefunds.with_stripe(charge.attributes, {amount: 50}.with_indifferent_access) end - it 'empty filter returns all' do + it "empty filter returns all" do donation_result_yesterday donation_result_today donation_result_tomorrow @@ -242,57 +243,56 @@ def generate_donation(h) expect(result[:data].count).to eq 5 end - context 'considering the nonprofit timezone on the query result' do + context "considering the nonprofit timezone on the query result" do before do donation_result_today first_refund_of_yesterday second_refund_of_yesterday end - it 'when the nonprofit does not have a timezone it considers UTC as default' do + it "when the nonprofit does not have a timezone it considers UTC as default" do donation_result_tomorrow - result = QueryPayments::full_search(nonprofit.id, {}) - expect(result[:data].first['date']).to eq (Time.now).to_s + result = QueryPayments.full_search(nonprofit.id, {}) + expect(result[:data].first["date"]).to eq Time.now.to_s end - context 'when the nonprofit has a timezone' do + context "when the nonprofit has a timezone" do before do - nonprofit.update(timezone: 'America/New_York') + nonprofit.update(timezone: "America/New_York") allow(QuerySourceToken) .to receive(:get_and_increment_source_token) .and_return(source_tokens[0]) end - it 'shows the corresponding time' do + it "shows the corresponding time" do donation_result_tomorrow - result = QueryPayments::full_search(nonprofit.id, {}) - expect(result[:data].first['date']).to eq ((Time.now) - 4.hours).to_s + result = QueryPayments.full_search(nonprofit.id, {}) + expect(result[:data].first["date"]).to eq (Time.now - 4.hours).to_s end - it 'finds the payments on dates after the specified dates' do + it "finds the payments on dates after the specified dates" do donation_result_tomorrow - result = QueryPayments::full_search(nonprofit.id, { after_date: Time.now - 4.hours }) + result = QueryPayments.full_search(nonprofit.id, {after_date: Time.now - 4.hours}) expect(result[:data].count).to eq 5 end - it 'finds the payments on dates before the specified dates' do + it "finds the payments on dates before the specified dates" do donation_result_tomorrow - result = QueryPayments::full_search(nonprofit.id, { before_date: Time.now }) + result = QueryPayments.full_search(nonprofit.id, {before_date: Time.now}) expect(result[:data].count).to eq 5 end - it 'finds the payments of an specific year' do + it "finds the payments of an specific year" do # creating a payment at 1 AM UTC from january 2020 # should not be included in the 2020 query if we are at America/New_York - Timecop.freeze(2020,1,1,1,0,0, "+00:00") - donation = - generate_donation( - amount: charge_amount_large, - token: source_tokens[2].token, - date: Time.now.to_s - ) - result_for_2020 = QueryPayments::full_search(nonprofit.id, { year: '2020' }) - result_for_2019 = QueryPayments::full_search(nonprofit.id, { year: '2019' }) + Timecop.freeze(2020, 1, 1, 1, 0, 0, "+00:00") + generate_donation( + amount: charge_amount_large, + token: source_tokens[2].token, + date: Time.now.to_s + ) + result_for_2020 = QueryPayments.full_search(nonprofit.id, {year: "2020"}) + result_for_2019 = QueryPayments.full_search(nonprofit.id, {year: "2019"}) expect(result_for_2019[:data].count).to eq 1 expect(result_for_2020[:data].count).to eq 4 end @@ -300,42 +300,42 @@ def generate_donation(h) end end - describe 'event donations' do + describe "event donations" do let(:donation_result_yesterday) do generate_donation(amount: charge_amount_small, - event_id: event.id, - token: source_tokens[0].token, - date: (Time.now - 1.day).to_s) + event_id: event.id, + token: source_tokens[0].token, + date: (Time.now - 1.day).to_s) end let(:donation_result_today) do generate_donation(amount: charge_amount_medium, - event_id: event.id, - token: source_tokens[1].token, + event_id: event.id, + token: source_tokens[1].token, - date: Time.now.to_s) + date: Time.now.to_s) end let(:donation_result_tomorrow) do generate_donation(amount: charge_amount_large, - token: source_tokens[2].token, - date: (Time.now - 1.day).to_s) + token: source_tokens[2].token, + date: (Time.now - 1.day).to_s) end - let (:first_refund_of_yesterday) do - charge = donation_result_yesterday['charge'] + let(:first_refund_of_yesterday) do + charge = donation_result_yesterday["charge"] - InsertRefunds.with_stripe(charge.attributes, { amount: 100 }.with_indifferent_access) + InsertRefunds.with_stripe(charge.attributes, {amount: 100}.with_indifferent_access) end let(:second_refund_of_yesterday) do - charge = donation_result_yesterday['charge'] + charge = donation_result_yesterday["charge"] - InsertRefunds.with_stripe(charge.attributes, { amount: 50 }.with_indifferent_access) + InsertRefunds.with_stripe(charge.attributes, {amount: 50}.with_indifferent_access) end - it 'search includes refunds for that event ' do + it "search includes refunds for that event " do donation_result_yesterday donation_result_today donation_result_tomorrow @@ -345,46 +345,46 @@ def generate_donation(h) result = QueryPayments.full_search(nonprofit.id, event_id: event.id) expect(result[:data].count).to eq 4 - expect(result[:data]).to_not satisfy { |i| i.any? { |j| j['id'] == donation_result_tomorrow['payment']['id'] } } + expect(result[:data]).to_not satisfy { |i| i.any? { |j| j["id"] == donation_result_tomorrow["payment"]["id"] } } end end - describe 'campaign donations' do + describe "campaign donations" do let(:donation_result_yesterday) do generate_donation(amount: charge_amount_small, - campaign_id: campaign.id, - token: source_tokens[0].token, - date: (Time.now - 1.day).to_s) + campaign_id: campaign.id, + token: source_tokens[0].token, + date: (Time.now - 1.day).to_s) end let(:donation_result_today) do generate_donation(amount: charge_amount_medium, - campaign_id: campaign.id, - token: source_tokens[1].token, + campaign_id: campaign.id, + token: source_tokens[1].token, - date: Time.now.to_s) + date: Time.now.to_s) end let(:donation_result_tomorrow) do generate_donation(amount: charge_amount_large, - token: source_tokens[2].token, - date: (Time.now - 1.day).to_s) + token: source_tokens[2].token, + date: (Time.now - 1.day).to_s) end - let (:first_refund_of_yesterday) do - charge = donation_result_yesterday['charge'] + let(:first_refund_of_yesterday) do + charge = donation_result_yesterday["charge"] - InsertRefunds.with_stripe(charge.attributes, { amount: 100 }.with_indifferent_access) + InsertRefunds.with_stripe(charge.attributes, {amount: 100}.with_indifferent_access) end let(:second_refund_of_yesterday) do - charge = donation_result_yesterday['charge'] + charge = donation_result_yesterday["charge"] - InsertRefunds.with_stripe(charge.attributes, { amount: 50 }.with_indifferent_access) + InsertRefunds.with_stripe(charge.attributes, {amount: 50}.with_indifferent_access) end - it 'search includes refunds for that campaign ' do + it "search includes refunds for that campaign " do donation_result_yesterday donation_result_today donation_result_tomorrow @@ -394,7 +394,7 @@ def generate_donation(h) result = QueryPayments.full_search(nonprofit.id, campaign_id: campaign.id) expect(result[:data].count).to eq 4 - expect(result[:data]).to_not satisfy { |i| i.any? { |j| j['id'] == donation_result_tomorrow['payment']['id'] } } + expect(result[:data]).to_not satisfy { |i| i.any? { |j| j["id"] == donation_result_tomorrow["payment"]["id"] } } end end end diff --git a/spec/legacy_lib/query/query_recurring_donations_spec.rb b/spec/legacy_lib/query/query_recurring_donations_spec.rb index e86e53654c..8a15919d17 100644 --- a/spec/legacy_lib/query/query_recurring_donations_spec.rb +++ b/spec/legacy_lib/query/query_recurring_donations_spec.rb @@ -2,220 +2,220 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" # Note that the recurring donation used in these tests is created on 2020-01-01 and the first charge is created on that date describe QueryRecurringDonations do - around(:each) do |example| + around do |example| Timecop.freeze(2020, 4, 5) do example.run end end - describe '.calculate_monthly_donation_total' do - let(:nonprofit) { Qx.insert_into(:nonprofits).values(name: SecureRandom.uuid).ts.returning('*').execute.first } + describe ".calculate_monthly_donation_total" do + let(:nonprofit) { Qx.insert_into(:nonprofits).values(name: SecureRandom.uuid).ts.returning("*").execute.first } let(:rec_dons) do - Qx.insert_into('recurring_donations').values([ - { active: true, amount: 4000, interval: 1, time_unit: 'month' }, - { active: true, amount: 1000, interval: 2, time_unit: 'week' }, - { active: false, amount: 10_000, interval: 1, time_unit: 'month' } - ]).common_values(nonprofit_id: nonprofit['id']).ts.returning('*').execute + Qx.insert_into("recurring_donations").values([ + {active: true, amount: 4000, interval: 1, time_unit: "month"}, + {active: true, amount: 1000, interval: 2, time_unit: "week"}, + {active: false, amount: 10_000, interval: 1, time_unit: "month"} + ]).common_values(nonprofit_id: nonprofit["id"]).ts.returning("*").execute end - it 'adds up the total for all active recurring donations' do + it "adds up the total for all active recurring donations" do rec_dons - sum = QueryRecurringDonations.calculate_monthly_donation_total(nonprofit['id']) - expect(sum).to eq(rec_dons[0]['amount'] + rec_dons[1]['amount']) + sum = QueryRecurringDonations.calculate_monthly_donation_total(nonprofit["id"]) + expect(sum).to eq(rec_dons[0]["amount"] + rec_dons[1]["amount"]) end end - describe '.is_due?' do + describe ".is_due?" do let(:nonprofit) { force_create(:nm_justice) } let(:supporter) { force_create(:supporter, nonprofit: nonprofit) } - let(:donation) do + let(:donation) do force_create(:donation, amount: 1000, supporter: supporter, recurring: true, nonprofit: nonprofit) end - let(:defaults) { { amount: 1000, interval: 1, time_unit: 'month', nonprofit: nonprofit, supporter: supporter, active: true, donation: donation } } + let(:defaults) { {amount: 1000, interval: 1, time_unit: "month", nonprofit: nonprofit, supporter: supporter, active: true, donation: donation} } def create_recdon(params) force_create(:recurring_donation, defaults.merge(params)) end - it 'when inactive, is not due' do + it "when inactive, is not due" do rd = create_recdon(active: false) expect(QueryRecurringDonations.is_due?(rd.id)).to eq(false) end - it 'when it hits max n_failures, is not due' do + it "when it hits max n_failures, is not due" do rd = create_recdon(n_failures: 3) expect(QueryRecurringDonations.is_due?(rd.id)).to eq(false) end - it 'is due when it has no charges' do + it "is due when it has no charges" do rd = create_recdon({}) expect(QueryRecurringDonations.is_due?(rd.id)).to eq(true) end - it 'is not due when it has a charge this month' do + it "is not due when it has a charge this month" do rd = create_recdon({}) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex - expect(QueryRecurringDonations.is_due?(rd['id'])).to be false + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex + expect(QueryRecurringDonations.is_due?(rd["id"])).to be false end - it 'is due when it has charges && when monthly && not paid this month && not paid last month' do + it "is due when it has charges && when monthly && not paid this month && not paid last month" do rd = create_recdon({}) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(2.months.from_now) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end - it 'is due when monthly && no paydate && last charge was last month && last charge created at day <= today' do + it "is due when monthly && no paydate && last charge was last month && last charge created at day <= today" do rd = create_recdon({}) - Timecop.freeze(Time.parse('2020-01-01')) do - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + Timecop.freeze(Time.parse("2020-01-01")) do + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex end - Timecop.freeze(Time.parse('2020-02-01')) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + Timecop.freeze(Time.parse("2020-02-01")) do + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end - it 'is due when monthly && paydate present && last charge was last month && paydate <= today' do + it "is due when monthly && paydate present && last charge was last month && paydate <= today" do rd = create_recdon(paydate: 10) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(1.month.from_now.change(day: 10)) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end - it 'is due when not monthly and the timespan is 3 days and it is 3 days later' do - rd = create_recdon(time_unit: 'day', interval: 3) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + it "is due when not monthly and the timespan is 3 days and it is 3 days later" do + rd = create_recdon(time_unit: "day", interval: 3) + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(3.days.from_now) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end - it 'is due when not monthly and the timespan is 2 weeks and it is 2 weeks later' do - rd = create_recdon(time_unit: 'week', interval: 2) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + it "is due when not monthly and the timespan is 2 weeks and it is 2 weeks later" do + rd = create_recdon(time_unit: "week", interval: 2) + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(2.weeks.from_now) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end - it 'is due when not monthly and the timespan is 1 year and it is 1 year later' do - rd = create_recdon(time_unit: 'year', interval: 1) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + it "is due when not monthly and the timespan is 1 year and it is 1 year later" do + rd = create_recdon(time_unit: "year", interval: 1) + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(1.year.from_now) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end - it 'is not due when not monthly and it is not a timespan later' do - rd = create_recdon(time_unit: 'day', interval: 3) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + it "is not due when not monthly and it is not a timespan later" do + rd = create_recdon(time_unit: "day", interval: 3) + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(2.days.from_now) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be false + expect(QueryRecurringDonations.is_due?(rd["id"])).to be false end end - it 'is not due when monthly and has been paid this month' do + it "is not due when monthly and has been paid this month" do rd = create_recdon({}) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex - expect(QueryRecurringDonations.is_due?(rd['id'])).to be false + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex + expect(QueryRecurringDonations.is_due?(rd["id"])).to be false end - it 'is not due when monthly and no paydate and today is < last charge created_at day' do + it "is not due when monthly and no paydate and today is < last charge created_at day" do rd = create_recdon({}) - Timecop.freeze(Time.parse('2020-01-02')) do - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + Timecop.freeze(Time.parse("2020-01-02")) do + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex end - Timecop.freeze(Time.parse('2020-02-01')) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be false + Timecop.freeze(Time.parse("2020-02-01")) do + expect(QueryRecurringDonations.is_due?(rd["id"])).to be false end end - it 'is not due when monthly an a paydate is present and today < paydate' do + it "is not due when monthly an a paydate is present and today < paydate" do rd = create_recdon(paydate: 2) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'pending').ts.ex + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "pending").ts.ex Timecop.freeze(1.month.from_now.change(day: 1)) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be false + expect(QueryRecurringDonations.is_due?(rd["id"])).to be false end end - it 'is due when monthly and there are only failed charges this month' do + it "is due when monthly and there are only failed charges this month" do rd = create_recdon({}) - Qx.insert_into(:charges).values(donation_id: rd['donation_id'], amount: 1000, supporter_id: supporter['id'], nonprofit_id: nonprofit['id'], status: 'failed').ts.ex + Qx.insert_into(:charges).values(donation_id: rd["donation_id"], amount: 1000, supporter_id: supporter["id"], nonprofit_id: nonprofit["id"], status: "failed").ts.ex Timecop.freeze(1.month.from_now) do - expect(QueryRecurringDonations.is_due?(rd['id'])).to be true + expect(QueryRecurringDonations.is_due?(rd["id"])).to be true end end end - describe '.for_export_enumerable' do - before :each do - @nonprofit = force_create(:nm_justice, name: 'npo1') - @supporters = [force_create(:supporter, name: 'supporter-0', nonprofit: @nonprofit), - force_create(:supporter, name: 'supporter-1', nonprofit: @nonprofit)] + describe ".for_export_enumerable" do + before do + @nonprofit = force_create(:nm_justice, name: "npo1") + @supporters = [force_create(:supporter, name: "supporter-0", nonprofit: @nonprofit), + force_create(:supporter, name: "supporter-1", nonprofit: @nonprofit)] - @recurring_donations = [force_create(:recurring_donation, amount: 1000, active: false, n_failures: 0, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: 'edit_token_1'), - force_create(:recurring_donation, amount: 2000, active: true, n_failures: 3, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: 'edit_token_2'), - force_create(:recurring_donation, amount: 3000, active: true, n_failures: 0, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: 'edit_token_3'), - force_create(:recurring_donation, amount: 400, active: false, n_failures: 3, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: 'edit_token_4')] - @root_url = 'https://localhost:8080' + @recurring_donations = [force_create(:recurring_donation, amount: 1000, active: false, n_failures: 0, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: "edit_token_1"), + force_create(:recurring_donation, amount: 2000, active: true, n_failures: 3, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: "edit_token_2"), + force_create(:recurring_donation, amount: 3000, active: true, n_failures: 0, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: "edit_token_3"), + force_create(:recurring_donation, amount: 400, active: false, n_failures: 3, nonprofit: @nonprofit, donation: force_create(:donation), edit_token: "edit_token_4")] + @root_url = "https://localhost:8080" end let(:headers) { MockHelpers.recurring_donation_export_headers } - it 'finishes recurring donation export' do + it "finishes recurring donation export" do rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, {}).to_a expect(rows.length).to eq(5) expect(rows[0]).to eq(headers) end - it 'retrieves active' do - rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, active_and_not_failed: true, root_url: 'https://localhost:8080/').to_a + it "retrieves active" do + rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, active_and_not_failed: true, root_url: "https://localhost:8080/").to_a expect(rows.length).to eq(2) expect(rows[0]).to eq(headers) - expect(rows[1][1]).to eq('$30.00') + expect(rows[1][1]).to eq("$30.00") expect(rows[1][-1]).to eq(MockHelpers.generate_expected_rd_management_url(@root_url, @recurring_donations[2])) end - it 'retrieves cancelled' do - rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, active_and_not_failed: false, root_url: 'https://localhost:8080/').to_a + it "retrieves cancelled" do + rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, active_and_not_failed: false, root_url: "https://localhost:8080/").to_a expect(rows.length).to eq(2) expect(rows[0]).to eq(headers) - expect(rows[1][1]).to eq('$10.00') - expect(rows[1][-1]).to eq('') + expect(rows[1][1]).to eq("$10.00") + expect(rows[1][-1]).to eq("") end - it 'retrieves failed' do - rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, failed: true, root_url: 'https://localhost:8080/').to_a + it "retrieves failed" do + rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, failed: true, root_url: "https://localhost:8080/").to_a expect(rows.length).to eq(3) expect(rows[0]).to eq(headers) - expect(rows[1][1]).to eq('$20.00') - expect(rows[2][1]).to eq('$4.00') + expect(rows[1][1]).to eq("$20.00") + expect(rows[2][1]).to eq("$4.00") expect(rows[1][-1]).to eq(MockHelpers.generate_expected_rd_management_url(@root_url, @recurring_donations[1])) - expect(rows[2][-1]).to eq('') + expect(rows[2][-1]).to eq("") end - it 'retrieves not-failed' do - rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, failed: false, root_url: 'https://localhost:8080/').to_a + it "retrieves not-failed" do + rows = QueryRecurringDonations.for_export_enumerable(@nonprofit.id, failed: false, root_url: "https://localhost:8080/").to_a expect(rows.length).to eq(3) expect(rows[0]).to eq(headers) - expect(rows[1][1]).to eq('$10.00') - expect(rows[2][1]).to eq('$30.00') + expect(rows[1][1]).to eq("$10.00") + expect(rows[2][1]).to eq("$30.00") - expect(rows[1][-1]).to eq('') + expect(rows[1][-1]).to eq("") expect(rows[2][-1]).to eq(MockHelpers.generate_expected_rd_management_url(@root_url, @recurring_donations[2])) end end diff --git a/spec/legacy_lib/query/query_roles_spec.rb b/spec/legacy_lib/query/query_roles_spec.rb index f7eb5ba89a..381e4e6c1f 100644 --- a/spec/legacy_lib/query/query_roles_spec.rb +++ b/spec/legacy_lib/query/query_roles_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QueryRoles do include_context :shared_donation_charge_context @@ -11,27 +11,27 @@ let(:nonprofit_associate_role) { force_create(:role, user: user, host: nonprofit, name: :nonprofit_associate) } let(:other_nonprofit_associate_role) { force_create(:role, user: user, host: other_nonprofit, name: :nonprofit_associate) } - describe 'is_nonprofit_user?' do - it 'false for no role' do + describe "is_nonprofit_user?" do + it "false for no role" do expect(QueryRoles.is_nonprofit_user?(user.id, nonprofit.id)).to be_falsey end - it 'false for other nonprofit admin' do + it "false for other nonprofit admin" do other_nonprofit_admin_role expect(QueryRoles.is_nonprofit_user?(user.id, nonprofit.id)).to be_falsey end - it 'false for other nonprofit associate' do + it "false for other nonprofit associate" do other_nonprofit_associate_role expect(QueryRoles.is_nonprofit_user?(user.id, nonprofit.id)).to be_falsey end - it 'true for nonprofit admin' do + it "true for nonprofit admin" do nonprofit_admin_role expect(QueryRoles.is_nonprofit_user?(user.id, nonprofit.id)).to be_truthy end - it 'true for nonprofit admin' do + it "true for nonprofit admin" do nonprofit_associate_role expect(QueryRoles.is_nonprofit_user?(user.id, nonprofit.id)).to be_truthy end diff --git a/spec/legacy_lib/query/query_source_token_spec.rb b/spec/legacy_lib/query/query_source_token_spec.rb index 5bc793f1e9..5867bdbe48 100644 --- a/spec/legacy_lib/query/query_source_token_spec.rb +++ b/spec/legacy_lib/query/query_source_token_spec.rb @@ -2,15 +2,15 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QuerySourceToken do - describe '.get_and_increment_source_token' do - let(:our_uuid) { '7ab66a26-05e5-11e8-b4ef-8f19083c3cc7' } # random uuid I generated - let(:not_our_uuid) { 'a96e3c2c-05e5-11e8-80cc-177b86bb74cd' } # ditto - let(:fake_uuid) { '15c13da0-05e8-11e8-9cc0-e7ccb95e5f1f' } # ditto - let(:expired_uuid) { '061124ca-05f1-11e8-8730-57558ad1064d' } - let(:overused_uuid) { '0ac67006-05f1-11e8-902c-035df51dbc79' } + describe ".get_and_increment_source_token" do + let(:our_uuid) { "7ab66a26-05e5-11e8-b4ef-8f19083c3cc7" } # random uuid I generated + let(:not_our_uuid) { "a96e3c2c-05e5-11e8-80cc-177b86bb74cd" } # ditto + let(:fake_uuid) { "15c13da0-05e8-11e8-9cc0-e7ccb95e5f1f" } # ditto + let(:expired_uuid) { "061124ca-05f1-11e8-8730-57558ad1064d" } + let(:overused_uuid) { "0ac67006-05f1-11e8-902c-035df51dbc79" } let(:nonprofit) { force_create(:nm_justice) } let(:event) { force_create(:event, nonprofit: nonprofit) } @@ -28,66 +28,66 @@ let(:expired_source_token) { force_create(:source_token, token: expired_uuid, total_uses: 0, expiration: Time.now - 1.day) } let(:overused_source_token) { force_create(:source_token, token: overused_uuid, total_uses: 1, expiration: Time.now + 1.day, max_uses: 1) } - before(:each) do + before do our_source_token not_our_source_token expired_source_token overused_source_token end - around(:each) do |example| + around do |example| Timecop.freeze(2020, 5, 4) do example.run end end - describe 'param validation' do - it 'basic validation' do + describe "param validation" do + it "basic validation" do expect { QuerySourceToken.get_and_increment_source_token(nil) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :token, name: :required }, - { key: :token, name: :format } - ]) + {key: :token, name: :required}, + {key: :token, name: :format} + ]) } end - it 'raises if source_token cant be found' do + it "raises if source_token cant be found" do expect { QuerySourceToken.get_and_increment_source_token(fake_uuid) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :token } - ]) + {key: :token} + ]) expect(error.message).to eq "#{fake_uuid} doesn't represent a valid source" } end - it 'raises if token already used too much' do + it "raises if token already used too much" do expect { QuerySourceToken.get_and_increment_source_token(overused_uuid) }.to raise_error { |error| expect(error).to be_a ExpiredTokenError } end - it 'raises if token expired' do + it "raises if token expired" do expect { QuerySourceToken.get_and_increment_source_token(expired_uuid) }.to raise_error { |error| expect(error).to be_a ExpiredTokenError } end - it 'raises authentication error if event on it but user is nil' do + it "raises authentication error if event on it but user is nil" do expect { QuerySourceToken.get_and_increment_source_token(our_uuid) }.to raise_error { |error| expect(error).to be_a AuthenticationError } end - it 'raises authentication error if event on it but user is not with nonprofit' do + it "raises authentication error if event on it but user is not with nonprofit" do expect { QuerySourceToken.get_and_increment_source_token(our_uuid, other_user) }.to raise_error { |error| expect(error).to be_a AuthenticationError } end end - it 'increments and returns source token' do + it "increments and returns source token" do result = QuerySourceToken.get_and_increment_source_token(our_uuid, user) expect(result).to be_a SourceToken diff --git a/spec/legacy_lib/query/query_supporters_spec.rb b/spec/legacy_lib/query/query_supporters_spec.rb index ba05d4e4c0..62271e74ad 100644 --- a/spec/legacy_lib/query/query_supporters_spec.rb +++ b/spec/legacy_lib/query/query_supporters_spec.rb @@ -2,49 +2,49 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QuerySupporters do let(:gift_level_one_time) { 1111 } let(:gift_level_recurring) { 5585 } let(:gift_level_changed_recurring) { 5512 } - let(:campaign_gift_option_name) { 'theowthoinv' } + let(:campaign_gift_option_name) { "theowthoinv" } let(:np) { force_create(:nm_justice) } - let(:supporter1) { force_create(:supporter, nonprofit: np, name: 'Cacau')} - let(:supporter2) { force_create(:supporter, nonprofit: np, name: 'Penelope')} - let(:campaign) { force_create(:campaign, nonprofit: np, slug: "slug stuff")} - let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, name: campaign_gift_option_name, amount_one_time: gift_level_one_time, amount_recurring: gift_level_recurring)} - let(:campaign_gift1) { force_create(:campaign_gift, campaign_gift_option: campaign_gift_option, donation: donation1)} + let(:supporter1) { force_create(:supporter, nonprofit: np, name: "Cacau") } + let(:supporter2) { force_create(:supporter, nonprofit: np, name: "Penelope") } + let(:campaign) { force_create(:campaign, nonprofit: np, slug: "slug stuff") } + let(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign, name: campaign_gift_option_name, amount_one_time: gift_level_one_time, amount_recurring: gift_level_recurring) } + let(:campaign_gift1) { force_create(:campaign_gift, campaign_gift_option: campaign_gift_option, donation: donation1) } let(:payment_utc_time) { Time.new(2021, 10, 10, 1, 1, 0, "+00:00") } let(:payment2_utc_time) { Time.new(2021, 1, 1, 1, 1, 0, "+00:00") } - let(:donation1) { force_create(:donation, amount: gift_level_one_time, campaign: campaign, supporter:supporter1, date: payment_utc_time)} - let(:donation4) { force_create(:donation, amount: gift_level_one_time, campaign: campaign, supporter:supporter1, date: payment2_utc_time)} - let(:donation5) { force_create(:donation, amount: gift_level_one_time, campaign: campaign, supporter:supporter2, date: payment2_utc_time)} + let(:donation1) { force_create(:donation, amount: gift_level_one_time, campaign: campaign, supporter: supporter1, date: payment_utc_time) } + let(:donation4) { force_create(:donation, amount: gift_level_one_time, campaign: campaign, supporter: supporter1, date: payment2_utc_time) } + let(:donation5) { force_create(:donation, amount: gift_level_one_time, campaign: campaign, supporter: supporter2, date: payment2_utc_time) } - let(:payment1) {force_create(:payment, gross_amount: gift_level_one_time, donation: donation1, date: payment_utc_time)} + let(:payment1) { force_create(:payment, gross_amount: gift_level_one_time, donation: donation1, date: payment_utc_time) } - let(:donation2) {force_create(:donation, amount: gift_level_changed_recurring, campaign: campaign, supporter:supporter2)} - let(:payment2) {force_create(:payment, gross_amount: gift_level_recurring, donation: donation2)} - let(:payment4) {force_create(:payment, gross_amount: gift_level_one_time, donation: donation4, date: payment2_utc_time)} - let(:payment5) {force_create(:payment, gross_amount: gift_level_one_time, donation: donation5, date: payment2_utc_time)} + let(:donation2) { force_create(:donation, amount: gift_level_changed_recurring, campaign: campaign, supporter: supporter2) } + let(:payment2) { force_create(:payment, gross_amount: gift_level_recurring, donation: donation2) } + let(:payment4) { force_create(:payment, gross_amount: gift_level_one_time, donation: donation4, date: payment2_utc_time) } + let(:payment5) { force_create(:payment, gross_amount: gift_level_one_time, donation: donation5, date: payment2_utc_time) } - let(:payment3) {force_create(:payment, gross_amount: gift_level_changed_recurring, donation: donation2)} - let(:campaign_gift2) { force_create(:campaign_gift, campaign_gift_option: campaign_gift_option, donation: donation2)} - let(:recurring) {force_create(:recurring_donation, donation: donation2, amount: gift_level_changed_recurring)} + let(:payment3) { force_create(:payment, gross_amount: gift_level_changed_recurring, donation: donation2) } + let(:campaign_gift2) { force_create(:campaign_gift, campaign_gift_option: campaign_gift_option, donation: donation2) } + let(:recurring) { force_create(:recurring_donation, donation: donation2, amount: gift_level_changed_recurring) } let(:note_content_1) do - 'CONTENT1' + "CONTENT1" end let(:note_content_2) do - 'CONTENT2' + "CONTENT2" end let(:note_content_3) do - 'CONTENT3' + "CONTENT3" end let(:supporter_note_for_s1) do @@ -75,16 +75,16 @@ QuerySupporters.campaign_list(np.id, campaign.id, page: 0) end - it 'counts gift donations properly' do + it "counts gift donations properly" do init_all glm = campaign_list data = glm[:data] - expect(data.map { |i| i['total_raised'] }).to match_array([gift_level_one_time, gift_level_recurring]) + expect(data.map { |i| i["total_raised"] }).to match_array([gift_level_one_time, gift_level_recurring]) end - describe '.supporter_note_export_enumerable' do + describe ".supporter_note_export_enumerable" do let(:lazy_enumerable) do supporter_note_for_s1 supporter_note_1_for_s2 @@ -92,45 +92,45 @@ QuerySupporters.supporter_note_export_enumerable(np.id, {}) end - it 'is a lazy enumerable' do + it "is a lazy enumerable" do expect(lazy_enumerable).to be_a Enumerator::Lazy end - it 'is three items long' do + it "is three items long" do expect(lazy_enumerable.to_a.size).to eq 4 end - it 'has correct headers' do - expect(lazy_enumerable.to_a.first).to eq ['Id', 'Email', 'Note Created At', 'Note Contents'] + it "has correct headers" do + expect(lazy_enumerable.to_a.first).to eq ["Id", "Email", "Note Created At", "Note Contents"] end end - describe '.full_search' do + describe ".full_search" do before do supporter1.payments = [payment1, payment4] supporter2.payments = [payment5] end - it 'returns the UTC date when the timezone is not specified' do - result = QuerySupporters.full_search(np.id, { search: 'Cacau' }) - expect(result[:data].first["last_contribution"]).to eq(payment_utc_time.strftime('%m/%d/%y')) + it "returns the UTC date when the timezone is not specified" do + result = QuerySupporters.full_search(np.id, {search: "Cacau"}) + expect(result[:data].first["last_contribution"]).to eq(payment_utc_time.strftime("%m/%d/%y")) end - it 'returns the converted date when the timezone is specified' do - np.update(timezone: 'America/New_York') - result = QuerySupporters.full_search(np.id, { search: 'Cacau' }) - expect(result[:data].first["last_contribution"]).to eq((payment_utc_time - 1.day).strftime('%m/%d/%y')) + it "returns the converted date when the timezone is specified" do + np.update(timezone: "America/New_York") + result = QuerySupporters.full_search(np.id, {search: "Cacau"}) + expect(result[:data].first["last_contribution"]).to eq((payment_utc_time - 1.day).strftime("%m/%d/%y")) end - it 'finds the payments on dates after the specified dates' do - np.update(timezone: 'America/New_York') - result = QuerySupporters.full_search(np.id, { last_payment_after: (payment2_utc_time + 1.day).to_s }) + it "finds the payments on dates after the specified dates" do + np.update(timezone: "America/New_York") + result = QuerySupporters.full_search(np.id, {last_payment_after: (payment2_utc_time + 1.day).to_s}) expect(result[:data].count).to eq 1 end - it 'finds the payments on dates before the specified dates' do - np.update(timezone: 'America/New_York') - result = QuerySupporters.full_search(np.id, { last_payment_before: payment_utc_time.to_s }) + it "finds the payments on dates before the specified dates" do + np.update(timezone: "America/New_York") + result = QuerySupporters.full_search(np.id, {last_payment_before: payment_utc_time.to_s}) expect(result[:data].count).to eq 2 end end diff --git a/spec/legacy_lib/query/query_ticket_levels_spec.rb b/spec/legacy_lib/query/query_ticket_levels_spec.rb index 8b89d6be46..ebf00cda1b 100644 --- a/spec/legacy_lib/query/query_ticket_levels_spec.rb +++ b/spec/legacy_lib/query/query_ticket_levels_spec.rb @@ -2,41 +2,41 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QueryTicketLevels do include_context :shared_donation_charge_context - describe '.gross_amount_from_tickets' do - it 'handles free tickets only properly' do - result = QueryTicketLevels.gross_amount_from_tickets(['ticket_level_id' => free_ticket_level.id, 'quantity' => 5], nil) + describe ".gross_amount_from_tickets" do + it "handles free tickets only properly" do + result = QueryTicketLevels.gross_amount_from_tickets(["ticket_level_id" => free_ticket_level.id, "quantity" => 5], nil) expect(result).to eq 0 end - it 'handles nonfree tickets only properly' do - result = QueryTicketLevels.gross_amount_from_tickets(['ticket_level_id' => ticket_level.id, 'quantity' => 5], nil) + it "handles nonfree tickets only properly" do + result = QueryTicketLevels.gross_amount_from_tickets(["ticket_level_id" => ticket_level.id, "quantity" => 5], nil) expect(result).to eq 2000 end - it 'handles mix of tickets properly' do + it "handles mix of tickets properly" do result = QueryTicketLevels.gross_amount_from_tickets( - [{ 'ticket_level_id' => ticket_level.id, 'quantity' => 5 }, - { 'ticket_level_id' => ticket_level2.id, 'quantity' => 2 }, - { 'ticket_level_id' => free_ticket_level.id, 'quantity' => 4000 }], nil - ) + [{"ticket_level_id" => ticket_level.id, "quantity" => 5}, + {"ticket_level_id" => ticket_level2.id, "quantity" => 2}, + {"ticket_level_id" => free_ticket_level.id, "quantity" => 4000}], nil + ) expect(result).to eq 3000 end - it 'handles mix of tickets properly with discount code properly' do + it "handles mix of tickets properly with discount code properly" do result = QueryTicketLevels.gross_amount_from_tickets( - [{ 'ticket_level_id' => ticket_level.id, 'quantity' => 5 }, - { 'ticket_level_id' => ticket_level2.id, 'quantity' => 2 }, - { 'ticket_level_id' => free_ticket_level.id, 'quantity' => 4000 }], event_discount.id - ) + [{"ticket_level_id" => ticket_level.id, "quantity" => 5}, + {"ticket_level_id" => ticket_level2.id, "quantity" => 2}, + {"ticket_level_id" => free_ticket_level.id, "quantity" => 4000}], event_discount.id + ) expect(result).to eq 2400 end end - describe '.verify_tickets_available' do + describe ".verify_tickets_available" do let(:ticket_level_1) { force_create(:ticket_level, limit: 3, event: event) } let(:ticket_level_2) { force_create(:ticket_level, limit: 2, event: event) } let(:tickets) do @@ -46,35 +46,35 @@ ] end - it 'fails when ticket level is too many' do + it "fails when ticket level is too many" do expect do QueryTicketLevels.verify_tickets_available([ - { ticket_level_id: ticket_level_1.id, quantity: 50 }, - { ticket_level_id: ticket_level_2.id, quantity: 1 } - ]) - end .to raise_error(NotEnoughQuantityError) + {ticket_level_id: ticket_level_1.id, quantity: 50}, + {ticket_level_id: ticket_level_2.id, quantity: 1} + ]) + end.to raise_error(NotEnoughQuantityError) expect do QueryTicketLevels.verify_tickets_available([ - { ticket_level_id: ticket_level_2.id, quantity: 3 } - ]) - end .to raise_error(NotEnoughQuantityError) + {ticket_level_id: ticket_level_2.id, quantity: 3} + ]) + end.to raise_error(NotEnoughQuantityError) end - it 'allows when a full item is at 0 and other is acceptable' do + it "allows when a full item is at 0 and other is acceptable" do expect do QueryTicketLevels.verify_tickets_available([ - { ticket_level_id: ticket_level_1.id, quantity: 0 }, - { ticket_level_id: ticket_level_2.id, quantity: 2 } - ]) - end .to_not raise_error + {ticket_level_id: ticket_level_1.id, quantity: 0}, + {ticket_level_id: ticket_level_2.id, quantity: 2} + ]) + end.to_not raise_error end - it 'allows when only acceptable are passed ' do + it "allows when only acceptable are passed " do expect do QueryTicketLevels.verify_tickets_available([ - { ticket_level_id: ticket_level_2.id, quantity: 2 } - ]) - end .to_not raise_error + {ticket_level_id: ticket_level_2.id, quantity: 2} + ]) + end.to_not raise_error end end end diff --git a/spec/legacy_lib/query/query_users_spec.rb b/spec/legacy_lib/query/query_users_spec.rb index 71c37251f8..c9856b1b35 100644 --- a/spec/legacy_lib/query/query_users_spec.rb +++ b/spec/legacy_lib/query/query_users_spec.rb @@ -2,10 +2,10 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe QueryUsers do - describe '.nonprofit_user_emails', pending: true do + describe ".nonprofit_user_emails", pending: true do before(:all) do # @np = Psql.execute(Qexpr.new.insert('nonprofits', [{name: 'xxyy'}])).first # @@ -45,12 +45,12 @@ # ], {common_data: {nonprofit_id: @np['id']}, no_timestamps: true})) end - it 'Returns all users who have the respective setting enabled (or no settings set), and does not return people without the right role' do - expect(QueryUsers.nonprofit_user_emails(@np['id'], 'notify_payments').sort).to eq([0, 2, 3, 4, 5].map { |id| @users[id]['email'] }.concat([@user_no_settings['email']]).sort) - expect(QueryUsers.nonprofit_user_emails(@np['id'], 'notify_campaigns').sort).to eq([0, 1, 3, 4, 5].map { |id| @users[id]['email'] }.concat([@user_no_settings['email']]).sort) - expect(QueryUsers.nonprofit_user_emails(@np['id'], 'notify_events').sort).to eq([0, 1, 2, 4, 5].map { |id| @users[id]['email'] }.concat([@user_no_settings['email']]).sort) - expect(QueryUsers.nonprofit_user_emails(@np['id'], 'notify_payouts').sort).to eq([0, 1, 2, 3, 5].map { |id| @users[id]['email'] }.concat([@user_no_settings['email']]).sort) - expect(QueryUsers.nonprofit_user_emails(@np['id'], 'notify_recurring_donations').sort).to eq([0, 1, 2, 3, 4].map { |id| @users[id]['email'] }.concat([@user_no_settings['email']]).sort) + it "Returns all users who have the respective setting enabled (or no settings set), and does not return people without the right role" do + expect(QueryUsers.nonprofit_user_emails(@np["id"], "notify_payments").sort).to eq([0, 2, 3, 4, 5].map { |id| @users[id]["email"] }.concat([@user_no_settings["email"]]).sort) + expect(QueryUsers.nonprofit_user_emails(@np["id"], "notify_campaigns").sort).to eq([0, 1, 3, 4, 5].map { |id| @users[id]["email"] }.concat([@user_no_settings["email"]]).sort) + expect(QueryUsers.nonprofit_user_emails(@np["id"], "notify_events").sort).to eq([0, 1, 2, 4, 5].map { |id| @users[id]["email"] }.concat([@user_no_settings["email"]]).sort) + expect(QueryUsers.nonprofit_user_emails(@np["id"], "notify_payouts").sort).to eq([0, 1, 2, 3, 5].map { |id| @users[id]["email"] }.concat([@user_no_settings["email"]]).sort) + expect(QueryUsers.nonprofit_user_emails(@np["id"], "notify_recurring_donations").sort).to eq([0, 1, 2, 3, 4].map { |id| @users[id]["email"] }.concat([@user_no_settings["email"]]).sort) end end end diff --git a/spec/legacy_lib/retrieve/retrieve_active_record_items_spec.rb b/spec/legacy_lib/retrieve/retrieve_active_record_items_spec.rb index 511ea669c6..f198154a1a 100644 --- a/spec/legacy_lib/retrieve/retrieve_active_record_items_spec.rb +++ b/spec/legacy_lib/retrieve/retrieve_active_record_items_spec.rb @@ -2,76 +2,78 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe RetrieveActiveRecordItems do - describe '.retrieve' do + describe ".retrieve" do let(:item) { force_create(:supporter, nonprofit: item2) } let(:item2) { force_create(:nm_justice) } - it 'raises if not a class for key' do - expect { RetrieveActiveRecordItems.retrieve('item' => 1) }.to raise_error(ArgumentError) + + it "raises if not a class for key" do + expect { RetrieveActiveRecordItems.retrieve("item" => 1) }.to raise_error(ArgumentError) end - it 'raises if optional is false and value is nil' do + it "raises if optional is false and value is nil" do expect { RetrieveActiveRecordItems.retrieve(ActiveRecord => nil) }.to raise_error(ArgumentError) end - it 'raises if optional is true and value is not integer' do - expect { RetrieveActiveRecordItems.retrieve({ ActiveRecord => 'number' }, true) }.to raise_error(ArgumentError) + it "raises if optional is true and value is not integer" do + expect { RetrieveActiveRecordItems.retrieve({ActiveRecord => "number"}, true) }.to raise_error(ArgumentError) end - it 'raises if optional is true and value is not positive integer' do - expect { RetrieveActiveRecordItems.retrieve({ ActiveRecord => -1 }, true) }.to raise_error(ArgumentError) + it "raises if optional is true and value is not positive integer" do + expect { RetrieveActiveRecordItems.retrieve({ActiveRecord => -1}, true) }.to raise_error(ArgumentError) end - it 'gets valid item as optional or not' do - expected = { Supporter => item, Nonprofit => item2 } + it "gets valid item as optional or not" do + expected = {Supporter => item, Nonprofit => item2} expect(RetrieveActiveRecordItems.retrieve(Supporter => item.id, Nonprofit => item2.id)).to eq expected - expect(RetrieveActiveRecordItems.retrieve({ Supporter => item.id, Nonprofit => item2.id }, true)).to eq expected + expect(RetrieveActiveRecordItems.retrieve({Supporter => item.id, Nonprofit => item2.id}, true)).to eq expected end - it 'raises if youve put in an invalid id' do + it "raises if youve put in an invalid id" do expect { RetrieveActiveRecordItems.retrieve(Supporter => 5555, Nonprofit => item2.id) }.to raise_error(ParamValidation::ValidationError) - expect { RetrieveActiveRecordItems.retrieve({ Supporter => 5555, Nonprofit => item2.id }, true) }.to raise_error(ParamValidation::ValidationError) + expect { RetrieveActiveRecordItems.retrieve({Supporter => 5555, Nonprofit => item2.id}, true) }.to raise_error(ParamValidation::ValidationError) end - it 'gets valid item as optional or not' do - expected = { Supporter => item, User => nil } - expect(RetrieveActiveRecordItems.retrieve({ Supporter => item.id, User => nil }, true)).to eq expected + it "gets valid item as optional or not" do + expected = {Supporter => item, User => nil} + expect(RetrieveActiveRecordItems.retrieve({Supporter => item.id, User => nil}, true)).to eq expected end end - describe '.retrieve_from_keys' do + describe ".retrieve_from_keys" do let(:item) { force_create(:supporter, nonprofit: item2) } let(:item2) { force_create(:nm_justice) } - it 'raises if not a class for key' do - expect { RetrieveActiveRecordItems.retrieve_from_keys({}, 'item' => 1) }.to raise_error(ArgumentError) + + it "raises if not a class for key" do + expect { RetrieveActiveRecordItems.retrieve_from_keys({}, "item" => 1) }.to raise_error(ArgumentError) end - it 'raises if optional is false and value is nil' do - expect { RetrieveActiveRecordItems.retrieve_from_keys({ data: nil }, Nonprofit => :data) }.to raise_error(ParamValidation::ValidationError) + it "raises if optional is false and value is nil" do + expect { RetrieveActiveRecordItems.retrieve_from_keys({data: nil}, Nonprofit => :data) }.to raise_error(ParamValidation::ValidationError) end - it 'raises if optional is true and value is not integer' do - expect { RetrieveActiveRecordItems.retrieve_from_keys({ data: '' }, { Nonprofit => :data }, true) }.to raise_error(ParamValidation::ValidationError) + it "raises if optional is true and value is not integer" do + expect { RetrieveActiveRecordItems.retrieve_from_keys({data: ""}, {Nonprofit => :data}, true) }.to raise_error(ParamValidation::ValidationError) end - it 'raises if optional is true and value is not positive integer' do - expect { RetrieveActiveRecordItems.retrieve_from_keys({ data: -1 }, { Nonprofit => :data }, true) }.to raise_error(ParamValidation::ValidationError) + it "raises if optional is true and value is not positive integer" do + expect { RetrieveActiveRecordItems.retrieve_from_keys({data: -1}, {Nonprofit => :data}, true) }.to raise_error(ParamValidation::ValidationError) end - it 'gets valid item as optional or not' do - expected = { supporter: item, nonprofit: item2 } - expect(RetrieveActiveRecordItems.retrieve_from_keys({ supporter: item.id, nonprofit: item2.id }, Supporter => :supporter, Nonprofit => :nonprofit)).to eq expected - expect(RetrieveActiveRecordItems.retrieve_from_keys({ supporter: item.id, nonprofit: item2.id }, { Supporter => :supporter, Nonprofit => :nonprofit }, true)).to eq expected + it "gets valid item as optional or not" do + expected = {supporter: item, nonprofit: item2} + expect(RetrieveActiveRecordItems.retrieve_from_keys({supporter: item.id, nonprofit: item2.id}, Supporter => :supporter, Nonprofit => :nonprofit)).to eq expected + expect(RetrieveActiveRecordItems.retrieve_from_keys({supporter: item.id, nonprofit: item2.id}, {Supporter => :supporter, Nonprofit => :nonprofit}, true)).to eq expected end - it 'raises if youve put in an invalid id' do - expect { RetrieveActiveRecordItems.retrieve_from_keys({ supporter: 5555, nonprofit: item2.id }, Supporter => :supporter, Nonprofit => :nonprofit) }.to raise_error(ParamValidation::ValidationError) - expect { RetrieveActiveRecordItems.retrieve_from_keys({ supporter: 5555, nonprofit: item2.id }, { Supporter => :supporter, Nonprofit => :nonprofit }, true) }.to raise_error(ParamValidation::ValidationError) + it "raises if youve put in an invalid id" do + expect { RetrieveActiveRecordItems.retrieve_from_keys({supporter: 5555, nonprofit: item2.id}, Supporter => :supporter, Nonprofit => :nonprofit) }.to raise_error(ParamValidation::ValidationError) + expect { RetrieveActiveRecordItems.retrieve_from_keys({supporter: 5555, nonprofit: item2.id}, {Supporter => :supporter, Nonprofit => :nonprofit}, true) }.to raise_error(ParamValidation::ValidationError) end - it 'gets valid item as optional or not' do - expected = { supporter: item, user: nil } - expect(RetrieveActiveRecordItems.retrieve_from_keys({ supporter: item.id, user: nil }, { Supporter => :supporter, User => :user }, true)).to eq expected + it "gets valid item as optional or not" do + expected = {supporter: item, user: nil} + expect(RetrieveActiveRecordItems.retrieve_from_keys({supporter: item.id, user: nil}, {Supporter => :supporter, User => :user}, true)).to eq expected end end end diff --git a/spec/legacy_lib/slug_copy_naming_algorithm_spec.rb b/spec/legacy_lib/slug_copy_naming_algorithm_spec.rb index e5ec38cf2e..684754041e 100644 --- a/spec/legacy_lib/slug_copy_naming_algorithm_spec.rb +++ b/spec/legacy_lib/slug_copy_naming_algorithm_spec.rb @@ -2,13 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe SlugCopyNamingAlgorithm do - describe '.create_copy_name' do + describe ".create_copy_name" do before(:all) do Timecop.freeze(2020, 5, 4) end + after(:all) do Timecop.return end @@ -17,29 +18,30 @@ def set_name(name) @name = name end - let(:short_slug) { 'slug_name' } - let(:short_slug_copy_today) { 'slug_name_copy_00' } - let(:short_slug_copy_today_plus_1) { 'slug_name_copy_01' } - let(:copy_base) { 'slug_name_copy' } + let(:short_slug) { "slug_name" } + let(:short_slug_copy_today) { "slug_name_copy_00" } + let(:short_slug_copy_today_plus_1) { "slug_name_copy_01" } + let(:copy_base) { "slug_name_copy" } let(:nonprofit) { force_create(:nm_justice) } - describe 'events' do + describe "events" do let(:event) { force_create(:event, slug: @name, nonprofit: nonprofit) } let(:event2) { force_create(:event, slug: @name2, nonprofit: nonprofit) } let(:events_at_max_copies) do (0..30).collect do |i| - force_create(:event, slug: "#{@copy_base}_#{format('%02d', i)}", nonprofit: nonprofit) + force_create(:event, slug: "#{@copy_base}_#{format("%02d", i)}", nonprofit: nonprofit) end end let(:algo) { SlugCopyNamingAlgorithm.new(Event, nonprofit.id) } - describe 'event slugs' do - it 'not a copy' do + + describe "event slugs" do + it "not a copy" do @name = short_slug event expect(algo.create_copy_name(@name)).to eq short_slug_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = short_slug @name2 = short_slug_copy_today event @@ -48,28 +50,29 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_slug_copy_today_plus_1 end - it 'has 30 as max copies' do + it "has 30 as max copies" do expect(algo.max_copies).to eq 30 end end end - describe 'campaigns' do + describe "campaigns" do let(:campaign) { force_create(:campaign, slug: @name, nonprofit: nonprofit) } let(:campaign2) { force_create(:campaign, slug: @name2, nonprofit: nonprofit) } let(:campaigns_at_max_copies) do (0..30).collect do |i| - force_create(:campaign, slug: "#{@copy_base}_#{format('%02d', i)}", nonprofit: nonprofit) + force_create(:campaign, slug: "#{@copy_base}_#{format("%02d", i)}", nonprofit: nonprofit) end end let(:algo) { SlugCopyNamingAlgorithm.new(Campaign, nonprofit.id) } - describe 'campaign slugs' do - it 'not a copy' do + + describe "campaign slugs" do + it "not a copy" do @name = short_slug campaign expect(algo.create_copy_name(@name)).to eq short_slug_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = short_slug @name2 = short_slug_copy_today campaign @@ -78,7 +81,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_slug_copy_today_plus_1 end - it 'has 30 as max copies' do + it "has 30 as max copies" do expect(algo.max_copies).to eq 30 end end diff --git a/spec/legacy_lib/slug_nonprofit_naming_algorithm_spec.rb b/spec/legacy_lib/slug_nonprofit_naming_algorithm_spec.rb index 3d40691fc3..68502d0c47 100644 --- a/spec/legacy_lib/slug_nonprofit_naming_algorithm_spec.rb +++ b/spec/legacy_lib/slug_nonprofit_naming_algorithm_spec.rb @@ -2,13 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe SlugNonprofitNamingAlgorithm do - describe '.create_copy_name' do + describe ".create_copy_name" do before(:all) do Timecop.freeze(2020, 5, 4) end + after(:all) do Timecop.return end @@ -17,35 +18,35 @@ def set_name(name) @name = name end - let(:short_slug) { 'slug_name' } - let(:short_slug_copy_today) { 'slug_name-00' } - let(:short_slug_copy_today_plus_1) { 'slug_name-01' } - let(:copy_base) { 'slug_name' } + let(:short_slug) { "slug_name" } + let(:short_slug_copy_today) { "slug_name-00" } + let(:short_slug_copy_today_plus_1) { "slug_name-01" } + let(:copy_base) { "slug_name" } - let(:state_slug) { 'state_slug' } - let(:city_slug) { 'city_slug' } - let(:not_our_state_slug) { 'not_our_state_slug' } - let(:not_our_city_slug) { 'not_our_city_slug' } + let(:state_slug) { "state_slug" } + let(:city_slug) { "city_slug" } + let(:not_our_state_slug) { "not_our_state_slug" } + let(:not_our_city_slug) { "not_our_city_slug" } - describe 'nonprofits' do + describe "nonprofits" do let(:nonprofit) { force_create(:nm_justice, slug: @name, state_code_slug: state_slug, city_slug: city_slug) } let(:nonprofit2) { force_create(:fv_poverty, slug: @name2, state_code_slug: state_slug, city_slug: city_slug) } let(:nonprofit_in_other_city) { force_create(:nm_justice, slug: @name, state_code_slug: state_slug, city_slug: not_our_city_slug, id: 523950250) } let(:nonprofit_in_other_state) { force_create(:fv_poverty, slug: @name, state_code_slug: not_our_state_slug, city_slug: city_slug, id: 5239502) } let(:nonprofit_at_max_copies) do (0..99).collect do |i| - force_create(:nonprofit, slug: "#{@copy_base}-#{format('%02d', i)}", state_code_slug: state_slug, city_slug: city_slug) + force_create(:nonprofit, slug: "#{@copy_base}-#{format("%02d", i)}", state_code_slug: state_slug, city_slug: city_slug) end end let(:algo) { SlugNonprofitNamingAlgorithm.new(state_slug, city_slug) } - describe 'nonprofit slugs' do - it 'not a copy' do + describe "nonprofit slugs" do + it "not a copy" do @name = short_slug nonprofit expect(algo.create_copy_name(@name)).to eq short_slug_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = short_slug @name2 = short_slug_copy_today nonprofit @@ -56,7 +57,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_slug_copy_today_plus_1 end - it 'it has 99 as max copies' do + it "it has 99 as max copies" do expect(algo.max_copies).to eq 99 end end diff --git a/spec/legacy_lib/slug_p2p_campaign_naming_algorithm_spec.rb b/spec/legacy_lib/slug_p2p_campaign_naming_algorithm_spec.rb index bf7657a568..85e8ffad2f 100644 --- a/spec/legacy_lib/slug_p2p_campaign_naming_algorithm_spec.rb +++ b/spec/legacy_lib/slug_p2p_campaign_naming_algorithm_spec.rb @@ -2,13 +2,14 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe SlugP2pCampaignNamingAlgorithm do - describe '.create_copy_name' do + describe ".create_copy_name" do before(:all) do Timecop.freeze(2020, 5, 4) end + after(:all) do Timecop.return end @@ -17,29 +18,30 @@ def set_name(name) @name = name end - let(:short_slug) { 'slug_name' } - let(:short_slug_copy_today) { 'slug_name_000' } - let(:short_slug_copy_today_plus_1) { 'slug_name_001' } - let(:copy_base) { 'slug_name' } + let(:short_slug) { "slug_name" } + let(:short_slug_copy_today) { "slug_name_000" } + let(:short_slug_copy_today_plus_1) { "slug_name_001" } + let(:copy_base) { "slug_name" } let(:nonprofit) { force_create(:nm_justice) } - describe 'campaigns' do + describe "campaigns" do let(:campaign) { force_create(:campaign, slug: @name, nonprofit: nonprofit, deleted: true) } let(:campaign2) { force_create(:campaign, slug: @name2, nonprofit: nonprofit) } let(:campaigns_at_max_copies) do (0..999).collect do |i| - force_create(:campaign, slug: "#{@copy_base}_#{format('%03d', i)}", nonprofit: nonprofit) + force_create(:campaign, slug: "#{@copy_base}_#{format("%03d", i)}", nonprofit: nonprofit) end end let(:algo) { SlugP2pCampaignNamingAlgorithm.new(nonprofit.id) } - describe 'campaign slugs' do - it 'not a copy' do + + describe "campaign slugs" do + it "not a copy" do @name = short_slug campaign expect(algo.create_copy_name(@name)).to eq short_slug_copy_today end - it 'one copy exists' do + it "one copy exists" do @name = short_slug @name2 = short_slug_copy_today campaign @@ -48,7 +50,7 @@ def set_name(name) expect(algo.create_copy_name(@name2)).to eq short_slug_copy_today_plus_1 end - it 'has 999 as the max_copies' do + it "has 999 as the max_copies" do expect(algo.max_copies).to eq 999 end end diff --git a/spec/legacy_lib/stripe_account_spec.rb b/spec/legacy_lib/stripe_account_spec.rb index 1dc488a2e7..291e0ca64a 100644 --- a/spec/legacy_lib/stripe_account_spec.rb +++ b/spec/legacy_lib/stripe_account_spec.rb @@ -2,93 +2,94 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'stripe' -require 'stripe_mock' +require "rails_helper" +require "stripe" +require "stripe_mock" describe StripeAccount do let(:stripe_helper) { StripeMockHelper.default_helper } - around(:each) do |example| - StripeMockHelper.mock do + around do |example| + StripeMockHelper.mock do example.run end end let(:nonprofit) { force_create(:nm_justice) } - describe '.find_or_create' do - describe 'param validation' do - it 'basic param validation' do + describe ".find_or_create" do + describe "param validation" do + it "basic param validation" do expect { StripeAccount.find_or_create(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :nonprofit_id, name: :required }, - { key: :nonprofit_id, name: :is_integer }]) + expect_validation_errors(error.data, [{key: :nonprofit_id, name: :required}, + {key: :nonprofit_id, name: :is_integer}]) end) end - it 'validate np' do + it "validate np" do expect { StripeAccount.find_or_create(5555) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :nonprofit_id }]) + expect_validation_errors(error.data, [{key: :nonprofit_id}]) end) end end + # basically the same as running create - describe 'creates new Stripe Account if none is set exists' do + describe "creates new Stripe Account if none is set exists" do let!(:result) { StripeAccount.find_or_create(nonprofit.id) } - it 'returns a Stripe acct id' do + it "returns a Stripe acct id" do expect(result).to_not be_blank end - it 'sets the Account values on Stripe' do + it "sets the Account values on Stripe" do saved_account = Stripe::Account.retrieve(result) - expect(saved_account['managed']).to eq true - expect(saved_account['business_name']).to eq nonprofit.name - expect(saved_account['email']).to eq nonprofit.email - expect(saved_account['business_url']).to eq nonprofit.website - expect(saved_account['legal_entity']['type']).to eq 'company' - expect(saved_account['legal_entity']['address']['city']).to eq nonprofit.city - expect(saved_account['legal_entity']['address']['state']).to eq nonprofit.state_code - expect(saved_account['legal_entity']['business_name']).to eq nonprofit.name - expect(saved_account['product_description']).to eq 'Nonprofit donations' - expect(saved_account['transfer_schedule']['interval']).to eq('manual') + expect(saved_account["managed"]).to eq true + expect(saved_account["business_name"]).to eq nonprofit.name + expect(saved_account["email"]).to eq nonprofit.email + expect(saved_account["business_url"]).to eq nonprofit.website + expect(saved_account["legal_entity"]["type"]).to eq "company" + expect(saved_account["legal_entity"]["address"]["city"]).to eq nonprofit.city + expect(saved_account["legal_entity"]["address"]["state"]).to eq nonprofit.state_code + expect(saved_account["legal_entity"]["business_name"]).to eq nonprofit.name + expect(saved_account["product_description"]).to eq "Nonprofit donations" + expect(saved_account["transfer_schedule"]["interval"]).to eq("manual") end - it 'updates the nonprofit itself' do + it "updates the nonprofit itself" do np = Nonprofit.find(nonprofit.id) expect(np.stripe_account_id).to eq result end end - describe 'get stripe account from database' do - let(:stripe_acct_id) { 'stripe_account_id' } + describe "get stripe account from database" do + let(:stripe_acct_id) { "stripe_account_id" } let!(:result) do nonprofit.stripe_account_id = stripe_acct_id - nonprofit.slug = 'slug' + nonprofit.slug = "slug" nonprofit.save! nonprofit.reload StripeAccount.find_or_create(nonprofit.id) end - it 'returns the expected id' do + it "returns the expected id" do expect(result).to eq stripe_acct_id end end end - describe '.create' do - it 'param validation' do + describe ".create" do + it "param validation" do expect { StripeAccount.create(nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :np, name: :required }, - { key: :np, name: :is_a }]) + expect_validation_errors(error.data, [{key: :np, name: :required}, + {key: :np, name: :is_a}]) end) end end - describe 'testing with valid nonprofit' do - it 'handles Stripe errors properly' do + describe "testing with valid nonprofit" do + it "handles Stripe errors properly" do StripeMockHelper.prepare_error(Stripe::StripeError.new, :new_account) expect { StripeAccount.create(nonprofit) }.to(raise_error do |error| expect(error).to be_a Stripe::StripeError @@ -96,64 +97,64 @@ end) end - describe 'saves properly without org email' do + describe "saves properly without org email" do let!(:result) { StripeAccount.create(nonprofit) } - it 'returns a Stripe acct id' do + it "returns a Stripe acct id" do expect(result).to_not be_blank end - it 'sets the Account values on Stripe' do + it "sets the Account values on Stripe" do saved_account = Stripe::Account.retrieve(result) - expect(saved_account['managed']).to eq true - expect(saved_account['business_name']).to eq nonprofit.name - expect(saved_account['email']).to eq nonprofit.email - expect(saved_account['business_url']).to eq nonprofit.website - expect(saved_account['legal_entity']['type']).to eq 'company' - expect(saved_account['legal_entity']['address']['city']).to eq nonprofit.city - expect(saved_account['legal_entity']['address']['state']).to eq nonprofit.state_code - expect(saved_account['legal_entity']['business_name']).to eq nonprofit.name - expect(saved_account['product_description']).to eq 'Nonprofit donations' - expect(saved_account['transfer_schedule']['interval']).to eq('manual') + expect(saved_account["managed"]).to eq true + expect(saved_account["business_name"]).to eq nonprofit.name + expect(saved_account["email"]).to eq nonprofit.email + expect(saved_account["business_url"]).to eq nonprofit.website + expect(saved_account["legal_entity"]["type"]).to eq "company" + expect(saved_account["legal_entity"]["address"]["city"]).to eq nonprofit.city + expect(saved_account["legal_entity"]["address"]["state"]).to eq nonprofit.state_code + expect(saved_account["legal_entity"]["business_name"]).to eq nonprofit.name + expect(saved_account["product_description"]).to eq "Nonprofit donations" + expect(saved_account["transfer_schedule"]["interval"]).to eq("manual") end - it 'updates the nonprofit itself' do + it "updates the nonprofit itself" do np = Nonprofit.find(nonprofit.id) expect(np.stripe_account_id).to eq result end end - describe 'saves properly without org email' do - before(:each) do + describe "saves properly without org email" do + before do nonprofit.email = nil nonprofit.save! role end - let(:admin_role_email) { 'email_user@email.email' } + let(:admin_role_email) { "email_user@email.email" } let(:user) { force_create(:user, email: admin_role_email) } let(:role) { force_create(:role, user: user, host: nonprofit, name: :nonprofit_admin) } let(:result) { StripeAccount.create(nonprofit) } - it 'returns a Stripe acct id' do + it "returns a Stripe acct id" do expect(result).to_not be_blank end - it 'sets the Account values on Stripe' do + it "sets the Account values on Stripe" do saved_account = Stripe::Account.retrieve(result) - expect(saved_account['managed']).to eq true - expect(saved_account['business_name']).to eq nonprofit.name - expect(saved_account['email']).to eq admin_role_email - expect(saved_account['business_url']).to eq nonprofit.website - expect(saved_account['legal_entity']['type']).to eq 'company' - expect(saved_account['legal_entity']['address']['city']).to eq nonprofit.city - expect(saved_account['legal_entity']['address']['state']).to eq nonprofit.state_code - expect(saved_account['legal_entity']['business_name']).to eq nonprofit.name - expect(saved_account['product_description']).to eq 'Nonprofit donations' - expect(saved_account['transfer_schedule']['interval']).to eq('manual') + expect(saved_account["managed"]).to eq true + expect(saved_account["business_name"]).to eq nonprofit.name + expect(saved_account["email"]).to eq admin_role_email + expect(saved_account["business_url"]).to eq nonprofit.website + expect(saved_account["legal_entity"]["type"]).to eq "company" + expect(saved_account["legal_entity"]["address"]["city"]).to eq nonprofit.city + expect(saved_account["legal_entity"]["address"]["state"]).to eq nonprofit.state_code + expect(saved_account["legal_entity"]["business_name"]).to eq nonprofit.name + expect(saved_account["product_description"]).to eq "Nonprofit donations" + expect(saved_account["transfer_schedule"]["interval"]).to eq("manual") end - it 'updates the nonprofit itself' do + it "updates the nonprofit itself" do result np = Nonprofit.find(nonprofit.id) expect(np.stripe_account_id).to eq result diff --git a/spec/legacy_lib/stripe_utils_spec.rb b/spec/legacy_lib/stripe_utils_spec.rb index cf705d1767..31372e9e38 100644 --- a/spec/legacy_lib/stripe_utils_spec.rb +++ b/spec/legacy_lib/stripe_utils_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe StripeUtils, pending: true do # describe '.get_verification_status' do diff --git a/spec/legacy_lib/timespan_spec.rb b/spec/legacy_lib/timespan_spec.rb index 9b0e14c12c..f031de153a 100644 --- a/spec/legacy_lib/timespan_spec.rb +++ b/spec/legacy_lib/timespan_spec.rb @@ -3,70 +3,69 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'chronic' -require 'timecop' -require_relative '../../app/legacy_lib/timespan' - +require "chronic" +require "timecop" +require_relative "../../app/legacy_lib/timespan" describe Timespan do - describe '#later_than_by?' do - let(:month) { Timespan.create(1, 'month') } - let(:week) { Timespan.create(1, 'month') } - let(:year) { Timespan.create(1, 'month') } - let(:day) { Timespan.create(1, 'month') } + describe "#later_than_by?" do + let(:month) { Timespan.create(1, "month") } + let(:week) { Timespan.create(1, "month") } + let(:year) { Timespan.create(1, "month") } + let(:day) { Timespan.create(1, "month") } - let(:date) { Chronic.parse('2019-01-15') } - let(:month_later) { Chronic.parse('2019-02-15') } + let(:date) { Chronic.parse("2019-01-15") } + let(:month_later) { Chronic.parse("2019-02-15") } - context 'when second date is later than the first by the timespan,' do - it 'returns true' do + context "when second date is later than the first by the timespan," do + it "returns true" do expect(Timespan.later_than_by?(date, month_later, month)).to eq(true) end end - context 'when the second date is sooner than the first by the timespan,' do - it 'returns false' do - sooner = Chronic.parse('2019-01-25') + context "when the second date is sooner than the first by the timespan," do + it "returns false" do + sooner = Chronic.parse("2019-01-25") expect(Timespan.later_than_by?(date, sooner, month)).to eq(false) end - context 'but when the first date is at the end of a long month and the second date is at the end of a shorter month,' do - let(:jan_31) { Chronic.parse('2019-01-31').to_date } - let(:feb_28) { Chronic.parse('2019-02-28').to_date } + context "but when the first date is at the end of a long month and the second date is at the end of a shorter month," do + let(:jan_31) { Chronic.parse("2019-01-31").to_date } + let(:feb_28) { Chronic.parse("2019-02-28").to_date } - it 'returns true' do + it "returns true" do expect(Timespan.later_than_by?(jan_31, feb_28, month)).to eq(true) end end end end - describe '#create' do - it 'returns the correct number of seconds constituting a timespan' do + describe "#create" do + it "returns the correct number of seconds constituting a timespan" do Timecop.freeze(2018, 3, 25) do - expect(Timespan.create(1, 'month').to_i).to eq(2_629_746) + expect(Timespan.create(1, "month").to_i).to eq(2_629_746) end end - it 'raises err when given an invalid time unit' do - expect { Timespan.create(1, 'blerg') }.to raise_error(ArgumentError) + it "raises err when given an invalid time unit" do + expect { Timespan.create(1, "blerg") }.to raise_error(ArgumentError) end end - describe '#in_future?' do - it 'returns true when date is in the future' do + describe "#in_future?" do + it "returns true when date is in the future" do expect(Timespan.in_future?(3.days.from_now)).to be(true) end - it 'returns false when date is in the past' do + it "returns false when date is in the past" do expect(Timespan.in_future?(3.days.ago)).to be(false) end end - describe '#in_past?' do - it 'returns true when date is in the past' do + describe "#in_past?" do + it "returns true when date is in the past" do expect(Timespan.in_past?(3.days.ago)).to be(true) end - it 'returns false when date is in the future' do + it "returns false when date is in the future" do expect(Timespan.in_past?(3.days.from_now)).to be(false) end end diff --git a/spec/legacy_lib/update/update_charges_spec.rb b/spec/legacy_lib/update/update_charges_spec.rb index 36fe2ee691..714b4e9613 100644 --- a/spec/legacy_lib/update/update_charges_spec.rb +++ b/spec/legacy_lib/update/update_charges_spec.rb @@ -2,16 +2,16 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateCharges do - describe '.disburse_all_with_payments', pending: true do - it 'test' do + describe ".disburse_all_with_payments", pending: true do + it "test" do raise end end - describe '.reverse_disburse_all_with_payments' do + describe ".reverse_disburse_all_with_payments" do let(:payment_to_reverse) { force_create(:payment) } let(:payment_to_ignore) { force_create(:payment) } let(:payment_to_reverse_2) { force_create(:payment) } @@ -19,14 +19,15 @@ let(:payment_to_reverse_with_refund) { force_create(:payment) } let(:reverse_payment_for_refund) { force_create(:payment) } let!(:charges) do - [force_create(:charge, payment: payment_to_reverse, status: 'disbursed'), - force_create(:charge, payment: payment_to_reverse_2, status: 'disbursed'), - force_create(:charge, payment: payment_to_ignore, status: 'disbursed'), - force_create(:charge, payment: payment_to_reverse_with_refund, status: 'disbursed')] + [force_create(:charge, payment: payment_to_reverse, status: "disbursed"), + force_create(:charge, payment: payment_to_reverse_2, status: "disbursed"), + force_create(:charge, payment: payment_to_ignore, status: "disbursed"), + force_create(:charge, payment: payment_to_reverse_with_refund, status: "disbursed")] end let!(:refunds) { [force_create(:refund, charge: charges.last, payment: reverse_payment_for_refund, disbursed: true)] } - before(:each) do + + before do UpdateCharges.reverse_disburse_all_with_payments([payment_to_reverse.id, payment_to_reverse_2.id, payment_to_reverse_with_refund.id, reverse_payment_for_refund.id]) payment_to_reverse.reload @@ -35,14 +36,14 @@ payment_to_ignore.reload end - it 'reverses payments it should' do - expect(payment_to_reverse.charge.status).to eq 'available' - expect(payment_to_reverse_2.charge.status).to eq 'available' - expect(payment_to_reverse_with_refund.charge.status).to eq 'available' + it "reverses payments it should" do + expect(payment_to_reverse.charge.status).to eq "available" + expect(payment_to_reverse_2.charge.status).to eq "available" + expect(payment_to_reverse_with_refund.charge.status).to eq "available" end - it 'does not reverse other payments' do - expect(payment_to_ignore.charge.status).to eq 'disbursed' + it "does not reverse other payments" do + expect(payment_to_ignore.charge.status).to eq "disbursed" end end end diff --git a/spec/legacy_lib/update/update_disputes_spec.rb b/spec/legacy_lib/update/update_disputes_spec.rb index 73b06d0e3e..7cb36d5932 100644 --- a/spec/legacy_lib/update/update_disputes_spec.rb +++ b/spec/legacy_lib/update/update_disputes_spec.rb @@ -2,11 +2,11 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateDisputes do - describe '.disburse_all_with_payments', pending: true do - it 'test' do + describe ".disburse_all_with_payments", pending: true do + it "test" do raise end end diff --git a/spec/legacy_lib/update/update_donation_spec.rb b/spec/legacy_lib/update/update_donation_spec.rb index 615fb564a0..4a3e6c9955 100644 --- a/spec/legacy_lib/update/update_donation_spec.rb +++ b/spec/legacy_lib/update/update_donation_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateDonation do before do @@ -12,19 +12,20 @@ after do Timecop.return end + let(:np) { force_create(:nm_justice) } let(:supporter) { force_create(:supporter) } let(:donation) do force_create(:donation, nonprofit: np, - dedication: initial_dedication, - comment: initial_comment, - designation: initial_designation, - amount: initial_amount, - date: initial_date, - supporter: supporter) + dedication: initial_dedication, + comment: initial_comment, + designation: initial_designation, + amount: initial_amount, + date: initial_date, + supporter: supporter) end - let(:trx) { + let(:trx) { trx = force_create(:transaction, supporter: supporter, amount: initial_amount) trx.donations.create(amount: initial_amount, legacy_donation: donation) @@ -33,28 +34,28 @@ let(:payment) do force_create(:payment, nonprofit: np, donation: donation, - towards: initial_designation, - date: initial_date, - gross_amount: initial_amount, - fee_total: initial_fee, - net_amount: initial_amount - initial_fee, - supporter: supporter) + towards: initial_designation, + date: initial_date, + gross_amount: initial_amount, + fee_total: initial_fee, + net_amount: initial_amount - initial_fee, + supporter: supporter) end let(:offsite_payment) do force_create(:offsite_payment, payment: payment, nonprofit: np, donation: donation, - check_number: initial_check_number, - gross_amount: initial_amount, - date: initial_date, - supporter: supporter) + check_number: initial_check_number, + gross_amount: initial_amount, + date: initial_date, + supporter: supporter) end let(:payment2) do force_create(:payment, nonprofit: np, donation: donation, - towards: initial_designation, - date: payment2_date, - gross_amount: initial_amount, - fee_total: initial_fee, - net_amount: initial_amount - initial_fee) + towards: initial_designation, + date: payment2_date, + gross_amount: initial_amount, + fee_total: initial_fee, + net_amount: initial_amount - initial_fee) end let(:campaign) { force_create(:campaign) } let(:event) { force_create(:event) } @@ -62,54 +63,55 @@ let(:other_event) { force_create(:event, nonprofit: force_create(:fv_poverty)) } let(:initial_date) { Date.new(2020, 4, 5).to_time } - let(:initial_dedication) { 'initial dedication' } - let(:initial_comment) { 'comment' } + let(:initial_dedication) { "initial dedication" } + let(:initial_comment) { "comment" } let(:initial_amount) { 4000 } - let(:initial_designation) { 'designation' } + let(:initial_designation) { "designation" } let(:initial_fee) { 555 } - let(:initial_check_number) { 'htoajmioeth' } + let(:initial_check_number) { "htoajmioeth" } - let(:new_date_input) { '2020-05-05' } + let(:new_date_input) { "2020-05-05" } let(:new_date) { Date.new(2020, 5, 5) } - let(:new_dedication) { 'new dedication' } - let(:new_comment) { 'new comment' } + let(:new_dedication) { "new dedication" } + let(:new_comment) { "new comment" } let(:new_amount) { 5646 } - let(:new_designation) { 'new designation' } + let(:new_designation) { "new designation" } let(:new_fee) { 54 } - let(:new_check_number) { 'new check number' } + let(:new_check_number) { "new check number" } let(:initial_time) { Time.now } let(:payment2_date) { initial_date + 10.days } - before(:each) do + before do allow(Houdini.event_publisher).to receive(:announce) initial_time payment end - describe '.update_payment' do - describe 'param validation' do - it 'basic validation' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + + describe ".update_payment" do + describe "param validation" do + it "basic validation" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect { UpdateDonation.update_payment(nil, nil) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :id, name: :required }, - { key: :id, name: :is_reference }, - { key: :data, name: :required }, - { key: :data, name: :is_hash }]) + expect_validation_errors(error.data, [{key: :id, name: :required}, + {key: :id, name: :is_reference}, + {key: :data, name: :required}, + {key: :data, name: :is_hash}]) } end - it 'validates whether payment is valid' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + it "validates whether payment is valid" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect { UpdateDonation.update_payment(5555, {}) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :id }]) - expect(error.message).to eq '5555 is does not correspond to a valid donation' + expect_validation_errors(error.data, [{key: :id}]) + expect(error.message).to eq "5555 is does not correspond to a valid donation" } end - describe 'data validation' do + describe "data validation" do let(:initial_invalid_arguments) do { designation: 1, @@ -122,42 +124,43 @@ let(:expanded_invalid_arguments) do initial_invalid_arguments.merge( - fee_total: 'fun', - gross_amount: 'fun', + fee_total: "fun", + gross_amount: "fun", check_number: Time.now, - date: 'INVALID DATE' + date: "INVALID DATE" ) end let(:initial_validation_errors) do [ - { key: :designation, name: :is_a }, - { key: :dedication, name: :is_a }, - { key: :comment, name: :is_a }, - { key: :campaign_id, name: :is_reference }, - { key: :campaign_id, name: :required }, - { key: :event_id, name: :is_reference }, - { key: :event_id, name: :required } + {key: :designation, name: :is_a}, + {key: :dedication, name: :is_a}, + {key: :comment, name: :is_a}, + {key: :campaign_id, name: :is_reference}, + {key: :campaign_id, name: :required}, + {key: :event_id, name: :is_reference}, + {key: :event_id, name: :required} ] end - it 'for offsite donations' do + + it "for offsite donations" do offsite_payment - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect { UpdateDonation.update_payment(donation.id, expanded_invalid_arguments) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, initial_validation_errors.concat([ - { key: :fee_total, name: :is_integer }, - { key: :gross_amount, name: :is_integer }, - { key: :gross_amount, name: :min }, - { key: :check_number, name: :is_a }, - { key: :date, name: :can_be_date } - ])) + {key: :fee_total, name: :is_integer}, + {key: :gross_amount, name: :is_integer}, + {key: :gross_amount, name: :min}, + {key: :check_number, name: :is_a}, + {key: :date, name: :can_be_date} + ])) end) end - it 'for online donation' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + it "for online donation" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect { UpdateDonation.update_payment(donation.id, expanded_invalid_arguments) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, initial_validation_errors) @@ -165,50 +168,50 @@ end end - it 'validate campaign_id' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + it "validate campaign_id" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect { UpdateDonation.update_payment(donation.id, campaign_id: 444, event_id: 444) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :campaign_id }]) + expect_validation_errors(error.data, [{key: :campaign_id}]) end) end - it 'validate event_id' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + it "validate event_id" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect { UpdateDonation.update_payment(donation.id, event_id: 4444, campaign_id: campaign.id) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :event_id }]) + expect_validation_errors(error.data, [{key: :event_id}]) end) end - it 'validates campaign belongs to payment org' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + it "validates campaign belongs to payment org" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) campaign_belongs { UpdateDonation.update_payment(donation.id, campaign_id: other_campaign.id, event_id: event.id) } end - it 'validates event belongs to payment org' do - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + it "validates event belongs to payment org" do + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) event_belongs { UpdateDonation.update_payment(donation.id, event_id: other_event.id, campaign_id: campaign.id) } end end - describe 'most of the values arent changed if not provided' do - it 'online donation' do + describe "most of the values arent changed if not provided" do + it "online donation" do trx payment2 result = verify_nothing_changed - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) expect(result).to eq donation.attributes.merge(payment: payment2.attributes) trx.reload expect(trx.amount).to eq initial_amount expect(trx.donations.first.amount).to eq initial_amount end - it 'offsite donation' do + it "offsite donation" do trx offsite_payment result = verify_nothing_changed - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) p2_attributes = payment2.attributes payment2.reload expect(p2_attributes).to eq payment2.attributes @@ -223,8 +226,8 @@ end def verify_nothing_changed - expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated,anything) - result = UpdateDonation.update_payment(donation.id, campaign_id: '', event_id: '') + expect(Houdini.event_publisher).to_not receive(:announce).with(:donation_updated, anything) + result = UpdateDonation.update_payment(donation.id, campaign_id: "", event_id: "") p_attributes = payment.attributes payment.reload @@ -241,32 +244,33 @@ def verify_nothing_changed end end - describe 'test everything changed' do + describe "test everything changed" do let(:new_data) do - { designation: new_designation, - dedication: new_dedication, - comment: new_comment, - campaign_id: campaign.id, - event_id: event.id, - - gross_amount: new_amount, - fee_total: new_fee, - check_number: new_check_number, - date: new_date_input } + {designation: new_designation, + dedication: new_dedication, + comment: new_comment, + campaign_id: campaign.id, + event_id: event.id, + + gross_amount: new_amount, + fee_total: new_fee, + check_number: new_check_number, + date: new_date_input} end - it 'online donation' do + + it "online donation" do trx payment2 Timecop.freeze(1.day) do - expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated, anything) result = UpdateDonation.update_payment(donation.id, new_data) expected_donation = donation.attributes.merge(designation: new_designation, - dedication: new_dedication, - comment: new_comment, - campaign_id: campaign.id, - event_id: event.id, - updated_at: Time.now).with_indifferent_access + dedication: new_dedication, + comment: new_comment, + campaign_id: campaign.id, + event_id: event.id, + updated_at: Time.now).with_indifferent_access donation.reload expect(donation.attributes).to eq expected_donation @@ -288,11 +292,11 @@ def verify_nothing_changed end end - it 'offline donation' do + it "offline donation" do trx offsite_payment Timecop.freeze(1.day) do - expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated, anything) result = UpdateDonation.update_payment(donation.id, new_data) expected_donation = donation.attributes.merge( @@ -331,43 +335,43 @@ def verify_nothing_changed end end - describe 'test blank but existent data will rewrite' do + describe "test blank but existent data will rewrite" do let(:blank_data) do - { designation: '', - dedication: '', - comment: '', - campaign_id: '', - event_id: '', - - gross_amount: new_amount, - fee_total: new_fee, - check_number: '', - date: new_date_input } + {designation: "", + dedication: "", + comment: "", + campaign_id: "", + event_id: "", + + gross_amount: new_amount, + fee_total: new_fee, + check_number: "", + date: new_date_input} end - it 'online donation' do + it "online donation" do trx payment2 Timecop.freeze(1.day) do - expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated, anything) UpdateDonation.update_payment(donation.id, new_data) result = UpdateDonation.update_payment(donation.id, blank_data) - expected_donation = donation.attributes.merge(designation: '', - dedication: '', - comment: '', - campaign_id: nil, - event_id: nil, - updated_at: Time.now).with_indifferent_access + expected_donation = donation.attributes.merge(designation: "", + dedication: "", + comment: "", + campaign_id: nil, + event_id: nil, + updated_at: Time.now).with_indifferent_access donation.reload expect(donation.attributes).to eq expected_donation - expected_p1 = payment.attributes.merge(towards: '', updated_at: Time.now).with_indifferent_access + expected_p1 = payment.attributes.merge(towards: "", updated_at: Time.now).with_indifferent_access payment.reload expect(payment.attributes).to eq expected_p1 - expected_p2 = payment2.attributes.merge(towards: '', updated_at: Time.now).with_indifferent_access + expected_p2 = payment2.attributes.merge(towards: "", updated_at: Time.now).with_indifferent_access payment2.reload expect(payment2.attributes).to eq expected_p2 @@ -380,11 +384,11 @@ def verify_nothing_changed end end - it 'offline donation' do + it "offline donation" do trx offsite_payment Timecop.freeze(1.day) do - expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated,anything) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_updated, anything) UpdateDonation.update_payment(donation.id, new_data) result = UpdateDonation.update_payment(donation.id, blank_data) @@ -392,9 +396,9 @@ def verify_nothing_changed date: new_date.in_time_zone, amount: new_amount, - designation: '', - dedication: '', - comment: '', + designation: "", + dedication: "", + comment: "", campaign_id: nil, event_id: nil, @@ -404,13 +408,13 @@ def verify_nothing_changed donation.reload expect(donation.attributes).to eq expected_donation - expected_p1 = payment.attributes.merge(towards: '', updated_at: Time.now, date: new_date.in_time_zone, gross_amount: new_amount, fee_total: new_fee, net_amount: new_amount - new_fee).with_indifferent_access + expected_p1 = payment.attributes.merge(towards: "", updated_at: Time.now, date: new_date.in_time_zone, gross_amount: new_amount, fee_total: new_fee, net_amount: new_amount - new_fee).with_indifferent_access payment.reload expect(payment.attributes).to eq expected_p1 expect(Payment.count).to eq 1 - expected_offsite_payment = offsite_payment.attributes.merge(check_number: '', date: new_date.in_time_zone, gross_amount: new_amount, updated_at: Time.now).with_indifferent_access + expected_offsite_payment = offsite_payment.attributes.merge(check_number: "", date: new_date.in_time_zone, gross_amount: new_amount, updated_at: Time.now).with_indifferent_access offsite_payment.reload expect(offsite_payment.attributes).to eq expected_offsite_payment @@ -425,16 +429,16 @@ def verify_nothing_changed def event_belongs expect { yield }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :event_id }]) - expect(error.message).to include 'event does not belong to this nonprofit' + expect_validation_errors(error.data, [{key: :event_id}]) + expect(error.message).to include "event does not belong to this nonprofit" end) end def campaign_belongs expect { yield }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :campaign_id }]) - expect(error.message).to include 'campaign does not belong to this nonprofit' + expect_validation_errors(error.data, [{key: :campaign_id}]) + expect(error.message).to include "campaign does not belong to this nonprofit" end) end diff --git a/spec/legacy_lib/update/update_misc_nonprofit_settings_spec.rb b/spec/legacy_lib/update/update_misc_nonprofit_settings_spec.rb index 804d632c21..d13daa87cb 100644 --- a/spec/legacy_lib/update/update_misc_nonprofit_settings_spec.rb +++ b/spec/legacy_lib/update/update_misc_nonprofit_settings_spec.rb @@ -2,57 +2,58 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateMiscellaneousNpInfo do - describe '#update' do - describe 'validates parameters' do - it 'does basic validation' do - expect { UpdateMiscellaneousNpInfo.update(nil, nil) }.to (raise_error do |error| + describe "#update" do + describe "validates parameters" do + it "does basic validation" do + expect { UpdateMiscellaneousNpInfo.update(nil, nil) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :np_id, name: :required }, - { key: :np_id, name: :is_integer }, - { key: :misc_settings, name: :required }, - { key: :misc_settings, name: :is_hash }]) + expect_validation_errors(error.data, [{key: :np_id, name: :required}, + {key: :np_id, name: :is_integer}, + {key: :misc_settings, name: :required}, + {key: :misc_settings, name: :is_hash}]) end) end - it 'does np validation' do - expect { UpdateMiscellaneousNpInfo.update(50, {}) }.to (raise_error do |error| + it "does np validation" do + expect { UpdateMiscellaneousNpInfo.update(50, {}) }.to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :np_id }]) + expect_validation_errors(error.data, [{key: :np_id}]) end) end end - describe 'main' do + describe "main" do let!(:np) { force_create(:nm_justice) } - let (:working_message) { '

working message

' } - it 'sets change_amount_message to nil if empty tags' do + let(:working_message) { "

working message

" } + + it "sets change_amount_message to nil if empty tags" do expect(MiscellaneousNpInfo.count).to eq 0 - update_result = UpdateMiscellaneousNpInfo.update(np.id, donate_again_url: 'url', not_an_attribute: 3, change_amount_message: '


') - expect(update_result).to have_attributes donate_again_url: 'url', nonprofit: np, change_amount_message: nil + update_result = UpdateMiscellaneousNpInfo.update(np.id, donate_again_url: "url", not_an_attribute: 3, change_amount_message: "


") + expect(update_result).to have_attributes donate_again_url: "url", nonprofit: np, change_amount_message: nil expect(MiscellaneousNpInfo.count).to eq 1 expect(update_result).to eq MiscellaneousNpInfo.first! end - it 'add misc if it doesnt exist' do + it "add misc if it doesnt exist" do expect(MiscellaneousNpInfo.count).to eq 0 - update_result = UpdateMiscellaneousNpInfo.update(np.id, donate_again_url: 'url', not_an_attribute: 3, change_amount_message: working_message) - expect(update_result).to have_attributes donate_again_url: 'url', nonprofit: np, change_amount_message: working_message + update_result = UpdateMiscellaneousNpInfo.update(np.id, donate_again_url: "url", not_an_attribute: 3, change_amount_message: working_message) + expect(update_result).to have_attributes donate_again_url: "url", nonprofit: np, change_amount_message: working_message expect(MiscellaneousNpInfo.count).to eq 1 expect(update_result).to eq MiscellaneousNpInfo.first! end - it 'update misc if already there' do + it "update misc if already there" do Timecop.freeze(2020, 0o1, 0o5) do - old_misc = create(:miscellaneous_np_info, nonprofit: np, donate_again_url: 'old_url') + old_misc = create(:miscellaneous_np_info, nonprofit: np, donate_again_url: "old_url") expect(MiscellaneousNpInfo.count).to eq 1 Timecop.freeze(10) do - update_result = UpdateMiscellaneousNpInfo.update(np.id, donate_again_url: 'url', not_an_attribute: 3, change_amount_message: working_message) - expect(update_result).to have_attributes donate_again_url: 'url', nonprofit: np, change_amount_message: working_message + update_result = UpdateMiscellaneousNpInfo.update(np.id, donate_again_url: "url", not_an_attribute: 3, change_amount_message: working_message) + expect(update_result).to have_attributes donate_again_url: "url", nonprofit: np, change_amount_message: working_message expect(MiscellaneousNpInfo.count).to eq 1 expect(update_result).to eq MiscellaneousNpInfo.first! diff --git a/spec/legacy_lib/update/update_payouts_spec.rb b/spec/legacy_lib/update/update_payouts_spec.rb index 2b4dc067a1..fc5309715d 100644 --- a/spec/legacy_lib/update/update_payouts_spec.rb +++ b/spec/legacy_lib/update/update_payouts_spec.rb @@ -2,39 +2,39 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdatePayouts do - describe '.reverse_with_stripe' do - describe 'param validation' do - it 'basic param_validation' do + describe ".reverse_with_stripe" do + describe "param validation" do + it "basic param_validation" do expect { UpdatePayouts.reverse_with_stripe(nil, nil, nil) }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error.data, [{ key: :payout_id, name: :required }, - { key: :payout_id, name: :is_integer }, - { key: :status, name: :required }, - { key: :status, name: :included_in }, - { key: :failure_message, name: :required }, - { key: :failure_message, name: :not_blank }]) + expect_validation_errors(error.data, [{key: :payout_id, name: :required}, + {key: :payout_id, name: :is_integer}, + {key: :status, name: :required}, + {key: :status, name: :included_in}, + {key: :failure_message, name: :required}, + {key: :failure_message, name: :not_blank}]) end) end - it 'reject non-existent payouts' do - expect { UpdatePayouts.reverse_with_stripe(5_555_555, 'failed', 'failure') }.to(raise_error do |error| + it "reject non-existent payouts" do + expect { UpdatePayouts.reverse_with_stripe(5_555_555, "failed", "failure") }.to(raise_error do |error| expect(error).to be_a(ParamValidation::ValidationError) - expect_validation_errors(error.data, [{ key: :payout_id }]) + expect_validation_errors(error.data, [{key: :payout_id}]) end) end - it 'reject payouts with no payments' do + it "reject payouts with no payments" do payout = force_create(:payout) - expect { UpdatePayouts.reverse_with_stripe(payout.id, 'failed', 'failure') }.to(raise_error do |error| + expect { UpdatePayouts.reverse_with_stripe(payout.id, "failed", "failure") }.to(raise_error do |error| expect(error).to be_a(ArgumentError) end) end end - describe 'validate proper function' do + describe "validate proper function" do let(:payment_to_reverse) { force_create(:payment) } let(:payment_to_ignore) { force_create(:payment) } let(:payment_to_reverse_2) { force_create(:payment) } @@ -42,10 +42,10 @@ let(:reverse_payment_for_refund) { force_create(:payment) } let!(:charges) do - [force_create(:charge, payment: payment_to_reverse, status: 'disbursed'), - force_create(:charge, payment: payment_to_reverse_2, status: 'disbursed'), - force_create(:charge, payment: payment_to_ignore, status: 'disbursed'), - force_create(:charge, payment: payment_to_reverse_with_refund, status: 'disbursed')] + [force_create(:charge, payment: payment_to_reverse, status: "disbursed"), + force_create(:charge, payment: payment_to_reverse_2, status: "disbursed"), + force_create(:charge, payment: payment_to_ignore, status: "disbursed"), + force_create(:charge, payment: payment_to_reverse_with_refund, status: "disbursed")] end let!(:refunds) { [force_create(:refund, charge: charges.last, payment: reverse_payment_for_refund, disbursed: true)] } @@ -53,15 +53,15 @@ let(:np) { force_create(:nm_justice) } let!(:bank_account) { force_create(:bank_account, nonprofit: np) } let!(:payout) do - force_create(:payout, status: 'paid', failure_message: 'all good', - nonprofit: np, stripe_transfer_id: 'transfer_id', email: 'no one cares', net_amount: 500) + force_create(:payout, status: "paid", failure_message: "all good", + nonprofit: np, stripe_transfer_id: "transfer_id", email: "no one cares", net_amount: 500) end - let(:bad_status) { 'failed' } - let(:bad_failure_message) { 'so terrible' } - let(:available) { 'available' } + let(:bad_status) { "failed" } + let(:bad_failure_message) { "so terrible" } + let(:available) { "available" } - before(:each) do + before do payout.payments.push(payment_to_reverse) payout.payments.push(payment_to_reverse_2) payout.payments.push(payment_to_reverse_with_refund) @@ -74,27 +74,27 @@ payment_to_ignore.reload end - it 'reverses proper payments' do + it "reverses proper payments" do expect(payment_to_reverse.charge.status).to eq available expect(payment_to_reverse_2.charge.status).to eq available expect(payment_to_reverse_with_refund.charge.status).to eq available end - it 'reverses proper refunds' do + it "reverses proper refunds" do refund = refunds.first refund.reload expect(refund.disbursed).to eq false end - it 'reverses disputes', pending: 'disputes aren\'t properly modeled to safely do this' do + it "reverses disputes", pending: "disputes aren't properly modeled to safely do this" do raise end - it 'ignores irrelevant payments' do - expect(payment_to_ignore.charge.status).to eq 'disbursed' + it "ignores irrelevant payments" do + expect(payment_to_ignore.charge.status).to eq "disbursed" end - it 'changes payout status and failure' do + it "changes payout status and failure" do payout.reload expect(payout.status).to eq bad_status expect(payout.failure_message).to eq bad_failure_message diff --git a/spec/legacy_lib/update/update_recurring_donations_spec.rb b/spec/legacy_lib/update/update_recurring_donations_spec.rb index 95a245b025..93cf7fe4c5 100644 --- a/spec/legacy_lib/update/update_recurring_donations_spec.rb +++ b/spec/legacy_lib/update/update_recurring_donations_spec.rb @@ -2,108 +2,107 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateRecurringDonations do # deactivate a recurring donation - describe '.cancel' do - + describe ".cancel" do let!(:np) { force_create(:nm_justice) } let(:s) { force_create(:supporter, nonprofit: np) } let(:donation) { force_create(:donation, nonprofit_id: np.id, supporter_id: s.id) } - let(:email) { 'test@test.com' } + let(:email) { "test@test.com" } let!(:rd) do inner_rd = force_create(:recurring_donation, amount: 999, active: true, supporter_id: s.id, donation_id: donation.id, nonprofit_id: np.id) UpdateRecurringDonations.cancel(inner_rd.id, email) end - it 'sets active to false' do - expect(rd['active']).to eq false + it "sets active to false" do + expect(rd["active"]).to eq false end - it 'sets cancelled_at to today' do - expect(rd['cancelled_at'].to_date.end_of_day).to eq(Time.now.end_of_day) + it "sets cancelled_at to today" do + expect(rd["cancelled_at"].to_date.end_of_day).to eq(Time.now.end_of_day) end - it 'sets the cancelled_by to the given email' do - expect(rd['cancelled_by']).to eq email + it "sets the cancelled_by to the given email" do + expect(rd["cancelled_by"]).to eq email end - it 'returns the full fetch_for_edit data' do - expect(rd['nonprofit_name']).to eq np.name + it "returns the full fetch_for_edit data" do + expect(rd["nonprofit_name"]).to eq np.name end - it 'creates a supporter note table describing the cancellation' do - note = Qx.select(:content).from(:supporter_notes).limit(1).order_by('id DESC').execute.first - expect(note['content']).to include('cancelled') + it "creates a supporter note table describing the cancellation" do + note = Qx.select(:content).from(:supporter_notes).limit(1).order_by("id DESC").execute.first + expect(note["content"]).to include("cancelled") end end - describe '.update_amount' do + describe ".update_amount" do include_context :shared_rd_donation_value_context - describe 'param validation' do - it 'rejects totally invalid data' do + let(:common_builder_expanded) do + { + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded + } + end + let(:supporter_builder_expanded) do + supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + end + let(:np_builder_expanded) do + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } + end + + describe "param validation" do + it "rejects totally invalid data" do expect { UpdateRecurringDonations.update_amount(nil, nil, nil) } .to(raise_error do |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error, [{ key: 'rd', name: :required }, - { key: 'rd', name: :is_a }, - { key: :token, name: :required }, - { key: :token, name: :format }, - { key: 'amount', name: :required }, - { key: 'amount', name: :is_integer }, - { key: 'amount', name: :min }]) + expect_validation_errors(error, [{key: "rd", name: :required}, + {key: "rd", name: :is_a}, + {key: :token, name: :required}, + {key: :token, name: :format}, + {key: "amount", name: :required}, + {key: "amount", name: :is_integer}, + {key: "amount", name: :min}]) end) end end - describe 'token validation' do - it 'invalid token errors' do + + describe "token validation" do + it "invalid token errors" do validation_invalid_token { UpdateRecurringDonations.update_amount(recurring_donation, fake_uuid, 500) } end - it 'unauthorized token errors' do + it "unauthorized token errors" do validation_unauthorized { UpdateRecurringDonations.update_amount(recurring_donation, fake_uuid, 500) } end - it 'validation expired errors' do + it "validation expired errors" do validation_expired { UpdateRecurringDonations.update_amount(recurring_donation, fake_uuid, 500) } end end - describe 'validate entities' do - it 'errors when rd is cancelled' do + describe "validate entities" do + it "errors when rd is cancelled" do error_when_rd_cancelled { UpdateRecurringDonations.update_amount(recurring_donation, source_token.id, 500) } end - it 'errors when card is deleted' do + it "errors when card is deleted" do error_when_card_deleted { UpdateRecurringDonations.update_amount(recurring_donation, source_token.id, 500) } end - it 'errors when card holder and supporter arent the same' do + it "errors when card holder and supporter arent the same" do errors_when_card_holder_and_supporter_neq { UpdateRecurringDonations.update_amount(recurring_donation, other_source_token.id, 500) } end end - let(:np_builder_expanded) do - { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - } - end - - let(:supporter_builder_expanded) do - supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - end - - let(:common_builder_expanded) do - { - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded - } - end - it 'changes amount properly' do + it "changes amount properly" do recurring_donation.n_failures = 2 recurring_donation.save! recurrence @@ -112,46 +111,48 @@ orig_rd = recurring_donation.attributes.with_indifferent_access orig_donation = recurring_donation.donation.attributes.with_indifferent_access expect(Houdini.event_publisher).to receive(:announce).with(:recurrence_updated, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'recurrence.updated', - 'data' => { - 'object' => common_builder_expanded.merge({ - 'object' => 'recurrence', - 'id' => orig_recurrence.id, - 'start_date' => orig_recurrence.start_date.to_i, - 'recurrences' => [ - { - 'start' => orig_recurrence.start_date.beginning_of_day.to_i, - 'interval' => 1, - 'type' => 'monthly' - }], - 'invoice_template' => { - 'supporter' => supporter.id, - 'amount' => {'cents' => 1000, 'currency' => 'usd'}, - 'payment_method' => {'type' => 'stripe'}, - 'trx_assignments' => [ - { - 'assignment_object' => 'donation', - 'designation' => nil, - 'amount' => {'cents' => 1000, 'currency' => 'usd'} - }] + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "recurrence.updated", + "data" => { + "object" => common_builder_expanded.merge({ + "object" => "recurrence", + "id" => orig_recurrence.id, + "start_date" => orig_recurrence.start_date.to_i, + "recurrences" => [ + { + "start" => orig_recurrence.start_date.beginning_of_day.to_i, + "interval" => 1, + "type" => "monthly" + } + ], + "invoice_template" => { + "supporter" => supporter.id, + "amount" => {"cents" => 1000, "currency" => "usd"}, + "payment_method" => {"type" => "stripe"}, + "trx_assignments" => [ + { + "assignment_object" => "donation", + "designation" => nil, + "amount" => {"cents" => 1000, "currency" => "usd"} + } + ] + } + }) } }) - }}) result = nil expect { - result = UpdateRecurringDonations.update_amount(recurring_donation, - source_token.token, 1000) - }.to have_enqueued_job(RecurringDonationChangeAmountJob).with(recurring_donation, orig_rd['amount']) + result = UpdateRecurringDonations.update_amount(recurring_donation, + source_token.token, 1000) + }.to have_enqueued_job(RecurringDonationChangeAmountJob).with(recurring_donation, orig_rd["amount"]) expectations = { donation: orig_donation.merge(amount: 1000, card_id: source_token.tokenizable.id), recurring_donation: orig_rd.merge(amount: 1000, n_failures: 0, start_date: Time.current.to_date) } - expect(result.attributes).to eq expectations[:recurring_donation] recurring_donation.reload @@ -162,61 +163,61 @@ end end - describe '.update_card_id' do + describe ".update_card_id" do include_context :shared_rd_donation_value_context - describe 'basic validation' do - it 'basic param validation' do + describe "basic validation" do + it "basic param validation" do expect { UpdateRecurringDonations.update_card_id(nil, nil) }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError expect_validation_errors(e.data, [ - { key: :rd, name: :is_hash }, - { key: :rd, name: :required }, - { key: :token, name: :required }, - { key: :token, name: :format } - ]) + {key: :rd, name: :is_hash}, + {key: :rd, name: :required}, + {key: :token, name: :required}, + {key: :token, name: :format} + ]) } end - it 'rd[:id] validation' do + it "rd[:id] validation" do expect { UpdateRecurringDonations.update_card_id({}, fake_uuid) }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError expect_validation_errors(e.data, [ - { key: :id, name: :is_reference }, - { key: :id, name: :required } - ]) + {key: :id, name: :is_reference}, + {key: :id, name: :required} + ]) } end end - describe 'token validation' do - it 'invalid token errors' do - validation_invalid_token { UpdateRecurringDonations.update_card_id({ id: 555 }, fake_uuid) } + describe "token validation" do + it "invalid token errors" do + validation_invalid_token { UpdateRecurringDonations.update_card_id({id: 555}, fake_uuid) } end - it 'unauthorized token errors' do - validation_unauthorized { UpdateRecurringDonations.update_card_id({ id: 555 }, fake_uuid) } + it "unauthorized token errors" do + validation_unauthorized { UpdateRecurringDonations.update_card_id({id: 555}, fake_uuid) } end - it 'validation expired errors' do - validation_expired { UpdateRecurringDonations.update_card_id({ id: 555 }, fake_uuid) } + it "validation expired errors" do + validation_expired { UpdateRecurringDonations.update_card_id({id: 555}, fake_uuid) } end end - describe 'entity retrieval errors' do - it 'find error on recurring donation' do - find_error_recurring_donation { UpdateRecurringDonations.update_card_id({ id: 55_555 }, source_token.token) } + describe "entity retrieval errors" do + it "find error on recurring donation" do + find_error_recurring_donation { UpdateRecurringDonations.update_card_id({id: 55_555}, source_token.token) } end end - it 'finishes properly' do - expect(InsertSupporterNotes).to receive(:create).with([{ content: "This supporter updated their card for their recurring donation with ID #{recurring_donation.id}", supporter_id: supporter.id, user_id: 540 }]) + it "finishes properly" do + expect(InsertSupporterNotes).to receive(:create).with([{content: "This supporter updated their card for their recurring donation with ID #{recurring_donation.id}", supporter_id: supporter.id, user_id: 540}]) recurring_donation.n_failures = 2 recurring_donation.save! orig_rd = recurring_donation.attributes.with_indifferent_access orig_donation = recurring_donation.donation.attributes.with_indifferent_access - result = UpdateRecurringDonations.update_card_id({ id: recurring_donation.id }, source_token.token) + result = UpdateRecurringDonations.update_card_id({id: recurring_donation.id}, source_token.token) expectations = { donation: orig_donation.merge(card_id: card.id), @@ -227,12 +228,12 @@ expectations[:result][:start_date] = expectations[:result]["start_date"].to_date.strftime("%Y-%m-%d") expectations[:result][:created_at] = expectations[:result]["created_at"].to_date expectations[:result][:updated_at] = expectations[:result]["updated_at"].to_date - + expect(result).to match expectations[:result] - + donation_for_rd.reload recurring_donation.reload - + expect(recurring_donation.attributes).to eq expectations[:recurring_donation] expect(donation_for_rd.attributes).to eq expectations[:donation] end @@ -241,7 +242,7 @@ def find_error_recurring_donation expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :id }]) + expect_validation_errors(e.data, [{key: :id}]) } end @@ -251,7 +252,7 @@ def error_when_rd_cancelled expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :id }]) + expect_validation_errors(e.data, [{key: :id}]) expect(e.message).to eq "Recurring Donation #{recurring_donation.id} is already cancelled." } end @@ -262,7 +263,7 @@ def error_when_card_deleted expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :token }]) + expect_validation_errors(e.data, [{key: :token}]) expect(e.message).to eq "Tokenized card #{card.id} is not valid." } end @@ -270,7 +271,7 @@ def error_when_card_deleted def errors_when_card_holder_and_supporter_neq expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :token }]) + expect_validation_errors(e.data, [{key: :token}]) expect(e.message).to eq "Supporter #{supporter.id} does not own card #{other_source_token.tokenizable.id}" } end diff --git a/spec/legacy_lib/update/update_refunds_spec.rb b/spec/legacy_lib/update/update_refunds_spec.rb index df31c101f7..e5be66e1fc 100644 --- a/spec/legacy_lib/update/update_refunds_spec.rb +++ b/spec/legacy_lib/update/update_refunds_spec.rb @@ -2,16 +2,16 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateRefunds do - describe '.disburse_all_with_payments', pending: true do - it 'test' do + describe ".disburse_all_with_payments", pending: true do + it "test" do raise end end - describe '.reverse_disburse_all_with_payments' do + describe ".reverse_disburse_all_with_payments" do let(:payment_to_reverse) { force_create(:payment) } let(:payment_to_ignore) { force_create(:payment) } let!(:refunds) do @@ -20,17 +20,18 @@ force_create(:refund, payment: payment_to_ignore, disbursed: true) ] end - before(:each) do + + before do UpdateRefunds.reverse_disburse_all_with_payments([payment_to_reverse.id]) refunds.each(&:reload) end - it 'reverses refunds as it should' do + it "reverses refunds as it should" do expect(refunds.first.disbursed).to eq false end - it 'doesn\'t reverse unselected refund' do + it "doesn't reverse unselected refund" do expect(refunds.last.disbursed).to eq true end end diff --git a/spec/legacy_lib/update/update_supporter_spec.rb b/spec/legacy_lib/update/update_supporter_spec.rb index 646f0f585f..3d3dae3000 100644 --- a/spec/legacy_lib/update/update_supporter_spec.rb +++ b/spec/legacy_lib/update/update_supporter_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateSupporter, pending: true do end diff --git a/spec/legacy_lib/update/update_tickets_spec.rb b/spec/legacy_lib/update/update_tickets_spec.rb index 8f176e8d44..1d63b2d2f6 100644 --- a/spec/legacy_lib/update/update_tickets_spec.rb +++ b/spec/legacy_lib/update/update_tickets_spec.rb @@ -2,21 +2,19 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe UpdateTickets do let(:ticket) do create(:ticket, :has_card, :has_event) end - - - describe '.update' do + describe ".update" do include_context :shared_rd_donation_value_context - let(:trx) {create(:transaction, supporter: supporter)} - + let(:trx) { create(:transaction, supporter: supporter) } + let(:basic_valid_ticket_input) do - { ticket_id: ticket.id, event_id: event.id } + {ticket_id: ticket.id, event_id: event.id} end let(:include_fake_token) do basic_valid_ticket_input.merge(token: fake_uuid) @@ -68,16 +66,15 @@ }.with_indifferent_access end - let(:payment) { force_create(:payment) } let(:charge) { force_create(:charge) } let(:ticket) do tp = trx.ticket_purchases.create(event: event) - + ticket = force_create(:ticket, - general_ticket.merge(event: event)) - ticket.quantity.times do + general_ticket.merge(event: event)) + ticket.quantity.times do ticket.ticket_to_legacy_tickets.create(ticket_purchase: tp) end ticket @@ -85,109 +82,109 @@ let(:other_ticket) do ticket = force_create(:ticket, - general_ticket.merge(event: other_event)) - ticket.quantity.times do + general_ticket.merge(event: other_event)) + ticket.quantity.times do ticket.ticket_to_legacy_tickets.create end - ticket + ticket end def expect_ticket_updated_to_not_be_called expect(Houdini.event_publisher).to_not receive(:announce).with(:ticket_updated, any_args) end - it 'basic validation' do + it "basic validation" do expect_ticket_updated_to_not_be_called - expect { UpdateTickets.update(token: 'bhaetiwhet', checked_in: 'blah', bid_id: 'bhalehti') }.to raise_error { |error| + expect { UpdateTickets.update(token: "bhaetiwhet", checked_in: "blah", bid_id: "bhalehti") }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError expect_validation_errors(error.data, [ - { key: :event_id, name: :required }, - { key: :event_id, name: :is_reference }, - { key: :ticket_id, name: :required }, - { key: :ticket_id, name: :is_reference }, - { key: :token, name: :format }, - { key: :bid_id, name: :is_integer }, - { key: :checked_in, name: :included_in } - ]) + {key: :event_id, name: :required}, + {key: :event_id, name: :is_reference}, + {key: :ticket_id, name: :required}, + {key: :ticket_id, name: :is_reference}, + {key: :token, name: :format}, + {key: :bid_id, name: :is_integer}, + {key: :checked_in, name: :included_in} + ]) } end - it 'event is invalid' do + it "event is invalid" do expect_ticket_updated_to_not_be_called find_error_event { UpdateTickets.update(event_id: 5555, ticket_id: ticket.id) } end - it 'ticket is invalid' do + it "ticket is invalid" do expect_ticket_updated_to_not_be_called find_error_ticket { UpdateTickets.update(event_id: event.id, ticket_id: 5555) } end - it 'ticket is deleted' do + it "ticket is deleted" do ticket.deleted = true ticket.save! expect_ticket_updated_to_not_be_called expect { UpdateTickets.update(event_id: event.id, ticket_id: ticket.id) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :ticket_id }]) - expect(error.message).to include 'deleted' + expect_validation_errors(error.data, [{key: :ticket_id}]) + expect(error.message).to include "deleted" expect(error.message).to include "Ticket ID #{ticket.id}" } end - it 'event is deleted' do + it "event is deleted" do event.deleted = true event.save! expect_ticket_updated_to_not_be_called expect { UpdateTickets.update(event_id: event.id, ticket_id: ticket.id) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :event_id }]) - expect(error.message).to include 'deleted' + expect_validation_errors(error.data, [{key: :event_id}]) + expect(error.message).to include "deleted" expect(error.message).to include "Event ID #{event.id}" } end - it 'event and ticket dont match' do + it "event and ticket dont match" do expect_ticket_updated_to_not_be_called expect { UpdateTickets.update(event_id: event.id, ticket_id: other_ticket.id) }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :ticket_id }]) + expect_validation_errors(error.data, [{key: :ticket_id}]) expect(error.message).to include "Ticket ID #{other_ticket.id} does not belong to event #{event.id}" } end - it 'token is invalid' do + it "token is invalid" do expect_ticket_updated_to_not_be_called validation_invalid_token { UpdateTickets.update(include_fake_token) } end - it 'errors out if token is unauthorized' do + it "errors out if token is unauthorized" do expect_ticket_updated_to_not_be_called validation_unauthorized { UpdateTickets.update(include_fake_token) } end - it 'errors out if token is expired' do + it "errors out if token is expired" do expect_ticket_updated_to_not_be_called validation_expired { UpdateTickets.update(include_fake_token) } end - it 'card doesnt belong to supporter' do + it "card doesnt belong to supporter" do expect_ticket_updated_to_not_be_called validation_card_not_with_supporter { UpdateTickets.update(include_fake_token.merge(token: other_source_token.token)) } end - it 'success editing note' do + it "success editing note" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:ticket_updated, any_args) - result = UpdateTickets.update(basic_valid_ticket_input.merge(note: 'noteedited')) - expected = general_expected.merge(note: 'noteedited') + result = UpdateTickets.update(basic_valid_ticket_input.merge(note: "noteedited")) + expected = general_expected.merge(note: "noteedited") expect(result.attributes).to eq expected ticket.reload expect(ticket.attributes).to eq expected end - it 'success editing bid_id' do + it "success editing bid_id" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:ticket_updated, any_args) result = UpdateTickets.update(basic_valid_ticket_input.merge(bid_id: 50)) @@ -198,10 +195,10 @@ def expect_ticket_updated_to_not_be_called expect(ticket.attributes).to eq expected end - it 'success editing checked_in' do + it "success editing checked_in" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:ticket_updated, any_args) - result = UpdateTickets.update(basic_valid_ticket_input.merge(checked_in: 'true')) + result = UpdateTickets.update(basic_valid_ticket_input.merge(checked_in: "true")) expected = general_expected.merge(checked_in: true) expect(result.attributes).to eq expected @@ -209,7 +206,7 @@ def expect_ticket_updated_to_not_be_called expect(ticket.attributes).to eq expected end - it 'success editing checked_in as a boolean' do + it "success editing checked_in as a boolean" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:ticket_updated, any_args) result = UpdateTickets.update(basic_valid_ticket_input.merge(checked_in: true)) @@ -220,7 +217,7 @@ def expect_ticket_updated_to_not_be_called expect(ticket.attributes).to eq expected end - it 'success editing token' do + it "success editing token" do expect_ticket_updated_to_not_be_called result = UpdateTickets.update(basic_valid_ticket_input.merge(token: source_token.token)) expected = general_expected.merge(source_token_id: source_token.id) @@ -231,12 +228,12 @@ def expect_ticket_updated_to_not_be_called end end - describe '.delete' do + describe ".delete" do include_context :shared_rd_donation_value_context - let(:trx) {create(:transaction, supporter: supporter)} - + let(:trx) { create(:transaction, supporter: supporter) } + let(:basic_valid_ticket_input) do - { ticket_id: ticket.id, event_id: event.id } + {ticket_id: ticket.id, event_id: event.id} end let(:include_fake_token) do basic_valid_ticket_input.merge(token: fake_uuid) @@ -288,39 +285,39 @@ def expect_ticket_updated_to_not_be_called }.with_indifferent_access end - let(:payment) { force_create(:payment) } let(:charge) { force_create(:charge) } let(:ticket) do tp = trx.ticket_purchases.create(event: event) - + ticket = force_create(:ticket, - general_ticket.merge(event: event)) - ticket.quantity.times do + general_ticket.merge(event: event)) + ticket.quantity.times do ticket.ticket_to_legacy_tickets.create(ticket_purchase: tp) end ticket end - it 'marks the given ticket as deleted=true' do + + it "marks the given ticket as deleted=true" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to_not receive(:announce).with(:ticket_updated, any_args) expect(Houdini.event_publisher).to receive(:announce).with(:ticket_deleted, any_args).exactly(ticket.quantity).times - UpdateTickets.delete(ticket['event_id'], ticket['id']) + UpdateTickets.delete(ticket["event_id"], ticket["id"]) ticket.reload - expect(ticket['deleted']).to eq(true) + expect(ticket["deleted"]).to eq(true) expect(ticket.ticket_to_legacy_tickets.all?(&:deleted)).to eq true expect(Ticket.count).to eq(1) end end - describe '.delete_card_for_ticket' do - it 'deletes the card from the ticket' do + describe ".delete_card_for_ticket" do + it "deletes the card from the ticket" do Timecop.freeze(2020, 1, 5) do original_ticket = ticket card = ticket.card expect(ticket.card).to_not be_nil - ret = UpdateTickets.delete_card_for_ticket(ticket['event_id'], ticket['id']) + ret = UpdateTickets.delete_card_for_ticket(ticket["event_id"], ticket["id"]) expect(ret[:status]).to eq :ok expect(ret[:json]).to eq({}) ticket.reload @@ -334,21 +331,21 @@ def expect_ticket_updated_to_not_be_called end end - context 'parameter validation' do - it 'validates parameters' do + context "parameter validation" do + it "validates parameters" do result = UpdateTickets.delete_card_for_ticket(nil, nil) errors = result[:json][:errors] expect(errors.length).to eq(4) expect(result[:status]).to eq :unprocessable_entity expect_validation_errors(errors, [ - { key: :event_id, name: :required }, - { key: :event_id, name: :is_integer }, - { key: :ticket_id, name: :required }, - { key: :ticket_id, name: :is_integer } - ]) + {key: :event_id, name: :required}, + {key: :event_id, name: :is_integer}, + {key: :ticket_id, name: :required}, + {key: :ticket_id, name: :is_integer} + ]) end - it 'invalid event_id causes no problem' do + it "invalid event_id causes no problem" do ticket tickets = Ticket.all events = Event.all @@ -358,7 +355,7 @@ def expect_ticket_updated_to_not_be_called expect(Event.all).to match_array(events) end - it 'invalid ticket_id causes no problem' do + it "invalid ticket_id causes no problem" do ticket tickets = Ticket.all events = Event.all diff --git a/spec/legacy_lib/uuid_spec.rb b/spec/legacy_lib/uuid_spec.rb index acf6b1e0c0..496b95dc87 100644 --- a/spec/legacy_lib/uuid_spec.rb +++ b/spec/legacy_lib/uuid_spec.rb @@ -2,28 +2,28 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'securerandom' -require_relative '../../app/legacy_lib/uuid' +require "securerandom" +require_relative "../../app/legacy_lib/uuid" describe UUID do - describe '::Regex' do - it 'rejects nil' do + describe "::Regex" do + it "rejects nil" do expect(nil).to_not match(UUID::Regex) end - it 'rejects blank' do - expect('').to_not match(UUID::Regex) + it "rejects blank" do + expect("").to_not match(UUID::Regex) end - it 'rejects non-uuid string' do - expect('thweoihchnao-n r -fahc').to_not match(UUID::Regex) + it "rejects non-uuid string" do + expect("thweoihchnao-n r -fahc").to_not match(UUID::Regex) end - it 'accepts unbraced uuid' do + it "accepts unbraced uuid" do expect(SecureRandom.uuid).to match(UUID::Regex) end - it 'accepts braced uuid' do + it "accepts braced uuid" do expect("{#{SecureRandom.uuid}}").to match(UUID::Regex) end end diff --git a/spec/mailers/admin_spec.rb b/spec/mailers/admin_spec.rb index 1d93f53498..934d3be1c9 100644 --- a/spec/mailers/admin_spec.rb +++ b/spec/mailers/admin_spec.rb @@ -2,45 +2,46 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe AdminMailer, type: :mailer do - describe 'notify_failed_gift' do - around(:each) do |ex| + describe "notify_failed_gift" do + around do |ex| before_value = Houdini.hoster.support_email - Houdini.hoster.support_email = 'expected_support@supportemail.com' + Houdini.hoster.support_email = "expected_support@supportemail.com" ex.run Houdini.hoster.support_email = before_value end - let!(:np) { force_create(:nm_justice, name: 'nonprofit', email: 'blah', timezone: 'UTC') } - let!(:s) { force_create(:supporter, email: 'supporter.email@mail.teha') } + + let!(:np) { force_create(:nm_justice, name: "nonprofit", email: "blah", timezone: "UTC") } + let!(:s) { force_create(:supporter, email: "supporter.email@mail.teha") } let!(:oldcard) { force_create(:card) } - let!(:donation) { force_create(:donation, nonprofit_id: np.id, supporter_id: s.id, card_id: oldcard.id, amount: 999) } + let!(:donation) { force_create(:donation, nonprofit_id: np.id, supporter_id: s.id, card_id: oldcard.id, amount: 999) } let!(:charge) { create(:charge, donation: donation, nonprofit: np, amount: 100, created_at: Time.now) } let(:campaign) { force_create(:campaign, nonprofit: np) } - let!(:campaign_gift_option_with_desc) { force_create(:campaign_gift_option, description: 'desc', amount_one_time: 999, campaign: campaign) } + let!(:campaign_gift_option_with_desc) { force_create(:campaign_gift_option, description: "desc", amount_one_time: 999, campaign: campaign) } let!(:campaign_gift_option) { force_create(:campaign_gift_option, campaign: campaign) } let(:mail) { AdminMailer.notify_failed_gift(donation, campaign_gift_option) } let(:mail_with_desc) { AdminMailer.notify_failed_gift(donation, campaign_gift_option_with_desc) } - it 'renders the headers for mail without desc' do + it "renders the headers for mail without desc" do expect(mail.subject).to eq("Tried to associate donation #{donation.id} with campaign gift option #{campaign_gift_option.id} which is out of stock") - expect(mail.to).to eq(['expected_support@supportemail.com']) - expect(mail.from).to eq(['expected_support@supportemail.com']) + expect(mail.to).to eq(["expected_support@supportemail.com"]) + expect(mail.from).to eq(["expected_support@supportemail.com"]) end - it 'renders the body without desc' do - expect(mail.body.encoded).to_not include('desc') + it "renders the body without desc" do + expect(mail.body.encoded).to_not include("desc") end - it 'renders the headers on mail with desc' do + it "renders the headers on mail with desc" do expect(mail_with_desc.subject).to eq("Tried to associate donation #{donation.id} with campaign gift option #{campaign_gift_option_with_desc.id} which is out of stock") - expect(mail_with_desc.to).to eq(['expected_support@supportemail.com']) - expect(mail_with_desc.from).to eq(['expected_support@supportemail.com']) + expect(mail_with_desc.to).to eq(["expected_support@supportemail.com"]) + expect(mail_with_desc.from).to eq(["expected_support@supportemail.com"]) end - it 'renders the body with desc' do - expect(mail.body.encoded).to include('Description:') + it "renders the body with desc" do + expect(mail.body.encoded).to include("Description:") end end end diff --git a/spec/mailers/donation_mailer_spec.rb b/spec/mailers/donation_mailer_spec.rb index 7e4d3d3fd2..50918d05f9 100644 --- a/spec/mailers/donation_mailer_spec.rb +++ b/spec/mailers/donation_mailer_spec.rb @@ -2,68 +2,72 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe DonationMailer, type: :mailer do - describe 'donor_recurring_donation_change_amount' do - let(:np) { force_create(:nm_justice, name: 'nonprofit', email: 'blah') } - let(:s) { force_create(:supporter, email: 'supporter.email@mail.teha') } + describe "donor_recurring_donation_change_amount" do + let(:np) { force_create(:nm_justice, name: "nonprofit", email: "blah") } + let(:s) { force_create(:supporter, email: "supporter.email@mail.teha") } let(:oldcard) { force_create(:card) } - let(:donation) { create(:donation, nonprofit_id: np.id, supporter_id: s.id, card_id: oldcard.id, amount: 999) } - let(:default_message) { 'You have successfully changed your recurring donation amount. Please see the receipt and details below.' } + let(:donation) { create(:donation, nonprofit_id: np.id, supporter_id: s.id, card_id: oldcard.id, amount: 999) } + let(:default_message) { "You have successfully changed your recurring donation amount. Please see the receipt and details below." } let(:rd) do - inner_rd = create(:recurring_donation, amount: 999, active: true, supporter_id: s.id, donation_id: donation.id, nonprofit_id: np.id, start_date: Date.today, interval: 1, time_unit: 'month') + create(:recurring_donation, amount: 999, active: true, supporter_id: s.id, donation_id: donation.id, nonprofit_id: np.id, start_date: Date.today, interval: 1, time_unit: "month") end - before(:each) do + before do np s oldcard donation default_message end - describe 'with custom' do - let(:custom_message) { 'custom_message' } + + describe "with custom" do + let(:custom_message) { "custom_message" } let!(:custom_donor_amount) { create(:miscellaneous_np_info, change_amount_message: custom_message, nonprofit: np) } let!(:mail) { DonationMailer.donor_recurring_donation_change_amount(rd.id, 1000) } - it 'renders the headers' do + + it "renders the headers" do expect(mail.subject).to eq("Recurring donation amount changed for #{np.name}") - expect(mail.to).to eq(['supporter.email@mail.teha']) + expect(mail.to).to eq(["supporter.email@mail.teha"]) expect(mail.reply_to).to eq([np.email]) end - it 'renders the body' do + it "renders the body" do expect(mail.body.encoded).to match custom_message.to_s expect(mail.body.encoded).to_not match default_message.to_s end end - describe 'without custom message' do + describe "without custom message" do let!(:custom_donor_amount) { create(:miscellaneous_np_info, nonprofit: np) } let!(:mail) { DonationMailer.donor_recurring_donation_change_amount(rd.id, 1000) } - it 'renders the headers' do + + it "renders the headers" do expect(mail.subject).to eq("Recurring donation amount changed for #{np.name}") - expect(mail.to).to eq(['supporter.email@mail.teha']) + expect(mail.to).to eq(["supporter.email@mail.teha"]) expect(mail.reply_to).to eq([np.email]) end - it 'renders the body' do + it "renders the body" do expect(mail.body.encoded).to match default_message.to_s end end - describe 'without miscinfo' do + describe "without miscinfo" do let!(:mail) { DonationMailer.donor_recurring_donation_change_amount(rd.id, 1000) } - it 'renders the headers' do + + it "renders the headers" do expect(mail.subject).to eq("Recurring donation amount changed for #{np.name}") - expect(mail.to).to eq(['supporter.email@mail.teha']) + expect(mail.to).to eq(["supporter.email@mail.teha"]) expect(mail.reply_to).to eq([np.email]) end - it 'renders the body' do + it "renders the body" do expect(mail.body.encoded).to match default_message.to_s end end diff --git a/spec/models/campaign_gift_option_spec.rb b/spec/models/campaign_gift_option_spec.rb index cc106c9b8f..1b03e6e814 100644 --- a/spec/models/campaign_gift_option_spec.rb +++ b/spec/models/campaign_gift_option_spec.rb @@ -2,126 +2,123 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe CampaignGiftOption, 'type' => :model do +RSpec.describe CampaignGiftOption, "type" => :model do include_context :shared_donation_charge_context - let(:name) {"CUSTOM GIFT OPTION"} - let(:amount_one_time) { 400} - let(:amount_recurring) { 100} - let(:description) { " Fun description!"} - let(:to_ship) { true} - let(:order) { 3} - - let(:campaign_gift_option) do + let(:name) { "CUSTOM GIFT OPTION" } + let(:amount_one_time) { 400 } + let(:amount_recurring) { 100 } + let(:description) { " Fun description!" } + let(:to_ship) { true } + let(:order) { 3 } + + let(:campaign_gift_option) do campaign.campaign_gift_options.create(description: description, amount_one_time: amount_one_time, amount_recurring: amount_recurring, - name: name, to_ship: to_ship, order: order - ) + name: name, to_ship: to_ship, order: order) end # campaign_gift_option with quantity but no to_ship - let(:campaign_gift_option_2) do + let(:campaign_gift_option_2) do campaign.campaign_gift_options.create(description: description, amount_one_time: amount_one_time, amount_recurring: amount_recurring, - name: name, quantity: 40, hide_contributions: true, order: order - ) + name: name, quantity: 40, hide_contributions: true, order: order) end - describe 'validate' do - it 'has no errors on first example' do + describe "validate" do + it "has no errors on first example" do expect(campaign_gift_option.errors).to be_empty end - it 'has no errors on second example' do + it "has no errors on second example" do expect(campaign_gift_option_2.errors).to be_empty end - end - describe 'create' do - it 'announces create for first example' do + describe "create" do + it "announces create for first example" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'campaign_gift_option.created', - 'data' => { - 'object' => { - 'campaign' => { - 'id' => campaign.id, - 'name' => campaign.name, - 'nonprofit' => nonprofit.id, - 'object' => 'campaign' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "campaign_gift_option.created", + "data" => { + "object" => { + "campaign" => { + "id" => campaign.id, + "name" => campaign.name, + "nonprofit" => nonprofit.id, + "object" => "campaign" }, - 'deleted' => false, - 'description' => description, - 'gift_option_amount' => [ + "deleted" => false, + "description" => description, + "gift_option_amount" => [ { - 'amount' => {'cents'=> amount_one_time, 'currency' => nonprofit.currency}, - 'recurrence' => nil + "amount" => {"cents" => amount_one_time, "currency" => nonprofit.currency}, + "recurrence" => nil }, { - 'amount' => {'cents' => amount_recurring, 'currency' => nonprofit.currency}, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly'} + "amount" => {"cents" => amount_recurring, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} } ], - 'id'=> kind_of(Numeric), - 'hide_contributions' => false, - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "hide_contributions" => false, + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'campaign_gift_option', - 'order' => order, - 'to_ship' => true + "object" => "campaign_gift_option", + "order" => order, + "to_ship" => true } } }) campaign_gift_option end - - it 'announces create for second example' do + + it "announces create for second example" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'campaign_gift_option.created', - 'data' => { - 'object' => { - 'campaign' => { - 'id' => campaign.id, - 'name' => campaign.name, - 'nonprofit' => nonprofit.id, - 'object' => 'campaign' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "campaign_gift_option.created", + "data" => { + "object" => { + "campaign" => { + "id" => campaign.id, + "name" => campaign.name, + "nonprofit" => nonprofit.id, + "object" => "campaign" }, - 'deleted' => false, - 'description' => description, - 'gift_option_amount' => [ + "deleted" => false, + "description" => description, + "gift_option_amount" => [ { - 'amount' => {'cents' => amount_one_time, 'currency' => nonprofit.currency}, - 'recurrence' => nil + "amount" => {"cents" => amount_one_time, "currency" => nonprofit.currency}, + "recurrence" => nil }, { - 'amount' => {'cents' => amount_recurring, 'currency' => nonprofit.currency}, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly'} + "amount" => {"cents" => amount_recurring, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} } ], - 'id'=> kind_of(Numeric), - 'hide_contributions' => true, - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "hide_contributions" => true, + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'campaign_gift_option', - 'order' => order, - 'quantity' => 40, - 'to_ship' => false + "object" => "campaign_gift_option", + "order" => order, + "quantity" => 40, + "to_ship" => false } } }) @@ -130,104 +127,104 @@ end end - describe 'update' do - let(:cgo_update) do + describe "update" do + let(:cgo_update) do campaign_gift_option.amount_one_time = nil campaign_gift_option.save campaign_gift_option end - let(:cgo2_update) do + let(:cgo2_update) do campaign_gift_option_2.amount_recurring = nil campaign_gift_option_2.hide_contributions = false campaign_gift_option_2.save campaign_gift_option_2 end - it 'is without error on first example' do + it "is without error on first example" do expect(cgo_update.errors).to be_empty end - it 'announces update for first example' do + it "announces update for first example" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'campaign_gift_option.updated', - 'data' => { - 'object' => { - 'campaign' => { - 'id' => campaign.id, - 'name' => campaign.name, - 'nonprofit' => nonprofit.id, - 'object' => 'campaign' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "campaign_gift_option.updated", + "data" => { + "object" => { + "campaign" => { + "id" => campaign.id, + "name" => campaign.name, + "nonprofit" => nonprofit.id, + "object" => "campaign" }, - 'deleted' => false, - 'description' => description, - 'gift_option_amount' => [ + "deleted" => false, + "description" => description, + "gift_option_amount" => [ { - 'amount' => {'cents' => amount_recurring, 'currency' => nonprofit.currency}, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly'} + "amount" => {"cents" => amount_recurring, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} } ], - 'id'=> kind_of(Numeric), - 'hide_contributions' => false, - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "hide_contributions" => false, + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'campaign_gift_option', - 'order' => order, - 'to_ship' => true + "object" => "campaign_gift_option", + "order" => order, + "to_ship" => true } } }).ordered cgo_update end - - it 'is without error on second example' do + + it "is without error on second example" do expect(cgo_update.errors).to be_empty end - it 'announces update for second example' do + it "announces update for second example" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'campaign_gift_option.updated', - 'data' => { - 'object' => { - 'campaign' => { - 'id' => campaign.id, - 'name' => campaign.name, - 'nonprofit' => nonprofit.id, - 'object' => 'campaign' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "campaign_gift_option.updated", + "data" => { + "object" => { + "campaign" => { + "id" => campaign.id, + "name" => campaign.name, + "nonprofit" => nonprofit.id, + "object" => "campaign" }, - 'deleted' => false, - 'description' => description, - 'gift_option_amount' => [ + "deleted" => false, + "description" => description, + "gift_option_amount" => [ { - 'amount' => {'cents' => amount_one_time, 'currency' => nonprofit.currency}, - 'recurrence' => nil - }, + "amount" => {"cents" => amount_one_time, "currency" => nonprofit.currency}, + "recurrence" => nil + } ], - 'id'=> kind_of(Numeric), - 'hide_contributions' => false, - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "hide_contributions" => false, + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'campaign_gift_option', - 'order' => order, - 'quantity' => 40, - 'to_ship' => false + "object" => "campaign_gift_option", + "order" => order, + "quantity" => 40, + "to_ship" => false } } }).ordered @@ -236,51 +233,50 @@ end end - - describe 'deleted' do - it 'is without error on first example' do + describe "deleted" do + it "is without error on first example" do campaign_gift_option.destroy expect(campaign_gift_option).to_not be_persisted end - it 'announces deleted for first example' do + it "announces deleted for first example" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'campaign_gift_option.deleted', - 'data' => { - 'object' => { - 'campaign' => { - 'id' => campaign.id, - 'name' => campaign.name, - 'nonprofit' => nonprofit.id, - 'object' => 'campaign' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "campaign_gift_option.deleted", + "data" => { + "object" => { + "campaign" => { + "id" => campaign.id, + "name" => campaign.name, + "nonprofit" => nonprofit.id, + "object" => "campaign" }, - 'deleted' => true, - 'description' => description, - 'gift_option_amount' => [ + "deleted" => true, + "description" => description, + "gift_option_amount" => [ { - 'amount' => {'cents' => amount_one_time, 'currency' => nonprofit.currency}, - 'recurrence' => nil + "amount" => {"cents" => amount_one_time, "currency" => nonprofit.currency}, + "recurrence" => nil }, { - 'amount' => {'cents' => amount_recurring, 'currency' => nonprofit.currency}, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly'} + "amount" => {"cents" => amount_recurring, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} } ], - 'id'=> kind_of(Numeric), - 'hide_contributions' => false, - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "hide_contributions" => false, + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'campaign_gift_option', - 'order' => order, - 'to_ship' => true + "object" => "campaign_gift_option", + "order" => order, + "to_ship" => true } } }) @@ -288,50 +284,50 @@ campaign_gift_option.destroy end - it 'is without error on second example' do + it "is without error on second example" do campaign_gift_option_2.destroy expect(campaign_gift_option_2).to_not be_persisted end - - it 'announces deleted for second example' do + + it "announces deleted for second example" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'campaign_gift_option.deleted', - 'data' => { - 'object' => { - 'campaign' => { - 'id' => campaign.id, - 'name' => campaign.name, - 'nonprofit' => nonprofit.id, - 'object' => 'campaign' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "campaign_gift_option.deleted", + "data" => { + "object" => { + "campaign" => { + "id" => campaign.id, + "name" => campaign.name, + "nonprofit" => nonprofit.id, + "object" => "campaign" }, - 'deleted' => true, - 'description' => description, - 'gift_option_amount' => [ + "deleted" => true, + "description" => description, + "gift_option_amount" => [ { - 'amount' => {'cents' => amount_one_time, 'currency' => nonprofit.currency}, - 'recurrence' => nil + "amount" => {"cents" => amount_one_time, "currency" => nonprofit.currency}, + "recurrence" => nil }, { - 'amount' => {'cents' => amount_recurring, 'currency' => nonprofit.currency}, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly'} + "amount" => {"cents" => amount_recurring, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} } ], - 'id'=> kind_of(Numeric), - 'hide_contributions' => true, - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "hide_contributions" => true, + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'campaign_gift_option', - 'order' => order, - 'quantity' => 40, - 'to_ship' => false + "object" => "campaign_gift_option", + "order" => order, + "quantity" => 40, + "to_ship" => false } } }) @@ -340,20 +336,21 @@ end end - describe '#gift_option_amounts' do - subject(:goa) { campaign_gift_option.gift_option_amounts} + describe "#gift_option_amounts" do + subject(:goa) { campaign_gift_option.gift_option_amounts } - it { expect(goa.count).to eq 2} + it { expect(goa.count).to eq 2 } describe "has a proper one time amount" do - subject { goa.detect{|i| i.recurrence.nil?}} + subject { goa.detect { |i| i.recurrence.nil? } } it { is_expected.to have_attributes( amount: have_attributes( - cents:amount_one_time, - currency: nonprofit.currency - )) + cents: amount_one_time, + currency: nonprofit.currency + ) + ) } it { @@ -362,20 +359,20 @@ end describe "has a proper one time amount" do - subject { goa.detect{|i| !i.recurrence.nil?}} + subject { goa.detect { |i| !i.recurrence.nil? } } it { is_expected.to have_attributes( amount: have_attributes( - cents:amount_recurring, - currency: nonprofit.currency - )) + cents: amount_recurring, + currency: nonprofit.currency + ) + ) } it { - is_expected.to have_attributes(recurrence: - have_attributes( interval: 1, type: 'monthly') - ) + is_expected.to have_attributes(recurrence: + have_attributes(interval: 1, type: "monthly")) } end end diff --git a/spec/models/campaign_gift_purchase_spec.rb b/spec/models/campaign_gift_purchase_spec.rb index 03ae31cf57..a668b1cbbb 100644 --- a/spec/models/campaign_gift_purchase_spec.rb +++ b/spec/models/campaign_gift_purchase_spec.rb @@ -2,79 +2,81 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe CampaignGiftPurchase, type: :model do include_context :shared_donation_charge_context # TODO Why are we manually setting everything here? It's not clear what order things should # go in for a transaction. Therefore, we don't assume the order for now and just make sure the # the output of to_builder is right - let(:trx) { force_create(:transaction, supporter: supporter, amount: 400)} - - let(:campaign_gift_purchase) {trx.campaign_gift_purchases.create(campaign: campaign, amount: 400, campaign_gifts: [ModernCampaignGift.new(amount: 400, legacy_campaign_gift:lcg)])} - let(:lcg) { CampaignGift.create( - donation: supporter.donations.create(amount: 400, campaign: campaign, nonprofit: nonprofit, supporter:supporter), - campaign_gift_option: campaign_gift_option - )} - let(:campaign_gift_option) { create(:campaign_gift_option, amount_one_time: 400, campaign: campaign)} - let(:campaign_gift) { campaign_gift_purchase.campaign_gifts.first} + let(:trx) { force_create(:transaction, supporter: supporter, amount: 400) } + + let(:campaign_gift_purchase) { trx.campaign_gift_purchases.create(campaign: campaign, amount: 400, campaign_gifts: [ModernCampaignGift.new(amount: 400, legacy_campaign_gift: lcg)]) } + let(:lcg) { + CampaignGift.create( + donation: supporter.donations.create(amount: 400, campaign: campaign, nonprofit: nonprofit, supporter: supporter), + campaign_gift_option: campaign_gift_option + ) + } + let(:campaign_gift_option) { create(:campaign_gift_option, amount_one_time: 400, campaign: campaign) } + let(:campaign_gift) { campaign_gift_purchase.campaign_gifts.first } let(:campaign_builder_expanded) do { - 'id' => kind_of(Numeric), - 'name' => campaign.name, - 'object' => "campaign", - 'nonprofit' => nonprofit.id + "id" => kind_of(Numeric), + "name" => campaign.name, + "object" => "campaign", + "nonprofit" => nonprofit.id } end let(:cgo_builder_expanded) do { - 'id' => kind_of(Numeric), - 'name' => campaign_gift_option.name, - 'description' => campaign_gift_option.description, - 'hide_contributions' => campaign_gift_option.hide_contributions, - 'order' => campaign_gift_option.order, - 'to_ship' => campaign_gift_option.to_ship, - 'object' => 'campaign_gift_option', - 'deleted' => false, - 'gift_option_amount' => [{ - 'amount' => { - 'cents' => 400, - 'currency' => 'usd' - }, + "id" => kind_of(Numeric), + "name" => campaign_gift_option.name, + "description" => campaign_gift_option.description, + "hide_contributions" => campaign_gift_option.hide_contributions, + "order" => campaign_gift_option.order, + "to_ship" => campaign_gift_option.to_ship, + "object" => "campaign_gift_option", + "deleted" => false, + "gift_option_amount" => [{ + "amount" => { + "cents" => 400, + "currency" => "usd" + } }], - 'campaign' => kind_of(Numeric), - 'nonprofit' => nonprofit.id + "campaign" => kind_of(Numeric), + "nonprofit" => nonprofit.id } end let(:np_builder_expanded) do { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" } end let(:supporter_builder_expanded) do - supporter_to_builder_base.merge({'name'=> 'Fake Supporter Name'}) + supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) end let(:transaction_builder_expanded) do { - 'id' => match_houid('trx'), - 'object' => 'transaction', - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("trx"), + "object" => "transaction", + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'created' => Time.current.to_i, - 'supporter' => supporter.id, - 'nonprofit' => nonprofit.id, - 'subtransaction' => nil, - 'payments' => [], - 'transaction_assignments' => [ + "created" => Time.current.to_i, + "supporter" => supporter.id, + "nonprofit" => nonprofit.id, + "subtransaction" => nil, + "payments" => [], + "transaction_assignments" => [ cgp_builder_to_id ] } @@ -82,72 +84,69 @@ let(:cgp_builder_to_id) do { - 'id' => match_houid('cgpur'), - 'object' => 'campaign_gift_purchase', - 'type' => 'trx_assignment' + "id" => match_houid("cgpur"), + "object" => "campaign_gift_purchase", + "type" => "trx_assignment" } end let(:cgp_builder_expanded) do { - 'id' => match_houid('cgpur'), - 'campaign' => kind_of(Numeric), - 'object' => 'campaign_gift_purchase', - 'campaign_gifts' => [modern_campaign_gift_builder], - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("cgpur"), + "campaign" => kind_of(Numeric), + "object" => "campaign_gift_purchase", + "campaign_gifts" => [modern_campaign_gift_builder], + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded, - 'transaction' => transaction_builder_expanded, - 'deleted' => false + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded, + "transaction" => transaction_builder_expanded, + "deleted" => false } end let(:modern_campaign_gift_builder) { { - 'amount' => { - 'cents' => 400, - 'currency' => 'usd' + "amount" => { + "cents" => 400, + "currency" => "usd" }, - 'campaign' => kind_of(Numeric), - 'campaign_gift_option' => kind_of(Numeric), - 'campaign_gift_purchase' => match_houid('cgpur'), - 'deleted' => false, - 'id' => match_houid('cgift'), - 'nonprofit'=> nonprofit.id, - 'object' => 'campaign_gift', - 'supporter' => supporter.id, - 'transaction' => match_houid('trx') + "campaign" => kind_of(Numeric), + "campaign_gift_option" => kind_of(Numeric), + "campaign_gift_purchase" => match_houid("cgpur"), + "deleted" => false, + "id" => match_houid("cgift"), + "nonprofit" => nonprofit.id, + "object" => "campaign_gift", + "supporter" => supporter.id, + "transaction" => match_houid("trx") } } - - - - it 'announces created properly when called' do + it "announces created properly when called" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, any_args) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_purchase_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'campaign_gift_purchase.created', - 'data' => { - 'object' => { - 'id' => match_houid('cgpur'), - 'campaign' => campaign_builder_expanded, - 'object' => 'campaign_gift_purchase', - 'campaign_gifts' => [modern_campaign_gift_builder], - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "campaign_gift_purchase.created", + "data" => { + "object" => { + "id" => match_houid("cgpur"), + "campaign" => campaign_builder_expanded, + "object" => "campaign_gift_purchase", + "campaign_gifts" => [modern_campaign_gift_builder], + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded, - 'transaction' => transaction_builder_expanded, - 'deleted' => false, - 'type' => 'trx_assignment' + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded, + "transaction" => transaction_builder_expanded, + "deleted" => false, + "type" => "trx_assignment" } } }) @@ -155,28 +154,28 @@ campaign_gift_purchase.publish_created end - it 'announces updated properly when called' do + it "announces updated properly when called" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, any_args) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_purchase_updated, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'campaign_gift_purchase.updated', - 'data' => { - 'object' => { - 'id' => match_houid('cgpur'), - 'campaign' => campaign_builder_expanded, - 'object' => 'campaign_gift_purchase', - 'campaign_gifts' => [modern_campaign_gift_builder], - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "campaign_gift_purchase.updated", + "data" => { + "object" => { + "id" => match_houid("cgpur"), + "campaign" => campaign_builder_expanded, + "object" => "campaign_gift_purchase", + "campaign_gifts" => [modern_campaign_gift_builder], + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded, - 'transaction' => transaction_builder_expanded, - 'deleted' => false, - 'type' => 'trx_assignment' + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded, + "transaction" => transaction_builder_expanded, + "deleted" => false, + "type" => "trx_assignment" } } }) @@ -184,28 +183,28 @@ campaign_gift_purchase.publish_updated end - it 'announces updated deleted properly when called' do + it "announces updated deleted properly when called" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_option_created, any_args) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_purchase_deleted, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'campaign_gift_purchase.deleted', - 'data' => { - 'object' => { - 'id' => match_houid('cgpur'), - 'campaign' => campaign_builder_expanded, - 'object' => 'campaign_gift_purchase', - 'campaign_gifts' => [modern_campaign_gift_builder], - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "campaign_gift_purchase.deleted", + "data" => { + "object" => { + "id" => match_houid("cgpur"), + "campaign" => campaign_builder_expanded, + "object" => "campaign_gift_purchase", + "campaign_gifts" => [modern_campaign_gift_builder], + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'supporter' => supporter_builder_expanded, - 'nonprofit' => np_builder_expanded, - 'transaction' => transaction_builder_expanded, - 'deleted' => true, - 'type' => 'trx_assignment' + "supporter" => supporter_builder_expanded, + "nonprofit" => np_builder_expanded, + "transaction" => transaction_builder_expanded, + "deleted" => true, + "type" => "trx_assignment" } } }) @@ -213,4 +212,4 @@ campaign_gift_purchase.discard! campaign_gift_purchase.publish_deleted end -end \ No newline at end of file +end diff --git a/spec/models/campaign_spec.rb b/spec/models/campaign_spec.rb index 964a6b1469..eec2b53349 100644 --- a/spec/models/campaign_spec.rb +++ b/spec/models/campaign_spec.rb @@ -2,27 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Campaign, type: :model do - describe 'sends correct email based on type of campaign' do + describe "sends correct email based on type of campaign" do let(:nonprofit) { force_create(:nm_justice) } - let(:parent_campaign) { force_create(:campaign, name: 'Parent campaign', nonprofit: nonprofit) } + let(:parent_campaign) { force_create(:campaign, name: "Parent campaign", nonprofit: nonprofit) } let(:child_campaign) do force_create(:campaign, - name: 'Child campaign', - parent_campaign_id: parent_campaign.id, - slug: 'twehotiheiotheiofnieoth', - goal_amount_dollars: '1000', nonprofit: nonprofit) + name: "Child campaign", + parent_campaign_id: parent_campaign.id, + slug: "twehotiheiotheiofnieoth", + goal_amount_dollars: "1000", nonprofit: nonprofit) end - it 'parent campaign sends out a create job' do + it "parent campaign sends out a create job" do expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args).exactly(:once) parent_campaign end - it 'child campaign sends out federated create job' do - expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args).exactly(:twice) + it "child campaign sends out federated create job" do + expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args).exactly(:twice) parent_campaign child_campaign end diff --git a/spec/models/concerns/model/eventable_spec.rb b/spec/models/concerns/model/eventable_spec.rb index 267f16d80d..15af442ac0 100644 --- a/spec/models/concerns/model/eventable_spec.rb +++ b/spec/models/concerns/model/eventable_spec.rb @@ -2,41 +2,41 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Model::Eventable do + let(:event_type) { "model.event_name" } - let(:event_type) {'model.event_name'} - class ClassWithoutToBuilder - include Model::Eventable - end + class ClassWithoutToBuilder + include Model::Eventable + end - class ClassWithToBuilder - include Model::Eventable + class ClassWithToBuilder + include Model::Eventable - def to_builder(*expand) - Jbuilder.new do |json| - json.id 1 - end - end - end + def to_builder(*expand) + Jbuilder.new do |json| + json.id 1 + end + end + end - it 'raises NotImplementedError when no to_builder is defined by developer' do - obj = ClassWithoutToBuilder.new - expect { obj.to_event event_type}.to raise_error(NotImplementedError) - end + it "raises NotImplementedError when no to_builder is defined by developer" do + obj = ClassWithoutToBuilder.new + expect { obj.to_event event_type }.to raise_error(NotImplementedError) + end - it 'returns an proper event when to_builder is defined by developer' do - obj = ClassWithToBuilder.new - expect(obj.to_event event_type).to match({ - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => event_type, - 'data' => { - 'object' => { - 'id' => 1 - } - } - }) - end + it "returns an proper event when to_builder is defined by developer" do + obj = ClassWithToBuilder.new + expect(obj.to_event(event_type)).to match({ + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => event_type, + "data" => { + "object" => { + "id" => 1 + } + } + }) + end end diff --git a/spec/models/concerns/model/houidable_spec.rb b/spec/models/concerns/model/houidable_spec.rb index c50269d329..61ba58fdd0 100644 --- a/spec/models/concerns/model/houidable_spec.rb +++ b/spec/models/concerns/model/houidable_spec.rb @@ -2,215 +2,215 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" # rubocop:disable RSpec/VerifiedDoubles, RSpec/MessageSpies regular doubles work fine in this use-case RSpec.describe Model::Houidable do - let(:houid_test_class) do - Class.new do - include ActiveModel::AttributeAssignment - include ActiveModel::Model - extend ActiveModel::Callbacks - include Model::Houidable - - attr_accessor :id, :houid_id - - define_model_callbacks :initialize - define_model_callbacks :save - def initialize(attributes = {}) - run_callbacks :initialize do - assign_attributes(attributes) - end - end - - def save - run_callbacks :save do - # run save - end - end - - # mock for read and write attributes - def read_attribute(attr_name) - send(attr_name.to_sym) - end - - def write_attribute(attr_name, value) - send("#{attr_name}=".to_sym, value) - end - end - end - - context 'when using the default :id attribute' do - let(:test_class) do - Class.new(houid_test_class) do - setup_houid :trxassign - end - end - - let(:with_before_set_callback) do - Class.new(test_class) do - mattr_accessor :callback_handler - before_houid_set ->(model) { self.class.callback_handler.before_houid_set_callback(model) } - end - end - - let(:with_after_set_callback) do - Class.new(test_class) do - mattr_accessor :callback_handler - after_houid_set ->(model) { self.class.callback_handler.after_houid_set_callback(model) } - end - end - - let(:prefix) { :trxassign } - let(:preset_houid) { 'test_eoiathotih' } - - let(:default_trxassign) { test_class.new } - - let(:already_set_houid) { test_class.new(id: preset_houid) } - - it 'sets houid_prefix' do - expect(default_trxassign.houid_prefix).to eq prefix - end - - it 'generates a valid houid' do - expect(default_trxassign.generate_houid).to match_houid(prefix) - end - - context 'when only initialized' do - it 'doesnt set a houid' do - expect(default_trxassign.id).to be_nil - end - - it 'will not override an id if already set' do - expect(already_set_houid.id).to eq preset_houid - end - - it 'will not fire the before_houid_set callback' do - with_before_set_callback.callback_handler = double('Before Callback Handler') - expect(with_before_set_callback.callback_handler).to_not receive(:before_houid_set_callback) - with_before_set_callback.new - end - - it 'will not fire the after_houid_set callback' do - with_after_set_callback.callback_handler = double('After Callback Handler') - expect(with_after_set_callback.callback_handler).to_not receive(:after_houid_set_callback) - with_after_set_callback.new - end - end - - context 'when saved' do - it 'generates a valid houid' do - default_trxassign.save - expect(default_trxassign.id).to match_houid(prefix) - end - - it 'will not override an id if already set' do - already_set_houid.save - expect(already_set_houid.id).to eq preset_houid - end - - it 'fires the before_houid_set callback' do - with_before_set_callback.callback_handler = double('Before Callback Handler') - expect(with_before_set_callback.callback_handler).to receive(:before_houid_set_callback).with( - having_attributes(id: nil) - ) - with_before_set_callback.new.save - end - - it 'fires the after_houid_set callback' do - with_after_set_callback.callback_handler = double('After Callback Handler') - expect(with_after_set_callback.callback_handler).to receive(:after_houid_set_callback).with( - having_attributes(id: match_houid(:trxassign)) - ) - with_after_set_callback.new.save - end - end - end - - context 'when using a custom attribute' do - let(:test_class) do - Class.new(houid_test_class) do - setup_houid 'trxassign', 'houid_id' - end - end - - let(:with_before_set_callback) do - Class.new(test_class) do - mattr_accessor :callback_handler - before_houid_set ->(model) { self.class.callback_handler.before_houid_set_callback(model) } - end - end - - let(:with_after_set_callback) do - Class.new(test_class) do - mattr_accessor :callback_handler - after_houid_set ->(model) { self.class.callback_handler.after_houid_set_callback(model) } - end - end - - let(:prefix) { :trxassign } - let(:preset_houid) { 'test_eoiathotih' } - - let(:default_trxassign) { test_class.new } - - let(:already_set_houid) { test_class.new(houid_id: preset_houid) } - - it 'sets houid_prefix' do - expect(default_trxassign.houid_prefix).to eq prefix - end - - it 'generates a valid houid' do - expect(default_trxassign.generate_houid).to match_houid(prefix) - end - - context 'when only initialized' do - it 'does not set a houid' do - expect(default_trxassign.houid_id).to be_nil - end - - it 'will not override an id if already set' do - expect(already_set_houid.houid_id).to eq preset_houid - end - - it 'will not fire the before_houid_set callback' do - with_before_set_callback.callback_handler = double('Before Callback Handler') # rubocop:disable RSpec/VerifiedDoubles - expect(with_before_set_callback.callback_handler).to_not receive(:before_houid_set_callback) - with_before_set_callback.new - end - - it 'will not fire the after_houid_set callback' do - with_after_set_callback.callback_handler = double('After Callback Handler') # rubocop:disable RSpec/VerifiedDoubles - expect(with_after_set_callback.callback_handler).to_not receive(:after_houid_set_callback) - with_after_set_callback.new - end - end - - context 'when saved' do - it 'sets a valid houid as id' do - default_trxassign.save - expect(default_trxassign.houid_id).to match_houid(prefix) - end - - it 'will not override an id if already set' do - already_set_houid.save - expect(already_set_houid.houid_id).to eq preset_houid - end - - it 'fires the before_houid_set callback' do - with_before_set_callback.callback_handler = double('Before Callback Handler') # rubocop:disable RSpec/VerifiedDoubles - expect(with_before_set_callback.callback_handler).to receive(:before_houid_set_callback).with( - having_attributes(houid_id: nil) - ) - with_before_set_callback.new.save - end - - it 'fires the after_houid_set callback' do - with_after_set_callback.callback_handler = double('After Callback Handler') # rubocop:disable RSpec/VerifiedDoubles - expect(with_after_set_callback.callback_handler).to receive(:after_houid_set_callback).with( - having_attributes(houid_id: match_houid(:trxassign)) - ) - with_after_set_callback.new.save - end - end - end + let(:houid_test_class) do + Class.new do + include ActiveModel::AttributeAssignment + include ActiveModel::Model + extend ActiveModel::Callbacks + include Model::Houidable + + attr_accessor :id, :houid_id + + define_model_callbacks :initialize + define_model_callbacks :save + def initialize(attributes = {}) + run_callbacks :initialize do + assign_attributes(attributes) + end + end + + def save + run_callbacks :save do + # run save + end + end + + # mock for read and write attributes + def read_attribute(attr_name) + send(attr_name.to_sym) + end + + def write_attribute(attr_name, value) + send(:"#{attr_name}=", value) + end + end + end + + context "when using the default :id attribute" do + let(:test_class) do + Class.new(houid_test_class) do + setup_houid :trxassign + end + end + + let(:with_before_set_callback) do + Class.new(test_class) do + mattr_accessor :callback_handler + before_houid_set ->(model) { self.class.callback_handler.before_houid_set_callback(model) } + end + end + + let(:with_after_set_callback) do + Class.new(test_class) do + mattr_accessor :callback_handler + after_houid_set ->(model) { self.class.callback_handler.after_houid_set_callback(model) } + end + end + + let(:prefix) { :trxassign } + let(:preset_houid) { "test_eoiathotih" } + + let(:default_trxassign) { test_class.new } + + let(:already_set_houid) { test_class.new(id: preset_houid) } + + it "sets houid_prefix" do + expect(default_trxassign.houid_prefix).to eq prefix + end + + it "generates a valid houid" do + expect(default_trxassign.generate_houid).to match_houid(prefix) + end + + context "when only initialized" do + it "doesnt set a houid" do + expect(default_trxassign.id).to be_nil + end + + it "will not override an id if already set" do + expect(already_set_houid.id).to eq preset_houid + end + + it "will not fire the before_houid_set callback" do + with_before_set_callback.callback_handler = double("Before Callback Handler") + expect(with_before_set_callback.callback_handler).to_not receive(:before_houid_set_callback) + with_before_set_callback.new + end + + it "will not fire the after_houid_set callback" do + with_after_set_callback.callback_handler = double("After Callback Handler") + expect(with_after_set_callback.callback_handler).to_not receive(:after_houid_set_callback) + with_after_set_callback.new + end + end + + context "when saved" do + it "generates a valid houid" do + default_trxassign.save + expect(default_trxassign.id).to match_houid(prefix) + end + + it "will not override an id if already set" do + already_set_houid.save + expect(already_set_houid.id).to eq preset_houid + end + + it "fires the before_houid_set callback" do + with_before_set_callback.callback_handler = double("Before Callback Handler") + expect(with_before_set_callback.callback_handler).to receive(:before_houid_set_callback).with( + having_attributes(id: nil) + ) + with_before_set_callback.new.save + end + + it "fires the after_houid_set callback" do + with_after_set_callback.callback_handler = double("After Callback Handler") + expect(with_after_set_callback.callback_handler).to receive(:after_houid_set_callback).with( + having_attributes(id: match_houid(:trxassign)) + ) + with_after_set_callback.new.save + end + end + end + + context "when using a custom attribute" do + let(:test_class) do + Class.new(houid_test_class) do + setup_houid "trxassign", "houid_id" + end + end + + let(:with_before_set_callback) do + Class.new(test_class) do + mattr_accessor :callback_handler + before_houid_set ->(model) { self.class.callback_handler.before_houid_set_callback(model) } + end + end + + let(:with_after_set_callback) do + Class.new(test_class) do + mattr_accessor :callback_handler + after_houid_set ->(model) { self.class.callback_handler.after_houid_set_callback(model) } + end + end + + let(:prefix) { :trxassign } + let(:preset_houid) { "test_eoiathotih" } + + let(:default_trxassign) { test_class.new } + + let(:already_set_houid) { test_class.new(houid_id: preset_houid) } + + it "sets houid_prefix" do + expect(default_trxassign.houid_prefix).to eq prefix + end + + it "generates a valid houid" do + expect(default_trxassign.generate_houid).to match_houid(prefix) + end + + context "when only initialized" do + it "does not set a houid" do + expect(default_trxassign.houid_id).to be_nil + end + + it "will not override an id if already set" do + expect(already_set_houid.houid_id).to eq preset_houid + end + + it "will not fire the before_houid_set callback" do + with_before_set_callback.callback_handler = double("Before Callback Handler") # rubocop:disable RSpec/VerifiedDoubles + expect(with_before_set_callback.callback_handler).to_not receive(:before_houid_set_callback) + with_before_set_callback.new + end + + it "will not fire the after_houid_set callback" do + with_after_set_callback.callback_handler = double("After Callback Handler") # rubocop:disable RSpec/VerifiedDoubles + expect(with_after_set_callback.callback_handler).to_not receive(:after_houid_set_callback) + with_after_set_callback.new + end + end + + context "when saved" do + it "sets a valid houid as id" do + default_trxassign.save + expect(default_trxassign.houid_id).to match_houid(prefix) + end + + it "will not override an id if already set" do + already_set_houid.save + expect(already_set_houid.houid_id).to eq preset_houid + end + + it "fires the before_houid_set callback" do + with_before_set_callback.callback_handler = double("Before Callback Handler") # rubocop:disable RSpec/VerifiedDoubles + expect(with_before_set_callback.callback_handler).to receive(:before_houid_set_callback).with( + having_attributes(houid_id: nil) + ) + with_before_set_callback.new.save + end + + it "fires the after_houid_set callback" do + with_after_set_callback.callback_handler = double("After Callback Handler") # rubocop:disable RSpec/VerifiedDoubles + expect(with_after_set_callback.callback_handler).to receive(:after_houid_set_callback).with( + having_attributes(houid_id: match_houid(:trxassign)) + ) + with_after_set_callback.new.save + end + end + end end # rubocop:enable RSpec/VerifiedDoubles, RSpec/MessageSpies diff --git a/spec/models/concerns/model/jbuilder_spec.rb b/spec/models/concerns/model/jbuilder_spec.rb index df46a0a8f7..c09ab9daef 100644 --- a/spec/models/concerns/model/jbuilder_spec.rb +++ b/spec/models/concerns/model/jbuilder_spec.rb @@ -2,156 +2,156 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Model::Jbuilder do - describe Model::Jbuilder::BuilderExpansion do - let(:model) do - stub_const('HasToBuilderAndToId', Struct.new(:to_id, :to_builder)) - - stub_const('ModelClass', Struct.new(:filled, :unfilled, :enumerable, :json_based_id, :flat_enumerable)) - - ModelClass.new( - HasToBuilderAndToId.new('id_result', 'builder_result'), - nil, - [ - HasToBuilderAndToId.new('enumerable_id_result_1', Jbuilder.new { |json| json.id 'enumerable_builder_result_1' }), - HasToBuilderAndToId.new('enumerable_id_result_2', Jbuilder.new { |json| json.id 'enumerable_builder_result_2' }) - ], - HasToBuilderAndToId.new(Jbuilder.new do |json| - json.id 'json_based_id' - end, 'expanded'), - %w[ - flat_id_result_1 - flat_id_result_2 - ] - ) - end - let(:filled_expansion) { described_class.new(key: :filled, json_attribute: 'filled_attrib') } - let(:unfilled_expansion) { described_class.new(key: :unfilled) } - let(:nonexistent_expansion) { described_class.new(key: :nonexistent) } - let(:expandable_expansion) { described_class.new(key: :enumerable, enum_type: :expandable) } - let(:flat_expansion) { described_class.new(key: :flat_enumerable, enum_type: :flat) } - - describe 'expansion where the attribute is filled' do - subject { filled_expansion } - - it { - is_expected.to have_attributes( - json_attribute: 'filled_attrib', - enumerable?: false, - flat_enum?: false, - expandable_enum?: false - ) - } - - describe '#to_id' do - subject { filled_expansion.to_id.call(model) } - - it { is_expected.to eq 'id_result' } - end - - describe '#to_builder' do - subject { filled_expansion.to_builder.call(model) } - - it { is_expected.to eq 'builder_result' } - end - end - - describe 'expansion where the attribute is unfilled' do - subject { unfilled_expansion } - - it { - is_expected.to have_attributes( - json_attribute: 'unfilled', - enumerable?: false, - flat_enum?: false, - expandable_enum?: false - ) - } - - describe '#to_id' do - subject { unfilled_expansion.to_id.call(model) } - - it { is_expected.to be_nil } - end - - describe '#to_builder' do - subject { unfilled_expansion.to_builder.call(model) } - - it { is_expected.to be_nil } - end - end - - describe 'expansion where the attribute is nonexistent' do - subject { nonexistent_expansion } - - it { - is_expected.to have_attributes( - json_attribute: 'nonexistent', - enumerable?: false, - flat_enum?: false, - expandable_enum?: false - ) - } - - it '.to_id raises error' do - expect { nonexistent_expansion.to_id.call(model) }.to raise_error ActiveModel::MissingAttributeError - end - - it '.to_builder raises error' do - expect { nonexistent_expansion.to_builder.call(model) }.to raise_error ActiveModel::MissingAttributeError - end - end - - describe 'expansion of expandable enumerable returns an enumerable' do - subject { expandable_expansion } - - it { - is_expected.to have_attributes( - json_attribute: 'enumerable', - enumerable?: true, - flat_enum?: false, - expandable_enum?: true - ) - } - - describe '#to_id' do - subject { expandable_expansion.to_id.call(model) } - - it { is_expected.to match(%w[enumerable_id_result_1 enumerable_id_result_2]) } - end - - describe '#to_builder' do - subject { expandable_expansion.to_builder.call(model) } - - it { is_expected.to match([{ 'id' => 'enumerable_builder_result_1' }, { 'id' => 'enumerable_builder_result_2' }]) } - end - end - - describe 'expansion of flat enumerable returns an enumerable' do - subject { flat_expansion } - - it { - is_expected.to have_attributes( - json_attribute: 'flat_enumerable', - enumerable?: true, - flat_enum?: true, - expandable_enum?: false - ) - } - - describe '#to_id' do - subject { flat_expansion.to_id.call(model) } - - it { is_expected.to match(%w[flat_id_result_1 flat_id_result_2]) } - end - - describe '#to_builder' do - subject { flat_expansion.to_builder.call(model) } - - it { is_expected.to match(%w[flat_id_result_1 flat_id_result_2]) } - end - end - end + describe Model::Jbuilder::BuilderExpansion do + let(:model) do + stub_const("HasToBuilderAndToId", Struct.new(:to_id, :to_builder)) + + stub_const("ModelClass", Struct.new(:filled, :unfilled, :enumerable, :json_based_id, :flat_enumerable)) + + ModelClass.new( + HasToBuilderAndToId.new("id_result", "builder_result"), + nil, + [ + HasToBuilderAndToId.new("enumerable_id_result_1", Jbuilder.new { |json| json.id "enumerable_builder_result_1" }), + HasToBuilderAndToId.new("enumerable_id_result_2", Jbuilder.new { |json| json.id "enumerable_builder_result_2" }) + ], + HasToBuilderAndToId.new(Jbuilder.new do |json| + json.id "json_based_id" + end, "expanded"), + %w[ + flat_id_result_1 + flat_id_result_2 + ] + ) + end + let(:filled_expansion) { described_class.new(key: :filled, json_attribute: "filled_attrib") } + let(:unfilled_expansion) { described_class.new(key: :unfilled) } + let(:nonexistent_expansion) { described_class.new(key: :nonexistent) } + let(:expandable_expansion) { described_class.new(key: :enumerable, enum_type: :expandable) } + let(:flat_expansion) { described_class.new(key: :flat_enumerable, enum_type: :flat) } + + describe "expansion where the attribute is filled" do + subject { filled_expansion } + + it { + is_expected.to have_attributes( + json_attribute: "filled_attrib", + enumerable?: false, + flat_enum?: false, + expandable_enum?: false + ) + } + + describe "#to_id" do + subject { filled_expansion.to_id.call(model) } + + it { is_expected.to eq "id_result" } + end + + describe "#to_builder" do + subject { filled_expansion.to_builder.call(model) } + + it { is_expected.to eq "builder_result" } + end + end + + describe "expansion where the attribute is unfilled" do + subject { unfilled_expansion } + + it { + is_expected.to have_attributes( + json_attribute: "unfilled", + enumerable?: false, + flat_enum?: false, + expandable_enum?: false + ) + } + + describe "#to_id" do + subject { unfilled_expansion.to_id.call(model) } + + it { is_expected.to be_nil } + end + + describe "#to_builder" do + subject { unfilled_expansion.to_builder.call(model) } + + it { is_expected.to be_nil } + end + end + + describe "expansion where the attribute is nonexistent" do + subject { nonexistent_expansion } + + it { + is_expected.to have_attributes( + json_attribute: "nonexistent", + enumerable?: false, + flat_enum?: false, + expandable_enum?: false + ) + } + + it ".to_id raises error" do + expect { nonexistent_expansion.to_id.call(model) }.to raise_error ActiveModel::MissingAttributeError + end + + it ".to_builder raises error" do + expect { nonexistent_expansion.to_builder.call(model) }.to raise_error ActiveModel::MissingAttributeError + end + end + + describe "expansion of expandable enumerable returns an enumerable" do + subject { expandable_expansion } + + it { + is_expected.to have_attributes( + json_attribute: "enumerable", + enumerable?: true, + flat_enum?: false, + expandable_enum?: true + ) + } + + describe "#to_id" do + subject { expandable_expansion.to_id.call(model) } + + it { is_expected.to match(%w[enumerable_id_result_1 enumerable_id_result_2]) } + end + + describe "#to_builder" do + subject { expandable_expansion.to_builder.call(model) } + + it { is_expected.to match([{"id" => "enumerable_builder_result_1"}, {"id" => "enumerable_builder_result_2"}]) } + end + end + + describe "expansion of flat enumerable returns an enumerable" do + subject { flat_expansion } + + it { + is_expected.to have_attributes( + json_attribute: "flat_enumerable", + enumerable?: true, + flat_enum?: true, + expandable_enum?: false + ) + } + + describe "#to_id" do + subject { flat_expansion.to_id.call(model) } + + it { is_expected.to match(%w[flat_id_result_1 flat_id_result_2]) } + end + + describe "#to_builder" do + subject { flat_expansion.to_builder.call(model) } + + it { is_expected.to match(%w[flat_id_result_1 flat_id_result_2]) } + end + end + end end diff --git a/spec/models/custom_field_definition_spec.rb b/spec/models/custom_field_definition_spec.rb index abd0462086..8bcb97fc37 100644 --- a/spec/models/custom_field_definition_spec.rb +++ b/spec/models/custom_field_definition_spec.rb @@ -2,60 +2,61 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe CustomFieldDefinition, type: :model do include_context :shared_donation_charge_context - let(:name) { "CustomFieldDefinition1"} + let(:name) { "CustomFieldDefinition1" } let(:custom_field_definition) { nonprofit.custom_field_definitions.create(name: name) } - let(:np_builder_expanded) { { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }} - - it 'creates' do + let(:np_builder_expanded) { + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } + } + + it "creates" do expect(custom_field_definition.errors).to be_empty end - it 'announces create' do + it "announces create" do expect(Houdini.event_publisher).to receive(:announce).with(:custom_field_definition_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'custom_field_definition.created', - 'data' => { - 'object' => { - 'id'=> kind_of(Numeric), - 'deleted' => false, - 'name' => name, - 'nonprofit'=> np_builder_expanded, - 'object' => 'custom_field_definition' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "custom_field_definition.created", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => false, + "name" => name, + "nonprofit" => np_builder_expanded, + "object" => "custom_field_definition" } } }) custom_field_definition end - - it 'announces deleted' do + + it "announces deleted" do expect(Houdini.event_publisher).to receive(:announce).with(:custom_field_definition_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:custom_field_definition_deleted, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'custom_field_definition.deleted', - 'data' => { - 'object' => { - 'id'=> kind_of(Numeric), - 'deleted' => true, - 'name' => name, - 'nonprofit'=> np_builder_expanded, - 'object' => 'custom_field_definition' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "custom_field_definition.deleted", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => true, + "name" => name, + "nonprofit" => np_builder_expanded, + "object" => "custom_field_definition" } } }).ordered - - custom_field_definition.discard! + custom_field_definition.discard! end end diff --git a/spec/models/event_discount_spec.rb b/spec/models/event_discount_spec.rb index 33980a2e2e..79669626e7 100644 --- a/spec/models/event_discount_spec.rb +++ b/spec/models/event_discount_spec.rb @@ -2,99 +2,109 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe EventDiscount, type: :model do include_context :shared_donation_charge_context - let(:name) {"CUSTOM EVENT DISCOUNT"} - let(:percent) { 55} - let(:code) { "fewet"} - let(:event_discount) { + let(:name) { "CUSTOM EVENT DISCOUNT" } + let(:percent) { 55 } + let(:code) { "fewet" } + let(:event_discount) { ticket_level event.event_discounts.create(name: name, percent: percent, code: code) } - describe 'validate' do - let(:event_discount) { ed = EventDiscount.new; ed.save; ed} - let(:ed_percent_at_0) { ed = EventDiscount.new(percent: 0); ed.save; ed} - let(:ed_percent_at_101) { ed = EventDiscount.new(percent: 101); ed.save; ed} - - it('has errors on name') do + describe "validate" do + let(:event_discount) { + ed = EventDiscount.new + ed.save + ed + } + let(:ed_percent_at_0) { + ed = EventDiscount.new(percent: 0) + ed.save + ed + } + let(:ed_percent_at_101) { + ed = EventDiscount.new(percent: 101) + ed.save + ed + } + + it("has errors on name") do expect(event_discount.errors.details[:name].length).to be(1) end - it('has errors on code') do + it("has errors on code") do expect(event_discount.errors.details[:code].length).to be(1) end - it('has errors on event') do + it("has errors on event") do expect(event_discount.errors.details[:event].length).to be(1) end - it('has errors on percent') do + it("has errors on percent") do expect(event_discount.errors.details[:percent].length).to be(2) end - it('has errors on percents at 0') do + it("has errors on percents at 0") do expect(ed_percent_at_0.errors.details[:percent].length).to be(1) end - it('has errors on percents at 101') do + it("has errors on percents at 101") do expect(ed_percent_at_101.errors.details[:percent].length).to be(1) end - end - describe 'create' do - - it 'is without error' do + describe "create" do + it "is without error" do expect(event_discount.errors).to be_empty end - it 'announces create' do + it "announces create" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:event_discount_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'event_discount.created', - 'data' => { - 'object' => { - 'code' => code, - 'deleted' => false, - 'discount' => { - 'percent' => percent + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "event_discount.created", + "data" => { + "object" => { + "code" => code, + "deleted" => false, + "discount" => { + "percent" => percent + }, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id }, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'event_discount', - 'ticket_levels' => [ + "object" => "event_discount", + "ticket_levels" => [ { - 'id' => ticket_level.id, - 'name' => ticket_level.name, - 'deleted' => ticket_level.deleted, - 'order' => ticket_level.order, - 'limit' => ticket_level.limit, - 'object' => 'ticket_level', - 'description' => ticket_level.description, - 'amount' => { - 'cents' => ticket_level.amount, - 'currency' => 'usd' + "id" => ticket_level.id, + "name" => ticket_level.name, + "deleted" => ticket_level.deleted, + "order" => ticket_level.order, + "limit" => ticket_level.limit, + "object" => "ticket_level", + "description" => ticket_level.description, + "amount" => { + "cents" => ticket_level.amount, + "currency" => "usd" }, - 'available_to' => 'everyone', - 'nonprofit' => nonprofit.id, - 'event' => event.id, - 'event_discounts' => [kind_of(Numeric)] + "available_to" => "everyone", + "nonprofit" => nonprofit.id, + "event" => event.id, + "event_discounts" => [kind_of(Numeric)] } ] } @@ -105,121 +115,120 @@ end end - describe 'update' do - it 'is without error' do - event_discount.code = 'code' + describe "update" do + it "is without error" do + event_discount.code = "code" event_discount.save expect(event_discount.errors).to be_empty end - it 'announces updated' do + it "announces updated" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:event_discount_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:event_discount_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'event_discount.updated', - 'data' => { - 'object' => { - 'code' => 'code', - 'deleted' => false, - 'discount' => { - 'percent' => percent + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "event_discount.updated", + "data" => { + "object" => { + "code" => "code", + "deleted" => false, + "discount" => { + "percent" => percent }, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id }, - 'object' => 'event_discount', - 'ticket_levels' => [ + "id" => kind_of(Numeric), + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "event_discount", + "ticket_levels" => [ { - 'id' => ticket_level.id, - 'name' => ticket_level.name, - 'deleted' => ticket_level.deleted, - 'order' => ticket_level.order, - 'limit' => ticket_level.limit, - 'object' => 'ticket_level', - 'description' => ticket_level.description, - 'amount' => { - 'cents' => ticket_level.amount, - 'currency' => 'usd' + "id" => ticket_level.id, + "name" => ticket_level.name, + "deleted" => ticket_level.deleted, + "order" => ticket_level.order, + "limit" => ticket_level.limit, + "object" => "ticket_level", + "description" => ticket_level.description, + "amount" => { + "cents" => ticket_level.amount, + "currency" => "usd" }, - 'available_to' => 'everyone', - 'nonprofit' => nonprofit.id, - 'event' => event.id, - 'event_discounts' => [kind_of(Numeric)] + "available_to" => "everyone", + "nonprofit" => nonprofit.id, + "event" => event.id, + "event_discounts" => [kind_of(Numeric)] } ] } } }).ordered - event_discount.code = 'code' + event_discount.code = "code" event_discount.save! end end - - describe 'deleted' do - it 'is without error' do + describe "deleted" do + it "is without error" do event_discount.destroy expect(event_discount).to_not be_persisted end - it 'announces deleted' do + it "announces deleted" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:event_discount_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:event_discount_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'event_discount.deleted', - 'data' => { - 'object' => { - 'code' => code, - 'deleted' => true, - 'discount' => { - 'percent' => percent + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "event_discount.deleted", + "data" => { + "object" => { + "code" => code, + "deleted" => true, + "discount" => { + "percent" => percent + }, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id }, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'name' => name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => kind_of(Numeric), + "name" => name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'object' => 'event_discount', - 'ticket_levels' => [ + "object" => "event_discount", + "ticket_levels" => [ { - 'id' => ticket_level.id, - 'name' => ticket_level.name, - 'deleted' => ticket_level.deleted, - 'order' => ticket_level.order, - 'limit' => ticket_level.limit, - 'object' => 'ticket_level', - 'description' => ticket_level.description, - 'amount' => { - 'cents' => ticket_level.amount, - 'currency' => 'usd' + "id" => ticket_level.id, + "name" => ticket_level.name, + "deleted" => ticket_level.deleted, + "order" => ticket_level.order, + "limit" => ticket_level.limit, + "object" => "ticket_level", + "description" => ticket_level.description, + "amount" => { + "cents" => ticket_level.amount, + "currency" => "usd" }, - 'available_to' => 'everyone', - 'nonprofit' => nonprofit.id, - 'event' => event.id, - 'event_discounts' => [kind_of(Numeric)] + "available_to" => "everyone", + "nonprofit" => nonprofit.id, + "event" => event.id, + "event_discounts" => [kind_of(Numeric)] } ] } diff --git a/spec/models/import_request_spec.rb b/spec/models/import_request_spec.rb index b3c5477530..a131d3064d 100644 --- a/spec/models/import_request_spec.rb +++ b/spec/models/import_request_spec.rb @@ -2,52 +2,55 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe ImportRequest, type: :model do - let(:import_path){ "spec/fixtures/test_import.csv"} - let(:import_filename) { 'test_import.csv'} - - let(:row_count) { 4} - let(:nonprofit) { create(:nm_justice)} - let(:user) {force_create(:user)} - let(:user_email) { user.email} - let(:header_matches) { { - "Date" => "donation.date", - "Program" => "donation.designation", - "Amount" => "donation.amount", - "Business or organization name" => "supporter.organization", - "First Name" => "supporter.first_name", - "Last Name" => "supporter.last_name", - "Address" => "supporter.address", - "City" => "supporter.city", - "State" => "supporter.state_code", - "Zip Code" => "supporter.zip_code", - "EMAIL" => "supporter.email", - "notes" => "donation.comment", - "Field Guy" => "custom_field", - "Tag 1" => "tag", - "Tag 2" => "tag" - }} - - describe 'successful' do - around(:each) do |example| - Timecop.freeze(2020, 5,5) do + let(:import_path) { "spec/fixtures/test_import.csv" } + let(:import_filename) { "test_import.csv" } + + let(:row_count) { 4 } + let(:nonprofit) { create(:nm_justice) } + let(:user) { force_create(:user) } + let(:user_email) { user.email } + let(:header_matches) { + { + "Date" => "donation.date", + "Program" => "donation.designation", + "Amount" => "donation.amount", + "Business or organization name" => "supporter.organization", + "First Name" => "supporter.first_name", + "Last Name" => "supporter.last_name", + "Address" => "supporter.address", + "City" => "supporter.city", + "State" => "supporter.state_code", + "Zip Code" => "supporter.zip_code", + "EMAIL" => "supporter.email", + "notes" => "donation.comment", + "Field Guy" => "custom_field", + "Tag 1" => "tag", + "Tag 2" => "tag" + } + } + + describe "successful" do + around do |example| + Timecop.freeze(2020, 5, 5) do example.run end end - let(:request) { - ir = ImportRequest.new(nonprofit:nonprofit, header_matches: header_matches, user_email:user_email) - ir.import_file.attach(io: File.open(import_path), filename:import_filename) + + let(:request) { + ir = ImportRequest.new(nonprofit: nonprofit, header_matches: header_matches, user_email: user_email) + ir.import_file.attach(io: File.open(import_path), filename: import_filename) ir.save! ir } - let!(:import) { request.execute(user)} + let!(:import) { request.execute(user) } - let(:donations) { Supporter.all.map(&:donations).flatten} + let(:donations) { Supporter.all.map(&:donations).flatten } - it 'creates an Import with all the correct data' do + it "creates an Import with all the correct data" do expect(import.nonprofit).to eq(nonprofit) expect(import.id).to be_present expect(import.row_count).to eq row_count @@ -56,60 +59,60 @@ expect(import.imported_count).to eq(16) end - it 'deleted the import request' do + it "deleted the import request" do expect(ImportRequest.where(id: request.id).count).to eq 0 end - it 'creates all the supporters with correct names' do - names = Supporter.pluck(:name) - expect(names).to match_array ['Robert Norris', 'Angie Vaughn', 'Bill Waddell', 'Bubba Thurmond'] + it "creates all the supporters with correct names" do + names = Supporter.pluck(:name) + expect(names).to match_array ["Robert Norris", "Angie Vaughn", "Bill Waddell", "Bubba Thurmond"] end - it 'creates all the supporters with correct emails' do + it "creates all the supporters with correct emails" do emails = Supporter.pluck(:email) - expect(emails).to match_array(['user@example.com', 'user@example.com', 'user@example.com', 'user@example.com']) + expect(emails).to match_array(["user@example.com", "user@example.com", "user@example.com", "user@example.com"]) end - it 'creates all the supporters with correct organizations' do + it "creates all the supporters with correct organizations" do orgs = Supporter.pluck(:organization) - expect(orgs).to match_array ['Jet-Pep', 'Klein Drug Shoppe, Inc.', 'River City Equipment Rental and Sales', 'Somewhere LLC'] + expect(orgs).to match_array ["Jet-Pep", "Klein Drug Shoppe, Inc.", "River City Equipment Rental and Sales", "Somewhere LLC"] end - it 'creates all the supporters with correct cities' do + it "creates all the supporters with correct cities" do cities = Supporter.pluck(:city) - expect(cities).to match_array ['Decatur', 'Guntersville', 'Holly Pond', 'Snead'] + expect(cities).to match_array ["Decatur", "Guntersville", "Holly Pond", "Snead"] end - it 'creates all the supporters with correct addresses' do + it "creates all the supporters with correct addresses" do addresses = Supporter.pluck(:address) - expect(addresses).to match_array(['3370 Alabama Highway 69', '649 Finley Island Road', 'P.O. Box 143', 'P.O. Box 611']) + expect(addresses).to match_array(["3370 Alabama Highway 69", "649 Finley Island Road", "P.O. Box 143", "P.O. Box 611"]) end - it 'creates all the supporters with correct zip_codes' do + it "creates all the supporters with correct zip_codes" do zips = Supporter.pluck(:zip_code) - expect(zips).to match_array(['35601', '35806', '35952', '35976']) + expect(zips).to match_array(["35601", "35806", "35952", "35976"]) end - it 'creates all the supporters with correct state_codes' do - states = Supporter.pluck(:state_code) - expect(states).to match_array(['AL', 'AL', 'AL', 'AL']) + it "creates all the supporters with correct state_codes" do + states = Supporter.pluck(:state_code) + expect(states).to match_array(["AL", "AL", "AL", "AL"]) end - it 'creates all the donations with correct amounts' do - amounts = donations.map { |d| d['amount'] } + it "creates all the donations with correct amounts" do + amounts = donations.map { |d| d["amount"] } expect(amounts).to match_array([1000, 1000, 1000, 1000]) end - it 'creates all the donations with correct designations' do - desigs = donations.map { |d| d['designation'] } - expect(desigs).to match_array(['third party event', 'third party event', 'third party event', 'third party event']) + it "creates all the donations with correct designations" do + desigs = donations.map { |d| d["designation"] } + expect(desigs).to match_array(["third party event", "third party event", "third party event", "third party event"]) end - it 'inserts custom fields' do + it "inserts custom fields" do vals = CustomFieldJoin.pluck(:value) - expect(vals).to match_array(['custfield', 'custfield', 'custfield', 'custfield']) + expect(vals).to match_array(["custfield", "custfield", "custfield", "custfield"]) end - it 'inserts tags' do + it "inserts tags" do names = TagJoin.joins(:tag_definition).pluck("tag_definitions.name") expect(names).to match_array(%w[tag1 tag1 tag1 tag1 tag2 tag2 tag2 tag2]) end diff --git a/spec/models/modern_campaign_gift_spec.rb b/spec/models/modern_campaign_gift_spec.rb index 2660f63e4e..bf1d1d3386 100644 --- a/spec/models/modern_campaign_gift_spec.rb +++ b/spec/models/modern_campaign_gift_spec.rb @@ -2,130 +2,132 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe ModernCampaignGift, type: :model do include_context :shared_donation_charge_context # TODO Why are we manually setting everything here? It's not clear what order things should # go in for a transaction. Therefore, we don't assume the order for now and just make sure the # the output of to_builder is right - let(:trx) { force_create(:transaction, supporter: supporter, amount: 400)} - - let(:campaign_gift_purchase) {trx.campaign_gift_purchases.create(campaign: campaign, amount: 400, campaign_gifts: [ModernCampaignGift.new(amount: 400, legacy_campaign_gift:lcg)])} - let(:lcg) { CampaignGift.create( - donation: supporter.donations.create(amount: 400, campaign: campaign, nonprofit: nonprofit, supporter:supporter), - campaign_gift_option: campaign_gift_option - )} - let(:campaign_gift_option) { create(:campaign_gift_option, amount_one_time: 400, campaign: campaign)} - let(:campaign_gift) { campaign_gift_purchase.campaign_gifts.first} + let(:trx) { force_create(:transaction, supporter: supporter, amount: 400) } + + let(:campaign_gift_purchase) { trx.campaign_gift_purchases.create(campaign: campaign, amount: 400, campaign_gifts: [ModernCampaignGift.new(amount: 400, legacy_campaign_gift: lcg)]) } + let(:lcg) { + CampaignGift.create( + donation: supporter.donations.create(amount: 400, campaign: campaign, nonprofit: nonprofit, supporter: supporter), + campaign_gift_option: campaign_gift_option + ) + } + let(:campaign_gift_option) { create(:campaign_gift_option, amount_one_time: 400, campaign: campaign) } + let(:campaign_gift) { campaign_gift_purchase.campaign_gifts.first } let(:campaign_builder_expanded) do { - 'id' => kind_of(Numeric), - 'name' => campaign.name, - 'object' => "campaign", - 'nonprofit' => nonprofit.id + "id" => kind_of(Numeric), + "name" => campaign.name, + "object" => "campaign", + "nonprofit" => nonprofit.id } end let(:cgo_builder_expanded) do { - 'id' => kind_of(Numeric), - 'name' => campaign_gift_option.name, - 'description' => campaign_gift_option.description, - 'hide_contributions' => campaign_gift_option.hide_contributions, - 'order' => campaign_gift_option.order, - 'to_ship' => campaign_gift_option.to_ship, - 'object' => 'campaign_gift_option', - 'deleted' => false, - 'gift_option_amount' => [{ - 'amount' => { - 'cents' => 400, - 'currency' => 'usd' + "id" => kind_of(Numeric), + "name" => campaign_gift_option.name, + "description" => campaign_gift_option.description, + "hide_contributions" => campaign_gift_option.hide_contributions, + "order" => campaign_gift_option.order, + "to_ship" => campaign_gift_option.to_ship, + "object" => "campaign_gift_option", + "deleted" => false, + "gift_option_amount" => [{ + "amount" => { + "cents" => 400, + "currency" => "usd" }, - 'recurrence' => nil + "recurrence" => nil }], - 'campaign' => kind_of(Numeric), - 'nonprofit' => kind_of(Numeric) + "campaign" => kind_of(Numeric), + "nonprofit" => kind_of(Numeric) } end let(:np_builder_expanded) do { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" } end let(:supporter_builder_expanded) do - supporter_to_builder_base.merge({'name'=> 'Fake Supporter Name'}) + supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) end let(:transaction_builder_expanded) do { - 'id' => match_houid('trx'), - 'object' => 'transaction', - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("trx"), + "object" => "transaction", + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'created' => Time.current.to_i, - 'supporter' => kind_of(Numeric), - 'nonprofit' => kind_of(Numeric), - 'subtransaction' => nil, - 'payments' => [], - 'transaction_assignments' => [cgp_builder_to_id] + "created" => Time.current.to_i, + "supporter" => kind_of(Numeric), + "nonprofit" => kind_of(Numeric), + "subtransaction" => nil, + "payments" => [], + "transaction_assignments" => [cgp_builder_to_id] } end let(:cgp_builder_to_id) do { - 'id' => match_houid('cgpur'), - 'object' => 'campaign_gift_purchase', - 'type' => 'trx_assignment' + "id" => match_houid("cgpur"), + "object" => "campaign_gift_purchase", + "type" => "trx_assignment" } end let(:cgp_builder_expanded) do { - 'id' => match_houid('cgpur'), - 'campaign' => kind_of(Numeric), - 'object' => 'campaign_gift_purchase', - 'campaign_gifts' => [match_houid('cgift')], - 'amount' => { - 'cents' => trx.amount, - 'currency' => 'usd' + "id" => match_houid("cgpur"), + "campaign" => kind_of(Numeric), + "object" => "campaign_gift_purchase", + "campaign_gifts" => [match_houid("cgift")], + "amount" => { + "cents" => trx.amount, + "currency" => "usd" }, - 'supporter' => kind_of(Numeric), - 'nonprofit' => kind_of(Numeric), - 'transaction' => match_houid('trx'), - 'deleted' => false, - 'type' => 'trx_assignment' + "supporter" => kind_of(Numeric), + "nonprofit" => kind_of(Numeric), + "transaction" => match_houid("trx"), + "deleted" => false, + "type" => "trx_assignment" } end - it 'announces created properly when called' do + it "announces created properly when called" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_created, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'campaign_gift.created', - 'data' => { - 'object' => { - 'amount' => { - 'cents' => 400, - 'currency' => 'usd' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "campaign_gift.created", + "data" => { + "object" => { + "amount" => { + "cents" => 400, + "currency" => "usd" }, - 'campaign' => campaign_builder_expanded, - 'campaign_gift_option' => cgo_builder_expanded, - 'campaign_gift_purchase' => cgp_builder_expanded, - 'deleted' => false, - 'id' => match_houid('cgift'), - 'nonprofit'=> np_builder_expanded, - 'object' => 'campaign_gift', - 'supporter' => supporter_builder_expanded, - 'transaction' => transaction_builder_expanded + "campaign" => campaign_builder_expanded, + "campaign_gift_option" => cgo_builder_expanded, + "campaign_gift_purchase" => cgp_builder_expanded, + "deleted" => false, + "id" => match_houid("cgift"), + "nonprofit" => np_builder_expanded, + "object" => "campaign_gift", + "supporter" => supporter_builder_expanded, + "transaction" => transaction_builder_expanded } } }) @@ -133,27 +135,27 @@ campaign_gift.publish_created end - it 'announces updated properly when called' do + it "announces updated properly when called" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_updated, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'campaign_gift.updated', - 'data' => { - 'object' => { - 'amount' => { - 'cents' => 400, - 'currency' => 'usd' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "campaign_gift.updated", + "data" => { + "object" => { + "amount" => { + "cents" => 400, + "currency" => "usd" }, - 'campaign' => campaign_builder_expanded, - 'campaign_gift_option' => cgo_builder_expanded, - 'campaign_gift_purchase' => cgp_builder_expanded, - 'deleted' => false, - 'id' => match_houid('cgift'), - 'nonprofit'=> np_builder_expanded, - 'object' => 'campaign_gift', - 'supporter' => supporter_builder_expanded, - 'transaction' => transaction_builder_expanded + "campaign" => campaign_builder_expanded, + "campaign_gift_option" => cgo_builder_expanded, + "campaign_gift_purchase" => cgp_builder_expanded, + "deleted" => false, + "id" => match_houid("cgift"), + "nonprofit" => np_builder_expanded, + "object" => "campaign_gift", + "supporter" => supporter_builder_expanded, + "transaction" => transaction_builder_expanded } } }) @@ -161,27 +163,27 @@ campaign_gift.publish_updated end - it 'announces updated deleted properly when called' do + it "announces updated deleted properly when called" do allow(Houdini.event_publisher).to receive(:announce) expect(Houdini.event_publisher).to receive(:announce).with(:campaign_gift_deleted, { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'campaign_gift.deleted', - 'data' => { - 'object' => { - 'amount' => { - 'cents' => 400, - 'currency' => 'usd' + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "campaign_gift.deleted", + "data" => { + "object" => { + "amount" => { + "cents" => 400, + "currency" => "usd" }, - 'campaign' => campaign_builder_expanded, - 'campaign_gift_option' => cgo_builder_expanded, - 'campaign_gift_purchase' => cgp_builder_expanded, - 'deleted' => true, - 'id' => match_houid('cgift'), - 'nonprofit'=> np_builder_expanded, - 'object' => 'campaign_gift', - 'supporter' => supporter_builder_expanded, - 'transaction' => transaction_builder_expanded + "campaign" => campaign_builder_expanded, + "campaign_gift_option" => cgo_builder_expanded, + "campaign_gift_purchase" => cgp_builder_expanded, + "deleted" => true, + "id" => match_houid("cgift"), + "nonprofit" => np_builder_expanded, + "object" => "campaign_gift", + "supporter" => supporter_builder_expanded, + "transaction" => transaction_builder_expanded } } }) diff --git a/spec/models/modern_donation_spec.rb b/spec/models/modern_donation_spec.rb index d1999ea6ab..fe552032e3 100644 --- a/spec/models/modern_donation_spec.rb +++ b/spec/models/modern_donation_spec.rb @@ -2,52 +2,55 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe ModernDonation, type: :model do include_context :shared_donation_charge_context # TODO Why are we manually setting everything here? It's not clear what order things should # go in for a transaction. Therefore, we don't assume the order for now and just make sure the # the output of to_builder is right - let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200)} + let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200) } let(:legacy_donation) { force_create(:donation, amount: 1200) } - let(:dedication) {{ - type: 'honor', - name: "Grandma Schultz" - }} + let(:dedication) { + { + type: "honor", + name: "Grandma Schultz" + } + } - let(:legacy_donation_with_dedication_and_designation) { force_create(:donation, amount: 1200, designation: 'designation', dedication: dedication) } - describe 'to_builder' do - let(:don_default) do + let(:legacy_donation_with_dedication_and_designation) { force_create(:donation, amount: 1200, designation: "designation", dedication: dedication) } + + describe "to_builder" do + let(:don_default) do { - 'id' => match_houid('don'), - 'object' => 'donation', - 'nonprofit' => nonprofit.id, - 'supporter' => supporter.id, - 'amount' => {'currency' => 'usd', 'cents' => 1200}, - 'transaction' => trx.id, - 'designation' => nil, - 'type' => 'trx_assignment' + "id" => match_houid("don"), + "object" => "donation", + "nonprofit" => nonprofit.id, + "supporter" => supporter.id, + "amount" => {"currency" => "usd", "cents" => 1200}, + "transaction" => trx.id, + "designation" => nil, + "type" => "trx_assignment" } end - it 'without dedication or designation' do + + it "without dedication or designation" do donation = trx.donations.create(amount: 1200) donation.legacy_donation = legacy_donation donation.save! expect(donation.to_builder.attributes!).to match(don_default) end - - it 'with designation and dedication' do + it "with designation and dedication" do donation = trx.donations.create(amount: 1200) donation.legacy_donation = legacy_donation_with_dedication_and_designation donation.save! expect(donation.to_builder.attributes!).to match(don_default.merge({ - 'designation' => 'designation', - 'dedication' => { - 'type' => 'honor', - 'name' => 'Grandma Schultz' + "designation" => "designation", + "dedication" => { + "type" => "honor", + "name" => "Grandma Schultz" } })) end diff --git a/spec/models/nonprofit_spec.rb b/spec/models/nonprofit_spec.rb index 6bc8a54b12..6c682b09cc 100644 --- a/spec/models/nonprofit_spec.rb +++ b/spec/models/nonprofit_spec.rb @@ -2,74 +2,77 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Nonprofit, type: :model do + describe ".currency_symbol" do + let(:nonprofit) { force_create(:nm_justice, currency: "eur") } + let(:euro) { "€" } - describe '.currency_symbol' do - let(:nonprofit) { force_create(:nm_justice, currency: 'eur') } - let(:euro) { '€' } - - it 'finds correct currency symbol for nonprofit' do + it "finds correct currency symbol for nonprofit" do expect(nonprofit.currency_symbol).to eq euro end end - describe '.for_type' do + describe ".for_type" do let(:nonprofit) { create(:nm_justice) } - let(:type) { 'supporter.created' } - let(:other_type) { 'supporter.deleted' } + let(:type) { "supporter.created" } + let(:other_type) { "supporter.deleted" } let!(:object_event_hook_config) do nonprofit.object_event_hook_configs.create( webhook_service: :open_fn, configuration: { - webhook_url: 'https://www.openfn.org/inbox/my-inbox-id', - headers: { 'x-api-key': 'my-secret-key' } + webhook_url: "https://www.openfn.org/inbox/my-inbox-id", + headers: {"x-api-key": "my-secret-key"} }, object_event_types: [type, other_type] ) end - describe 'there is an ObjectEventHookConfig for the specified type' do - it 'returns a list of ObjectEventHookConfigs' do + describe "there is an ObjectEventHookConfig for the specified type" do + it "returns a list of ObjectEventHookConfigs" do result = nonprofit.object_event_hook_configs.for_type(type) expect(result).to eq([object_event_hook_config]) end end - describe 'there is not an ObjectEventHookConfig for the specified type' do - let(:some_other_type) { 'supporter.updated' } - it 'returns an empty list' do + describe "there is not an ObjectEventHookConfig for the specified type" do + let(:some_other_type) { "supporter.updated" } + + it "returns an empty list" do result = nonprofit.object_event_hook_configs.for_type(some_other_type) expect(result).to eq([]) end end end - describe 'create' do - describe 'validates on parameters' do - let(:nonprofit) { Nonprofit.new()} - let(:nonprofit_with_invalid_user) { Nonprofit.new(user_id: 3333)} - let(:nonprofit_with_user_who_already_admin) {nonprofit_admin_role; Nonprofit.new(user_id: user.id)} + describe "create" do + describe "validates on parameters" do + let(:nonprofit) { Nonprofit.new } + let(:nonprofit_with_invalid_user) { Nonprofit.new(user_id: 3333) } + let(:nonprofit_with_user_who_already_admin) { + nonprofit_admin_role + Nonprofit.new(user_id: user.id) + } - let(:nonprofit_with_same_name) { Nonprofit.new({name: "New Mexico Equality", state_code: nm_justice.state_code, city: nm_justice.city, user_id: user.id})} - let(:nonprofit_with_same_name_but_different_state) { Nonprofit.new({name: "New Mexico Equality", state_code: 'mn', city: nm_justice.city, user_id: user.id })} + let(:nonprofit_with_same_name) { Nonprofit.new({name: "New Mexico Equality", state_code: nm_justice.state_code, city: nm_justice.city, user_id: user.id}) } + let(:nonprofit_with_same_name_but_different_state) { Nonprofit.new({name: "New Mexico Equality", state_code: "mn", city: nm_justice.city, user_id: user.id}) } - let(:nonprofit_with_bad_email_and_website) { Nonprofit.new({email: 'not_email', website: 'not_website' })} + let(:nonprofit_with_bad_email_and_website) { Nonprofit.new({email: "not_email", website: "not_website"}) } - let(:nonprofit_with_not_US_state) { Nonprofit.new(user_id: user.id, state_code: 'KK')} - let(:nonprofit_with_non_capitalized_state_code) { Nonprofit.new(user_id: user.id, state_code: 'Or')} + let(:nonprofit_with_not_US_state) { Nonprofit.new(user_id: user.id, state_code: "KK") } + let(:nonprofit_with_non_capitalized_state_code) { Nonprofit.new(user_id: user.id, state_code: "Or") } - let(:user) { create(:user)} + let(:user) { create(:user) } let(:nonprofit_admin_role) do - role = user.roles.build(host: nonprofit, name: 'nonprofit_admin') + role = user.roles.build(host: nonprofit, name: "nonprofit_admin") role.save! role end - let(:nm_justice) {create(:nm_justice)} + let(:nm_justice) { create(:nm_justice) } - before(:each) do + before do nonprofit.valid? nonprofit_with_invalid_user.valid? nonprofit_with_user_who_already_admin.valid? @@ -80,125 +83,125 @@ nonprofit_with_non_capitalized_state_code.valid? end - it 'has an error for no name' do - expect(nonprofit.errors['name'].first).to match /.*blank.*/ + it "has an error for no name" do + expect(nonprofit.errors["name"].first).to match(/.*blank.*/) end - it 'has an error for no user' do - expect(nonprofit.errors['user_id'].first).to match /.*blank.*/ + it "has an error for no user" do + expect(nonprofit.errors["user_id"].first).to match(/.*blank.*/) end - it 'has an error for no city' do - expect(nonprofit.errors['city'].first).to match /.*blank.*/ + it "has an error for no city" do + expect(nonprofit.errors["city"].first).to match(/.*blank.*/) end - it 'has an error for no state' do - expect(nonprofit.errors['state_code'].first).to match /.*blank.*/ + it "has an error for no state" do + expect(nonprofit.errors["state_code"].first).to match(/.*blank.*/) end - it 'has an error for not in the US state' do - expect(nonprofit_with_not_US_state.errors['state_code']).to match_array ['must be a US two-letter state code'] + it "has an error for not in the US state" do + expect(nonprofit_with_not_US_state.errors["state_code"]).to match_array ["must be a US two-letter state code"] end - it 'does nothing when the state code is not capitalized' do - expect(nonprofit_with_non_capitalized_state_code.errors['state_code']).to be_empty + it "does nothing when the state code is not capitalized" do + expect(nonprofit_with_non_capitalized_state_code.errors["state_code"]).to be_empty end - it 'rejects an invalid user' do - expect(nonprofit_with_invalid_user.errors['user_id'].first).to match /.*not a valid user.*/ + it "rejects an invalid user" do + expect(nonprofit_with_invalid_user.errors["user_id"].first).to match(/.*not a valid user.*/) end - it 'rejects a user who is already an admin' do - expect(nonprofit_with_user_who_already_admin.errors['user_id'].first).to match /.*admin.*/ + it "rejects a user who is already an admin" do + expect(nonprofit_with_user_who_already_admin.errors["user_id"].first).to match(/.*admin.*/) end - it 'accepts and corrects a slug when it tries to save' do - expect(nonprofit_with_same_name.errors['slug']).to be_empty + it "accepts and corrects a slug when it tries to save" do + expect(nonprofit_with_same_name.errors["slug"]).to be_empty expect(nonprofit_with_same_name.slug).to eq "#{nm_justice.slug}-00" end - it 'does nothing to a slug when a slug was provided' do - expect(nonprofit_with_same_name_but_different_state.errors['slug']).to be_empty + it "does nothing to a slug when a slug was provided" do + expect(nonprofit_with_same_name_but_different_state.errors["slug"]).to be_empty expect(nonprofit_with_same_name_but_different_state.slug).to eq "#{nm_justice.slug}" end - it 'marks email as having errors if they do' do - expect(nonprofit_with_bad_email_and_website.errors['email'].first).to match /.*invalid.*/ + it "marks email as having errors if they do" do + expect(nonprofit_with_bad_email_and_website.errors["email"].first).to match(/.*invalid.*/) end - describe 'website validation' do - it 'marks as having errors if it does not have a public suffix' do - expect(nonprofit_with_bad_email_and_website.errors['website'].first) - .to match('is not a valid URL') + describe "website validation" do + it "marks as having errors if it does not have a public suffix" do + expect(nonprofit_with_bad_email_and_website.errors["website"].first) + .to match("is not a valid URL") end - it 'does not mark website as having errors if it does not have a scheme and adds scheme' do - nonprofit_with_bad_email_and_website.update(website: 'a_website.com') - expect(nonprofit_with_bad_email_and_website.errors['website'].first) + it "does not mark website as having errors if it does not have a scheme and adds scheme" do + nonprofit_with_bad_email_and_website.update(website: "a_website.com") + expect(nonprofit_with_bad_email_and_website.errors["website"].first) .to be_nil expect(nonprofit_with_bad_email_and_website.website) - .to eq('http://a_website.com') + .to eq("http://a_website.com") end - it 'marks as having errors if a non-accpted scheme is provided' do - nonprofit_with_bad_email_and_website.update(website: 'ftp://invalid.com') - expect(nonprofit_with_bad_email_and_website.errors['website'].first) - .to match('is not a valid URL') + it "marks as having errors if a non-accpted scheme is provided" do + nonprofit_with_bad_email_and_website.update(website: "ftp://invalid.com") + expect(nonprofit_with_bad_email_and_website.errors["website"].first) + .to match("is not a valid URL") expect(nonprofit_with_bad_email_and_website.website) - .to eq('ftp://invalid.com') + .to eq("ftp://invalid.com") end - it 'marks as having errors if an array is provided' do + it "marks as having errors if an array is provided" do nonprofit_with_bad_email_and_website.update(website: []) - expect(nonprofit_with_bad_email_and_website.errors['website'].first) - .to match('is not a valid URL') + expect(nonprofit_with_bad_email_and_website.errors["website"].first) + .to match("is not a valid URL") expect(nonprofit_with_bad_email_and_website.website) .to eq("[]") end - it 'marks as having errors if there is a space in the website string' do - nonprofit_with_bad_email_and_website.update(website: 'invalid .com') - expect(nonprofit_with_bad_email_and_website.errors['website'].first) - .to match('is not a valid URL') + it "marks as having errors if there is a space in the website string" do + nonprofit_with_bad_email_and_website.update(website: "invalid .com") + expect(nonprofit_with_bad_email_and_website.errors["website"].first) + .to match("is not a valid URL") expect(nonprofit_with_bad_email_and_website.website) - .to eq('invalid .com') + .to eq("invalid .com") end - it 'marks as having errors if a number is provided' do + it "marks as having errors if a number is provided" do nonprofit_with_bad_email_and_website.update(website: 1234) - expect(nonprofit_with_bad_email_and_website.errors['website'].first) - .to match('is not a valid URL') + expect(nonprofit_with_bad_email_and_website.errors["website"].first) + .to match("is not a valid URL") expect(nonprofit_with_bad_email_and_website.website) .to eq("1234") end - it 'marks as having errors if a hash is provided' do + it "marks as having errors if a hash is provided" do nonprofit_with_bad_email_and_website.update(website: {}) - expect(nonprofit_with_bad_email_and_website.errors['website'].first) - .to match('is not a valid URL') + expect(nonprofit_with_bad_email_and_website.errors["website"].first) + .to match("is not a valid URL") expect(nonprofit_with_bad_email_and_website.website) .to eq("{}") end end - it 'marks an nonprofit as invalid when no slug could be created ' do + it "marks an nonprofit as invalid when no slug could be created " do nonprofit = Nonprofit.new({name: nm_justice.name, city: nm_justice.city, state_code: nm_justice.state_code, slug: nm_justice.slug}) expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new) nonprofit.valid? - expect(nonprofit.errors['slug'].first).to match /.*could not be created.*/ + expect(nonprofit.errors["slug"].first).to match(/.*could not be created.*/) end - describe 'timezone validations' do - it 'does not fail if the timezone is nil' do + describe "timezone validations" do + it "does not fail if the timezone is nil" do expect { create(:nm_justice, timezone: nil) }.not_to raise_error(ActiveRecord::RecordInvalid) end - it 'does not fail if the timezone is readable by postgres' do - expect { create(:nm_justice, timezone: 'America/Chicago') }.not_to raise_error(ActiveRecord::RecordInvalid) + it "does not fail if the timezone is readable by postgres" do + expect { create(:nm_justice, timezone: "America/Chicago") }.not_to raise_error(ActiveRecord::RecordInvalid) end - it 'raises error if the timezone is invalid' do - expect { create(:nm_justice, timezone: 'Central Time (US & Canada)') }.to raise_error(ActiveRecord::RecordInvalid) + it "raises error if the timezone is invalid" do + expect { create(:nm_justice, timezone: "Central Time (US & Canada)") }.to raise_error(ActiveRecord::RecordInvalid) end end end diff --git a/spec/models/object_event_hook_config_spec.rb b/spec/models/object_event_hook_config_spec.rb index 6a628191bf..886cfa2319 100644 --- a/spec/models/object_event_hook_config_spec.rb +++ b/spec/models/object_event_hook_config_spec.rb @@ -2,29 +2,34 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe ObjectEventHookConfig, type: :model do let(:nonprofit) { create(:nm_justice) } let(:open_fn_config) { create(:open_fn_config, nonprofit_id: nonprofit.id) } - describe 'validation' do - subject{ oehc = ObjectEventHookConfig.new(object_event_types:[]); oehc.validate; oehc} + describe "validation" do + subject { + oehc = ObjectEventHookConfig.new(object_event_types: []) + oehc.validate + oehc + } - it 'has an error for webhook_service missing' do + it "has an error for webhook_service missing" do expect(subject.errors[:webhook_service]).to_not be_nil end - it 'has an error for configuraiton missing' do + it "has an error for configuraiton missing" do expect(subject.errors[:configuration]).to_not be_nil end - it 'has an error for configuraition empty' do + it "has an error for configuraition empty" do expect(subject.errors[:object_event_types]).to_not be_empty end end - describe '.webhook' do - it 'returns an instance of OpenFn webhook' do + + describe ".webhook" do + it "returns an instance of OpenFn webhook" do webhook = double expect(Houdini::WebhookAdapter) .to receive(:build) diff --git a/spec/models/offline_transaction_charge_spec.rb b/spec/models/offline_transaction_charge_spec.rb index 7edee510ee..619b3a25a8 100644 --- a/spec/models/offline_transaction_charge_spec.rb +++ b/spec/models/offline_transaction_charge_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe OfflineTransactionCharge do - pending "add some examples to (or delete) #{__FILE__}" + pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/models/offline_transaction_dispute_spec.rb b/spec/models/offline_transaction_dispute_spec.rb index 64ad1a8e23..7a51377b33 100644 --- a/spec/models/offline_transaction_dispute_spec.rb +++ b/spec/models/offline_transaction_dispute_spec.rb @@ -2,268 +2,268 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe OfflineTransactionDispute do - let!(:nonprofit) { create(:nm_justice) } - let!(:supporter) { force_create(:supporter, nonprofit: nonprofit) } + let!(:nonprofit) { create(:nm_justice) } + let!(:supporter) { force_create(:supporter, nonprofit: nonprofit) } - let(:offline_transaction_dispute) do - build( - :offline_transaction_dispute, - payment: - force_create( - :payment, - gross_amount: 500, - net_amount: 400, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - ) - end - let(:offline_transaction_charge) do - build( - :offline_transaction_charge, - payment: - force_create( - :payment, - gross_amount: 400, - net_amount: 300, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - ) - end + let(:offline_transaction_dispute) do + build( + :offline_transaction_dispute, + payment: + force_create( + :payment, + gross_amount: 500, + net_amount: 400, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + ) + end + let(:offline_transaction_charge) do + build( + :offline_transaction_charge, + payment: + force_create( + :payment, + gross_amount: 400, + net_amount: 300, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + ) + end - let(:offline_transaction) { build(:offline_transaction) } - let(:transaction) do - trx = supporter.transactions.build(amount: 500) - trx.build_subtransaction( - subtransactable: OfflineTransaction.new(amount: 500), - payments: [ - build(:subtransaction_payment, paymentable: offline_transaction_dispute), - build(:subtransaction_payment, paymentable: offline_transaction_charge) - ] - ) - trx.save! - trx - end + let(:offline_transaction) { build(:offline_transaction) } + let(:transaction) do + trx = supporter.transactions.build(amount: 500) + trx.build_subtransaction( + subtransactable: OfflineTransaction.new(amount: 500), + payments: [ + build(:subtransaction_payment, paymentable: offline_transaction_dispute), + build(:subtransaction_payment, paymentable: offline_transaction_charge) + ] + ) + trx.save! + trx + end - let(:event_publisher) { double } + let(:event_publisher) { double } - let(:expected_event) do - { - 'data' => { - 'object' => { - 'created' => kind_of(Numeric), - 'fee_total' => { 'cents' => 100, 'currency' => nonprofit.currency }, - 'gross_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'id' => match_houid('offtrxdspt'), - 'net_amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'offline_transaction_dispute', - 'subtransaction' => { - 'created' => kind_of(Numeric), - 'id' => match_houid('offlinetrx'), - 'initial_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'net_amount' => { 'cents' => 700, 'currency' => nonprofit.currency }, - 'nonprofit' => nonprofit.id, - 'object' => 'offline_transaction', - 'payments' => [ - { - 'id' => match_houid('offtrxdspt'), - 'object' => 'offline_transaction_dispute', - 'type' => 'payment' - }, { - 'id' => match_houid('offtrxchrg'), - 'object' => 'offline_transaction_charge', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'subtransaction' - }, - 'supporter' => { - 'anonymous' => false, - 'deleted' => false, - 'id' => supporter.id, - 'merged_into' => nil, - 'name' => supporter.name, - 'nonprofit' => kind_of(Numeric), - 'object' => 'supporter', - 'organization' => nil, - 'phone' => nil, - 'supporter_addresses' => [kind_of(Numeric)] - }, - 'transaction' => { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'created' => kind_of(Numeric), - 'id' => match_houid('trx'), - 'nonprofit' => kind_of(Numeric), - 'object' => 'transaction', - 'subtransaction' => { - 'id' => match_houid('offlinetrx'), - 'object' => 'offline_transaction', - 'type' => 'subtransaction' - }, - 'payments' => [ - { - 'id' => match_houid('offtrxdspt'), - 'object' => 'offline_transaction_dispute', - 'type' => 'payment' - }, { - 'id' => match_houid('offtrxchrg'), - 'object' => 'offline_transaction_charge', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction_assignments' => [] - }, - 'type' => 'payment' - } - }, - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'event_type' - } - end + let(:expected_event) do + { + "data" => { + "object" => { + "created" => kind_of(Numeric), + "fee_total" => {"cents" => 100, "currency" => nonprofit.currency}, + "gross_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "id" => match_houid("offtrxdspt"), + "net_amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "offline_transaction_dispute", + "subtransaction" => { + "created" => kind_of(Numeric), + "id" => match_houid("offlinetrx"), + "initial_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "net_amount" => {"cents" => 700, "currency" => nonprofit.currency}, + "nonprofit" => nonprofit.id, + "object" => "offline_transaction", + "payments" => [ + { + "id" => match_houid("offtrxdspt"), + "object" => "offline_transaction_dispute", + "type" => "payment" + }, { + "id" => match_houid("offtrxchrg"), + "object" => "offline_transaction_charge", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "subtransaction" + }, + "supporter" => { + "anonymous" => false, + "deleted" => false, + "id" => supporter.id, + "merged_into" => nil, + "name" => supporter.name, + "nonprofit" => kind_of(Numeric), + "object" => "supporter", + "organization" => nil, + "phone" => nil, + "supporter_addresses" => [kind_of(Numeric)] + }, + "transaction" => { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "created" => kind_of(Numeric), + "id" => match_houid("trx"), + "nonprofit" => kind_of(Numeric), + "object" => "transaction", + "subtransaction" => { + "id" => match_houid("offlinetrx"), + "object" => "offline_transaction", + "type" => "subtransaction" + }, + "payments" => [ + { + "id" => match_houid("offtrxdspt"), + "object" => "offline_transaction_dispute", + "type" => "payment" + }, { + "id" => match_houid("offtrxchrg"), + "object" => "offline_transaction_charge", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction_assignments" => [] + }, + "type" => "payment" + } + }, + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "event_type" + } + end - before do - allow(Houdini) - .to receive(:event_publisher) - .and_return(event_publisher) - transaction - end + before do + allow(Houdini) + .to receive(:event_publisher) + .and_return(event_publisher) + transaction + end - describe 'offline transaction dispute' do - subject { offline_transaction_dispute } + describe "offline transaction dispute" do + subject { offline_transaction_dispute } - it do - is_expected - .to have_attributes( - nonprofit: an_instance_of(Nonprofit), - id: match_houid('offtrxdspt') - ) - end + it do + is_expected + .to have_attributes( + nonprofit: an_instance_of(Nonprofit), + id: match_houid("offtrxdspt") + ) + end - it { is_expected.to be_persisted } - end + it { is_expected.to be_persisted } + end - describe '.to_builder' do - subject { JSON.parse(offline_transaction_dispute.to_builder.target!) } + describe ".to_builder" do + subject { JSON.parse(offline_transaction_dispute.to_builder.target!) } - it do - is_expected - .to match_json( - { - object: 'offline_transaction_dispute', - nonprofit: kind_of(Numeric), - supporter: kind_of(Numeric), - id: match_houid('offtrxdspt'), - type: 'payment', - fee_total: { cents: 100, currency: nonprofit.currency }, - net_amount: { cents: 400, currency: nonprofit.currency }, - gross_amount: { cents: 500, currency: nonprofit.currency }, - created: kind_of(Numeric), - subtransaction: { - id: match_houid('offlinetrx'), - object: 'offline_transaction', - type: 'subtransaction' - }, - transaction: match_houid('trx') - } - ) - end - end + it do + is_expected + .to match_json( + { + object: "offline_transaction_dispute", + nonprofit: kind_of(Numeric), + supporter: kind_of(Numeric), + id: match_houid("offtrxdspt"), + type: "payment", + fee_total: {cents: 100, currency: nonprofit.currency}, + net_amount: {cents: 400, currency: nonprofit.currency}, + gross_amount: {cents: 500, currency: nonprofit.currency}, + created: kind_of(Numeric), + subtransaction: { + id: match_houid("offlinetrx"), + object: "offline_transaction", + type: "subtransaction" + }, + transaction: match_houid("trx") + } + ) + end + end - describe '.publish_created' do - before do - expected_event['type'] = 'offline_transaction_dispute.created' + describe ".publish_created" do + before do + expected_event["type"] = "offline_transaction_dispute.created" - allow(event_publisher) - .to receive(:announce) - .with(:payment_created, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :offline_transaction_dispute_created, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_created, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :offline_transaction_dispute_created, + expected_event + ) + end - it 'announces offline_transaction_dispute.created event' do - offline_transaction_dispute.publish_created + it "announces offline_transaction_dispute.created event" do + offline_transaction_dispute.publish_created - expect(event_publisher) - .to have_received(:announce) - .with( - :offline_transaction_dispute_created, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :offline_transaction_dispute_created, + expected_event + ) + end + end - describe '.publish_updated' do - before do - expected_event['type'] = 'offline_transaction_dispute.updated' + describe ".publish_updated" do + before do + expected_event["type"] = "offline_transaction_dispute.updated" - allow(event_publisher) - .to receive(:announce) - .with(:payment_updated, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :offline_transaction_dispute_updated, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_updated, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :offline_transaction_dispute_updated, + expected_event + ) + end - it 'announces offline_transaction_dispute.updated event' do - offline_transaction_dispute.publish_updated + it "announces offline_transaction_dispute.updated event" do + offline_transaction_dispute.publish_updated - expect(event_publisher) - .to have_received(:announce) - .with( - :offline_transaction_dispute_updated, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :offline_transaction_dispute_updated, + expected_event + ) + end + end - describe '.publish_deleted' do - before do - expected_event['type'] = 'offline_transaction_dispute.deleted' + describe ".publish_deleted" do + before do + expected_event["type"] = "offline_transaction_dispute.deleted" - allow(event_publisher) - .to receive(:announce) - .with(:payment_deleted, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :offline_transaction_dispute_deleted, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_deleted, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :offline_transaction_dispute_deleted, + expected_event + ) + end - it 'announces offline_transaction_dispute.deleted event' do - offline_transaction_dispute.publish_deleted + it "announces offline_transaction_dispute.deleted event" do + offline_transaction_dispute.publish_deleted - expect(event_publisher) - .to have_received(:announce) - .with( - :offline_transaction_dispute_deleted, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :offline_transaction_dispute_deleted, + expected_event + ) + end + end end diff --git a/spec/models/offline_transaction_refund_spec.rb b/spec/models/offline_transaction_refund_spec.rb index 5cc5bdca6d..ade646f753 100644 --- a/spec/models/offline_transaction_refund_spec.rb +++ b/spec/models/offline_transaction_refund_spec.rb @@ -2,268 +2,268 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe OfflineTransactionRefund do - let!(:nonprofit) { create(:nm_justice) } - let!(:supporter) { force_create(:supporter, nonprofit: nonprofit) } + let!(:nonprofit) { create(:nm_justice) } + let!(:supporter) { force_create(:supporter, nonprofit: nonprofit) } - let(:offline_transaction_refund) do - build( - :offline_transaction_refund, - payment: - force_create( - :payment, - gross_amount: 500, - net_amount: 400, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - ) - end - let(:offline_transaction_charge) do - build( - :offline_transaction_charge, - payment: - force_create( - :payment, - gross_amount: 400, - net_amount: 300, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - ) - end + let(:offline_transaction_refund) do + build( + :offline_transaction_refund, + payment: + force_create( + :payment, + gross_amount: 500, + net_amount: 400, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + ) + end + let(:offline_transaction_charge) do + build( + :offline_transaction_charge, + payment: + force_create( + :payment, + gross_amount: 400, + net_amount: 300, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + ) + end - let(:offline_transaction) { build(:offline_transaction) } - let(:transaction) do - trx = supporter.transactions.build(amount: 500) - trx.build_subtransaction( - subtransactable: OfflineTransaction.new(amount: 500), - payments: [ - build(:subtransaction_payment, paymentable: offline_transaction_refund), - build(:subtransaction_payment, paymentable: offline_transaction_charge) - ] - ) - trx.save! - trx - end + let(:offline_transaction) { build(:offline_transaction) } + let(:transaction) do + trx = supporter.transactions.build(amount: 500) + trx.build_subtransaction( + subtransactable: OfflineTransaction.new(amount: 500), + payments: [ + build(:subtransaction_payment, paymentable: offline_transaction_refund), + build(:subtransaction_payment, paymentable: offline_transaction_charge) + ] + ) + trx.save! + trx + end - let(:event_publisher) { double } + let(:event_publisher) { double } - let(:expected_event) do - { - 'data' => { - 'object' => { - 'created' => kind_of(Numeric), - 'fee_total' => { 'cents' => 100, 'currency' => nonprofit.currency }, - 'gross_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'id' => match_houid('offtrxrfnd'), - 'net_amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'offline_transaction_refund', - 'subtransaction' => { - 'created' => kind_of(Numeric), - 'id' => match_houid('offlinetrx'), - 'initial_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'net_amount' => { 'cents' => 700, 'currency' => nonprofit.currency }, - 'nonprofit' => nonprofit.id, - 'object' => 'offline_transaction', - 'payments' => [ - { - 'id' => match_houid('offtrxrfnd'), - 'object' => 'offline_transaction_refund', - 'type' => 'payment' - }, { - 'id' => match_houid('offtrxchrg'), - 'object' => 'offline_transaction_charge', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'subtransaction' - }, - 'supporter' => { - 'anonymous' => false, - 'deleted' => false, - 'id' => supporter.id, - 'merged_into' => nil, - 'name' => supporter.name, - 'nonprofit' => kind_of(Numeric), - 'object' => 'supporter', - 'organization' => nil, - 'phone' => nil, - 'supporter_addresses' => [kind_of(Numeric)] - }, - 'transaction' => { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'created' => kind_of(Numeric), - 'id' => match_houid('trx'), - 'nonprofit' => kind_of(Numeric), - 'object' => 'transaction', - 'subtransaction' => { - 'id' => match_houid('offlinetrx'), - 'object' => 'offline_transaction', - 'type' => 'subtransaction' - }, - 'payments' => [ - { - 'id' => match_houid('offtrxrfnd'), - 'object' => 'offline_transaction_refund', - 'type' => 'payment' - }, { - 'id' => match_houid('offtrxchrg'), - 'object' => 'offline_transaction_charge', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction_assignments' => [] - }, - 'type' => 'payment' - } - }, - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'event_type' - } - end + let(:expected_event) do + { + "data" => { + "object" => { + "created" => kind_of(Numeric), + "fee_total" => {"cents" => 100, "currency" => nonprofit.currency}, + "gross_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "id" => match_houid("offtrxrfnd"), + "net_amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "offline_transaction_refund", + "subtransaction" => { + "created" => kind_of(Numeric), + "id" => match_houid("offlinetrx"), + "initial_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "net_amount" => {"cents" => 700, "currency" => nonprofit.currency}, + "nonprofit" => nonprofit.id, + "object" => "offline_transaction", + "payments" => [ + { + "id" => match_houid("offtrxrfnd"), + "object" => "offline_transaction_refund", + "type" => "payment" + }, { + "id" => match_houid("offtrxchrg"), + "object" => "offline_transaction_charge", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "subtransaction" + }, + "supporter" => { + "anonymous" => false, + "deleted" => false, + "id" => supporter.id, + "merged_into" => nil, + "name" => supporter.name, + "nonprofit" => kind_of(Numeric), + "object" => "supporter", + "organization" => nil, + "phone" => nil, + "supporter_addresses" => [kind_of(Numeric)] + }, + "transaction" => { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "created" => kind_of(Numeric), + "id" => match_houid("trx"), + "nonprofit" => kind_of(Numeric), + "object" => "transaction", + "subtransaction" => { + "id" => match_houid("offlinetrx"), + "object" => "offline_transaction", + "type" => "subtransaction" + }, + "payments" => [ + { + "id" => match_houid("offtrxrfnd"), + "object" => "offline_transaction_refund", + "type" => "payment" + }, { + "id" => match_houid("offtrxchrg"), + "object" => "offline_transaction_charge", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction_assignments" => [] + }, + "type" => "payment" + } + }, + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "event_type" + } + end - before do - allow(Houdini) - .to receive(:event_publisher) - .and_return(event_publisher) - transaction - end + before do + allow(Houdini) + .to receive(:event_publisher) + .and_return(event_publisher) + transaction + end - describe 'offline transaction refund' do - subject { offline_transaction_refund } + describe "offline transaction refund" do + subject { offline_transaction_refund } - it do - is_expected - .to have_attributes( - nonprofit: an_instance_of(Nonprofit), - id: match_houid('offtrxrfnd') - ) - end + it do + is_expected + .to have_attributes( + nonprofit: an_instance_of(Nonprofit), + id: match_houid("offtrxrfnd") + ) + end - it { is_expected.to be_persisted } - end + it { is_expected.to be_persisted } + end - describe '.to_builder' do - subject { JSON.parse(offline_transaction_refund.to_builder.target!) } + describe ".to_builder" do + subject { JSON.parse(offline_transaction_refund.to_builder.target!) } - it do - is_expected - .to match_json( - { - object: 'offline_transaction_refund', - nonprofit: kind_of(Numeric), - supporter: kind_of(Numeric), - id: match_houid('offtrxrfnd'), - type: 'payment', - fee_total: { cents: 100, currency: nonprofit.currency }, - net_amount: { cents: 400, currency: nonprofit.currency }, - gross_amount: { cents: 500, currency: nonprofit.currency }, - created: kind_of(Numeric), - subtransaction: { - id: match_houid('offlinetrx'), - object: 'offline_transaction', - type: 'subtransaction' - }, - transaction: match_houid('trx') - } - ) - end - end + it do + is_expected + .to match_json( + { + object: "offline_transaction_refund", + nonprofit: kind_of(Numeric), + supporter: kind_of(Numeric), + id: match_houid("offtrxrfnd"), + type: "payment", + fee_total: {cents: 100, currency: nonprofit.currency}, + net_amount: {cents: 400, currency: nonprofit.currency}, + gross_amount: {cents: 500, currency: nonprofit.currency}, + created: kind_of(Numeric), + subtransaction: { + id: match_houid("offlinetrx"), + object: "offline_transaction", + type: "subtransaction" + }, + transaction: match_houid("trx") + } + ) + end + end - describe '.publish_created' do - before do - expected_event['type'] = 'offline_transaction_refund.created' + describe ".publish_created" do + before do + expected_event["type"] = "offline_transaction_refund.created" - allow(event_publisher) - .to receive(:announce) - .with(:payment_created, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :offline_transaction_refund_created, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_created, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :offline_transaction_refund_created, + expected_event + ) + end - it 'announces offline_transaction_refund.created event' do - offline_transaction_refund.publish_created + it "announces offline_transaction_refund.created event" do + offline_transaction_refund.publish_created - expect(event_publisher) - .to have_received(:announce) - .with( - :offline_transaction_refund_created, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :offline_transaction_refund_created, + expected_event + ) + end + end - describe '.publish_updated' do - before do - expected_event['type'] = 'offline_transaction_refund.updated' + describe ".publish_updated" do + before do + expected_event["type"] = "offline_transaction_refund.updated" - allow(event_publisher) - .to receive(:announce) - .with(:payment_updated, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :offline_transaction_refund_updated, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_updated, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :offline_transaction_refund_updated, + expected_event + ) + end - it 'announces offline_transaction_refund.updated event' do - offline_transaction_refund.publish_updated + it "announces offline_transaction_refund.updated event" do + offline_transaction_refund.publish_updated - expect(event_publisher) - .to have_received(:announce) - .with( - :offline_transaction_refund_updated, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :offline_transaction_refund_updated, + expected_event + ) + end + end - describe '.publish_deleted' do - before do - expected_event['type'] = 'offline_transaction_refund.deleted' + describe ".publish_deleted" do + before do + expected_event["type"] = "offline_transaction_refund.deleted" - allow(event_publisher) - .to receive(:announce) - .with(:payment_deleted, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :offline_transaction_refund_deleted, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_deleted, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :offline_transaction_refund_deleted, + expected_event + ) + end - it 'announces offline_transaction_refund.deleted event' do - offline_transaction_refund.publish_deleted + it "announces offline_transaction_refund.deleted event" do + offline_transaction_refund.publish_deleted - expect(event_publisher) - .to have_received(:announce) - .with( - :offline_transaction_refund_deleted, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :offline_transaction_refund_deleted, + expected_event + ) + end + end end diff --git a/spec/models/offline_transaction_spec.rb b/spec/models/offline_transaction_spec.rb index cfa39a5783..7c880a2753 100644 --- a/spec/models/offline_transaction_spec.rb +++ b/spec/models/offline_transaction_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe OfflineTransaction do - pending "add some examples to (or delete) #{__FILE__}" + pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/models/payment_import_spec.rb b/spec/models/payment_import_spec.rb index 16952abe8a..d7767f9c4b 100644 --- a/spec/models/payment_import_spec.rb +++ b/spec/models/payment_import_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe PaymentImport, type: :model do pending "add some examples to (or delete) #{__FILE__}" diff --git a/spec/models/recurrence_spec.rb b/spec/models/recurrence_spec.rb index 042308c506..fef21717e5 100644 --- a/spec/models/recurrence_spec.rb +++ b/spec/models/recurrence_spec.rb @@ -2,301 +2,301 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Recurrence do - around do |example| - Timecop.freeze(2020, 5, 4) do - example.run - end - end - - describe 'recurrence with donations, designation and dedication' do - subject { create(:recurrence) } - - def trx_assignment_match - { - assignment_object: 'donation', - amount: 500, - dedication: { - contact: { - email: 'email@ema.com' - }, - name: 'our loved one', - note: 'we miss them dearly', - type: 'memory' - }, - designation: 'designated for soup kitchen' - } - end - - def trx_assignment_json - trx_assignment_match.merge({ amount: { cents: 500, currency: 'usd' } }) - end - - def invoice_template_match - { - - amount: 500, - supporter: an_instance_of(Supporter), - payment_method: { - type: 'stripe' - }, - trx_assignments: [trx_assignment_match] - } - end - - def invoice_template_json - invoice_template_match.merge(trx_assignments: [trx_assignment_json]).deep_stringify_keys - end - - it { - is_expected.to have_attributes( - supporter: an_instance_of(Supporter), - nonprofit: an_instance_of(Nonprofit), - start_date: Time.current, - id: match_houid('recur') - ) - } - - it { - is_expected.to have_attributes(recurrences: contain_exactly( - { - start: Time.current.beginning_of_day, - interval: 1, - type: 'monthly' - } - )) - } - - it { is_expected.to be_persisted } - - it do - is_expected.to have_attributes( - invoice_template: invoice_template_match - ) - end - - describe '.to_builder' do - subject { JSON.parse(recurrence.to_builder.target!) } - - let(:recurrence) { create(:recurrence) } - let(:invoice_template) { subject['invoice_template'] } - - it do # rubocop:disable RSpec/ExampleLength - is_expected.to match_json( - { - object: 'recurrence', - nonprofit: kind_of(Numeric), - supporter: kind_of(Numeric), - id: match_houid('recur'), - start_date: Time.current.to_i, - recurrences: [ - { - start: Time.new(2020, 5, 4).to_i, - interval: 1, - type: 'monthly' - } - ], - invoice_template: { - supporter: kind_of(Numeric), - amount: { 'cents' => 500, 'currency' => 'usd' }, - payment_method: { 'type' => 'stripe' }, - trx_assignments: [trx_assignment_json] - } - } - ) - end - end - end - - describe 'recurrence_with_paydate_later_in_month' do - subject { create(:recurrence_with_paydate_later_in_month) } - - def trx_assignment_match - { - assignment_object: 'donation', - amount: 500, - dedication: { - contact: { - email: 'email@ema.com' - }, - name: 'our loved one', - note: 'we miss them dearly', - type: 'memory' - }, - designation: 'designated for soup kitchen' - } - end - - def trx_assignment_json - trx_assignment_match.merge({ amount: { cents: 500, currency: 'usd' } }) - end - - def invoice_template_match - { - - amount: 500, - supporter: an_instance_of(Supporter), - payment_method: { - type: 'stripe' - }, - trx_assignments: [trx_assignment_match] - } - end - - def invoice_template_json - invoice_template_match.merge(trx_assignments: [trx_assignment_json]).deep_stringify_keys - end - - it { - is_expected.to have_attributes( - supporter: an_instance_of(Supporter), - nonprofit: an_instance_of(Nonprofit), - start_date: Time.current, - id: match_houid('recur') - ) - } - - it { - is_expected.to have_attributes(recurrences: contain_exactly( - { - start: Time.new(2020, 5, 5).utc, - interval: 1, - type: 'monthly' - } - )) - } - - it { is_expected.to be_persisted } - - it do - is_expected.to have_attributes( - invoice_template: invoice_template_match - ) - end - - describe '.to_builder' do - subject { JSON.parse(recurrence.to_builder.target!) } - - let(:recurrence) { create(:recurrence_with_paydate_later_in_month) } - let(:invoice_template) { subject['invoice_template'] } - - it do - is_expected.to match_json({ - object: 'recurrence', - nonprofit: kind_of(Numeric), - supporter: kind_of(Numeric), - id: match_houid('recur'), - start_date: Time.current.to_i, - recurrences: [ - { - start: Time.new(2020, 5, 5).to_i, - interval: 1, - type: 'monthly' - } - ], - invoice_template: { supporter: kind_of(Numeric), - amount: { 'cents' => 500, 'currency' => 'usd' }, - payment_method: { 'type' => 'stripe' }, - trx_assignments: [trx_assignment_json] } - }) - end - end - end - - describe 'recurrence_with_paydate_earlier_in_month' do - subject { create(:recurrence_with_paydate_earlier_in_month) } - - def trx_assignment_match - { - assignment_object: 'donation', - amount: 500, - dedication: { - contact: { - email: 'email@ema.com' - }, - name: 'our loved one', - note: 'we miss them dearly', - type: 'memory' - }, - designation: 'designated for soup kitchen' - } - end - - def trx_assignment_json - trx_assignment_match.merge({ amount: { cents: 500, currency: 'usd' } }) - end - - def invoice_template_match - { - - amount: 500, - supporter: an_instance_of(Supporter), - payment_method: { - type: 'stripe' - }, - trx_assignments: [trx_assignment_match] - } - end - - def invoice_template_json - invoice_template_match.merge(trx_assignments: [trx_assignment_json]).deep_stringify_keys - end - - it { - is_expected.to have_attributes( - supporter: an_instance_of(Supporter), - nonprofit: an_instance_of(Nonprofit), - start_date: Time.current, - id: match_houid('recur') - ) - } - - it { - is_expected.to have_attributes(recurrences: contain_exactly( - { - start: Time.new(2020, 6, 3).utc, - interval: 1, - type: 'monthly' - } - )) - } - - it { is_expected.to be_persisted } - - it do - is_expected.to have_attributes( - invoice_template: invoice_template_match - ) - end - - describe '.to_builder' do - subject { JSON.parse(recurrence.to_builder.target!) } - - let(:recurrence) { create(:recurrence_with_paydate_earlier_in_month) } - let(:invoice_template) { subject['invoice_template'] } - - it do - is_expected.to match_json({ - object: 'recurrence', - nonprofit: kind_of(Numeric), - supporter: kind_of(Numeric), - id: match_houid('recur'), - start_date: Time.current.to_i, - recurrences: [ - { - start: Time.new(2020, 6, 3).to_i, - interval: 1, - type: 'monthly' - } - ], - invoice_template: { supporter: kind_of(Numeric), - amount: { 'cents' => 500, 'currency' => 'usd' }, - payment_method: { 'type' => 'stripe' }, - trx_assignments: [trx_assignment_json] } - }) - end - end - end + around do |example| + Timecop.freeze(2020, 5, 4) do + example.run + end + end + + describe "recurrence with donations, designation and dedication" do + subject { create(:recurrence) } + + def trx_assignment_match + { + assignment_object: "donation", + amount: 500, + dedication: { + contact: { + email: "email@ema.com" + }, + name: "our loved one", + note: "we miss them dearly", + type: "memory" + }, + designation: "designated for soup kitchen" + } + end + + def trx_assignment_json + trx_assignment_match.merge({amount: {cents: 500, currency: "usd"}}) + end + + def invoice_template_match + { + + amount: 500, + supporter: an_instance_of(Supporter), + payment_method: { + type: "stripe" + }, + trx_assignments: [trx_assignment_match] + } + end + + def invoice_template_json + invoice_template_match.merge(trx_assignments: [trx_assignment_json]).deep_stringify_keys + end + + it { + is_expected.to have_attributes( + supporter: an_instance_of(Supporter), + nonprofit: an_instance_of(Nonprofit), + start_date: Time.current, + id: match_houid("recur") + ) + } + + it { + is_expected.to have_attributes(recurrences: contain_exactly( + { + start: Time.current.beginning_of_day, + interval: 1, + type: "monthly" + } + )) + } + + it { is_expected.to be_persisted } + + it do + is_expected.to have_attributes( + invoice_template: invoice_template_match + ) + end + + describe ".to_builder" do + subject { JSON.parse(recurrence.to_builder.target!) } + + let(:recurrence) { create(:recurrence) } + let(:invoice_template) { subject["invoice_template"] } + + it do # rubocop:disable RSpec/ExampleLength + is_expected.to match_json( + { + object: "recurrence", + nonprofit: kind_of(Numeric), + supporter: kind_of(Numeric), + id: match_houid("recur"), + start_date: Time.current.to_i, + recurrences: [ + { + start: Time.new(2020, 5, 4).to_i, + interval: 1, + type: "monthly" + } + ], + invoice_template: { + supporter: kind_of(Numeric), + amount: {"cents" => 500, "currency" => "usd"}, + payment_method: {"type" => "stripe"}, + trx_assignments: [trx_assignment_json] + } + } + ) + end + end + end + + describe "recurrence_with_paydate_later_in_month" do + subject { create(:recurrence_with_paydate_later_in_month) } + + def trx_assignment_match + { + assignment_object: "donation", + amount: 500, + dedication: { + contact: { + email: "email@ema.com" + }, + name: "our loved one", + note: "we miss them dearly", + type: "memory" + }, + designation: "designated for soup kitchen" + } + end + + def trx_assignment_json + trx_assignment_match.merge({amount: {cents: 500, currency: "usd"}}) + end + + def invoice_template_match + { + + amount: 500, + supporter: an_instance_of(Supporter), + payment_method: { + type: "stripe" + }, + trx_assignments: [trx_assignment_match] + } + end + + def invoice_template_json + invoice_template_match.merge(trx_assignments: [trx_assignment_json]).deep_stringify_keys + end + + it { + is_expected.to have_attributes( + supporter: an_instance_of(Supporter), + nonprofit: an_instance_of(Nonprofit), + start_date: Time.current, + id: match_houid("recur") + ) + } + + it { + is_expected.to have_attributes(recurrences: contain_exactly( + { + start: Time.new(2020, 5, 5).utc, + interval: 1, + type: "monthly" + } + )) + } + + it { is_expected.to be_persisted } + + it do + is_expected.to have_attributes( + invoice_template: invoice_template_match + ) + end + + describe ".to_builder" do + subject { JSON.parse(recurrence.to_builder.target!) } + + let(:recurrence) { create(:recurrence_with_paydate_later_in_month) } + let(:invoice_template) { subject["invoice_template"] } + + it do + is_expected.to match_json({ + object: "recurrence", + nonprofit: kind_of(Numeric), + supporter: kind_of(Numeric), + id: match_houid("recur"), + start_date: Time.current.to_i, + recurrences: [ + { + start: Time.new(2020, 5, 5).to_i, + interval: 1, + type: "monthly" + } + ], + invoice_template: {supporter: kind_of(Numeric), + amount: {"cents" => 500, "currency" => "usd"}, + payment_method: {"type" => "stripe"}, + trx_assignments: [trx_assignment_json]} + }) + end + end + end + + describe "recurrence_with_paydate_earlier_in_month" do + subject { create(:recurrence_with_paydate_earlier_in_month) } + + def trx_assignment_match + { + assignment_object: "donation", + amount: 500, + dedication: { + contact: { + email: "email@ema.com" + }, + name: "our loved one", + note: "we miss them dearly", + type: "memory" + }, + designation: "designated for soup kitchen" + } + end + + def trx_assignment_json + trx_assignment_match.merge({amount: {cents: 500, currency: "usd"}}) + end + + def invoice_template_match + { + + amount: 500, + supporter: an_instance_of(Supporter), + payment_method: { + type: "stripe" + }, + trx_assignments: [trx_assignment_match] + } + end + + def invoice_template_json + invoice_template_match.merge(trx_assignments: [trx_assignment_json]).deep_stringify_keys + end + + it { + is_expected.to have_attributes( + supporter: an_instance_of(Supporter), + nonprofit: an_instance_of(Nonprofit), + start_date: Time.current, + id: match_houid("recur") + ) + } + + it { + is_expected.to have_attributes(recurrences: contain_exactly( + { + start: Time.new(2020, 6, 3).utc, + interval: 1, + type: "monthly" + } + )) + } + + it { is_expected.to be_persisted } + + it do + is_expected.to have_attributes( + invoice_template: invoice_template_match + ) + end + + describe ".to_builder" do + subject { JSON.parse(recurrence.to_builder.target!) } + + let(:recurrence) { create(:recurrence_with_paydate_earlier_in_month) } + let(:invoice_template) { subject["invoice_template"] } + + it do + is_expected.to match_json({ + object: "recurrence", + nonprofit: kind_of(Numeric), + supporter: kind_of(Numeric), + id: match_houid("recur"), + start_date: Time.current.to_i, + recurrences: [ + { + start: Time.new(2020, 6, 3).to_i, + interval: 1, + type: "monthly" + } + ], + invoice_template: {supporter: kind_of(Numeric), + amount: {"cents" => 500, "currency" => "usd"}, + payment_method: {"type" => "stripe"}, + trx_assignments: [trx_assignment_json]} + }) + end + end + end end diff --git a/spec/models/stripe_charge_spec.rb b/spec/models/stripe_charge_spec.rb index 6ef7ec9f5e..0d70072f85 100644 --- a/spec/models/stripe_charge_spec.rb +++ b/spec/models/stripe_charge_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe StripeCharge do - pending "add some examples to (or delete) #{__FILE__}" + pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/models/stripe_dispute_spec.rb b/spec/models/stripe_dispute_spec.rb index 6553e95429..efbf5dc391 100644 --- a/spec/models/stripe_dispute_spec.rb +++ b/spec/models/stripe_dispute_spec.rb @@ -2,270 +2,270 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe StripeDispute do - let!(:nonprofit) { create(:nm_justice) } - let!(:supporter) { create(:supporter, nonprofit: nonprofit) } - let!(:payment) do - force_create( - :payment, - gross_amount: 500, - net_amount: 400, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - end + let!(:nonprofit) { create(:nm_justice) } + let!(:supporter) { create(:supporter, nonprofit: nonprofit) } + let!(:payment) do + force_create( + :payment, + gross_amount: 500, + net_amount: 400, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + end - let(:stripe_transaction_charge) do - build( - :stripe_charge, - payment: - force_create( - :payment, - gross_amount: 500, - net_amount: 400, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - ) - end + let(:stripe_transaction_charge) do + build( + :stripe_charge, + payment: + force_create( + :payment, + gross_amount: 500, + net_amount: 400, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + ) + end - let!(:stripe_transaction_dispute) do - build( - :stripe_dispute, - payment: payment - ) - end + let!(:stripe_transaction_dispute) do + build( + :stripe_dispute, + payment: payment + ) + end - let(:transaction) do - trx = supporter.transactions.build(amount: 500) - trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: 500), - payments: [ - build(:subtransaction_payment, paymentable: stripe_transaction_charge), - build(:subtransaction_payment, paymentable: stripe_transaction_dispute) - ] - ) - trx.save! - trx - end + let(:transaction) do + trx = supporter.transactions.build(amount: 500) + trx.build_subtransaction( + subtransactable: StripeTransaction.new(amount: 500), + payments: [ + build(:subtransaction_payment, paymentable: stripe_transaction_charge), + build(:subtransaction_payment, paymentable: stripe_transaction_dispute) + ] + ) + trx.save! + trx + end - let(:event_publisher) { double } + let(:event_publisher) { double } - let(:expected_event) do - { - 'data' => { - 'object' => { - 'created' => kind_of(Numeric), - 'fee_total' => { 'cents' => 100, 'currency' => nonprofit.currency }, - 'gross_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'id' => match_houid('stripedisp'), - 'stripe_id' => kind_of(String), - 'net_amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'stripe_transaction_dispute', - 'subtransaction' => { - 'created' => kind_of(Numeric), - 'id' => match_houid('stripetrx'), - 'initial_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'net_amount' => { 'cents' => 800, 'currency' => nonprofit.currency }, - 'nonprofit' => nonprofit.id, - 'object' => 'stripe_transaction', - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, - { - 'id' => match_houid('stripedisp'), - 'object' => 'stripe_transaction_dispute', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'subtransaction' - }, - 'supporter' => { - 'anonymous' => supporter.anonymous, - 'deleted' => supporter.deleted, - 'id' => supporter.id, - 'merged_into' => supporter.merged_into, - 'name' => supporter.name, - 'nonprofit' => nonprofit.id, - 'object' => 'supporter', - 'organization' => supporter.organization, - 'phone' => supporter.phone, - 'supporter_addresses' => [kind_of(Numeric)] - }, - 'transaction' => { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'created' => kind_of(Numeric), - 'id' => match_houid('trx'), - 'nonprofit' => nonprofit.id, - 'object' => 'transaction', - 'subtransaction' => { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - }, - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, { - 'id' => match_houid('stripedisp'), - 'object' => 'stripe_transaction_dispute', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction_assignments' => [] - }, - 'type' => 'payment' - } - }, - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'event_type' - } - end + let(:expected_event) do + { + "data" => { + "object" => { + "created" => kind_of(Numeric), + "fee_total" => {"cents" => 100, "currency" => nonprofit.currency}, + "gross_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "id" => match_houid("stripedisp"), + "stripe_id" => kind_of(String), + "net_amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "stripe_transaction_dispute", + "subtransaction" => { + "created" => kind_of(Numeric), + "id" => match_houid("stripetrx"), + "initial_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "net_amount" => {"cents" => 800, "currency" => nonprofit.currency}, + "nonprofit" => nonprofit.id, + "object" => "stripe_transaction", + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, + { + "id" => match_houid("stripedisp"), + "object" => "stripe_transaction_dispute", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "subtransaction" + }, + "supporter" => { + "anonymous" => supporter.anonymous, + "deleted" => supporter.deleted, + "id" => supporter.id, + "merged_into" => supporter.merged_into, + "name" => supporter.name, + "nonprofit" => nonprofit.id, + "object" => "supporter", + "organization" => supporter.organization, + "phone" => supporter.phone, + "supporter_addresses" => [kind_of(Numeric)] + }, + "transaction" => { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "created" => kind_of(Numeric), + "id" => match_houid("trx"), + "nonprofit" => nonprofit.id, + "object" => "transaction", + "subtransaction" => { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + }, + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, { + "id" => match_houid("stripedisp"), + "object" => "stripe_transaction_dispute", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction_assignments" => [] + }, + "type" => "payment" + } + }, + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "event_type" + } + end - before do - allow(Houdini) - .to receive(:event_publisher) - .and_return(event_publisher) - force_create(:dispute, payment: payment, stripe_dispute_id: 'some_id') - transaction - end + before do + allow(Houdini) + .to receive(:event_publisher) + .and_return(event_publisher) + force_create(:dispute, payment: payment, stripe_dispute_id: "some_id") + transaction + end - describe 'stripe transaction dispute' do - subject { stripe_transaction_dispute } + describe "stripe transaction dispute" do + subject { stripe_transaction_dispute } - it do - is_expected - .to have_attributes( - nonprofit: an_instance_of(Nonprofit), - id: match_houid('stripedisp') - ) - end + it do + is_expected + .to have_attributes( + nonprofit: an_instance_of(Nonprofit), + id: match_houid("stripedisp") + ) + end - it { is_expected.to be_persisted } - end + it { is_expected.to be_persisted } + end - describe '.to_builder' do - subject { JSON.parse(stripe_transaction_dispute.to_builder.target!) } + describe ".to_builder" do + subject { JSON.parse(stripe_transaction_dispute.to_builder.target!) } - it do - is_expected - .to match_json( - { - object: 'stripe_transaction_dispute', - nonprofit: nonprofit.id, - supporter: supporter.id, - id: match_houid('stripedisp'), - stripe_id: kind_of(String), - type: 'payment', - fee_total: { cents: 100, currency: nonprofit.currency }, - net_amount: { cents: 400, currency: nonprofit.currency }, - gross_amount: { cents: 500, currency: nonprofit.currency }, - created: kind_of(Numeric), - subtransaction: { id: match_houid('stripetrx'), object: 'stripe_transaction', type: 'subtransaction' }, - transaction: match_houid('trx') - } - ) - end - end + it do + is_expected + .to match_json( + { + object: "stripe_transaction_dispute", + nonprofit: nonprofit.id, + supporter: supporter.id, + id: match_houid("stripedisp"), + stripe_id: kind_of(String), + type: "payment", + fee_total: {cents: 100, currency: nonprofit.currency}, + net_amount: {cents: 400, currency: nonprofit.currency}, + gross_amount: {cents: 500, currency: nonprofit.currency}, + created: kind_of(Numeric), + subtransaction: {id: match_houid("stripetrx"), object: "stripe_transaction", type: "subtransaction"}, + transaction: match_houid("trx") + } + ) + end + end - describe '.publish_created' do - before do - expected_event['type'] = 'stripe_transaction_dispute.created' + describe ".publish_created" do + before do + expected_event["type"] = "stripe_transaction_dispute.created" - allow(event_publisher) - .to receive(:announce) - .with(:payment_created, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :stripe_transaction_dispute_created, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_created, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :stripe_transaction_dispute_created, + expected_event + ) + end - it 'announces stripe_transaction_dispute.created event' do - stripe_transaction_dispute.publish_created + it "announces stripe_transaction_dispute.created event" do + stripe_transaction_dispute.publish_created - expect(event_publisher) - .to have_received(:announce) - .with( - :stripe_transaction_dispute_created, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :stripe_transaction_dispute_created, + expected_event + ) + end + end - describe '.publish_updated' do - before do - expected_event['type'] = 'stripe_transaction_dispute.updated' + describe ".publish_updated" do + before do + expected_event["type"] = "stripe_transaction_dispute.updated" - allow(event_publisher) - .to receive(:announce) - .with(:payment_updated, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :stripe_transaction_dispute_updated, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_updated, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :stripe_transaction_dispute_updated, + expected_event + ) + end - it 'announces stripe_transaction_dispute.updated event' do - stripe_transaction_dispute.publish_updated + it "announces stripe_transaction_dispute.updated event" do + stripe_transaction_dispute.publish_updated - expect(event_publisher) - .to have_received(:announce) - .with( - :stripe_transaction_dispute_updated, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :stripe_transaction_dispute_updated, + expected_event + ) + end + end - describe '.publish_deleted' do - before do - expected_event['type'] = 'stripe_transaction_dispute.deleted' + describe ".publish_deleted" do + before do + expected_event["type"] = "stripe_transaction_dispute.deleted" - allow(event_publisher) - .to receive(:announce) - .with(:payment_deleted, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :stripe_transaction_dispute_deleted, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_deleted, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :stripe_transaction_dispute_deleted, + expected_event + ) + end - it 'announces stripe_transaction_dispute.deleted event' do - stripe_transaction_dispute.publish_deleted + it "announces stripe_transaction_dispute.deleted event" do + stripe_transaction_dispute.publish_deleted - expect(event_publisher) - .to have_received(:announce) - .with( - :stripe_transaction_dispute_deleted, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :stripe_transaction_dispute_deleted, + expected_event + ) + end + end end diff --git a/spec/models/stripe_refund_spec.rb b/spec/models/stripe_refund_spec.rb index 46c04451c0..bf54f80b81 100644 --- a/spec/models/stripe_refund_spec.rb +++ b/spec/models/stripe_refund_spec.rb @@ -2,270 +2,270 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe StripeRefund do - let!(:nonprofit) { create(:nm_justice) } - let!(:supporter) { create(:supporter, nonprofit: nonprofit) } - let!(:payment) do - force_create( - :payment, - gross_amount: 500, - net_amount: 400, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - end + let!(:nonprofit) { create(:nm_justice) } + let!(:supporter) { create(:supporter, nonprofit: nonprofit) } + let!(:payment) do + force_create( + :payment, + gross_amount: 500, + net_amount: 400, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + end - let(:stripe_charge) do - build( - :stripe_charge, - payment: - force_create( - :payment, - gross_amount: 500, - net_amount: 400, - fee_total: 100, - date: Time.zone.now, - nonprofit: nonprofit, - supporter: supporter - ) - ) - end + let(:stripe_charge) do + build( + :stripe_charge, + payment: + force_create( + :payment, + gross_amount: 500, + net_amount: 400, + fee_total: 100, + date: Time.zone.now, + nonprofit: nonprofit, + supporter: supporter + ) + ) + end - let!(:stripe_transaction_refund) do - build( - :stripe_refund, - payment: payment - ) - end + let!(:stripe_transaction_refund) do + build( + :stripe_refund, + payment: payment + ) + end - let(:transaction) do - trx = supporter.transactions.build(amount: 500) - trx.build_subtransaction( - subtransactable: StripeTransaction.new(amount: 500), - payments: [ - build(:subtransaction_payment, paymentable: stripe_charge), - build(:subtransaction_payment, paymentable: stripe_transaction_refund) - ] - ) - trx.save! - trx - end + let(:transaction) do + trx = supporter.transactions.build(amount: 500) + trx.build_subtransaction( + subtransactable: StripeTransaction.new(amount: 500), + payments: [ + build(:subtransaction_payment, paymentable: stripe_charge), + build(:subtransaction_payment, paymentable: stripe_transaction_refund) + ] + ) + trx.save! + trx + end - let(:event_publisher) { double } + let(:event_publisher) { double } - let(:expected_event) do - { - 'data' => { - 'object' => { - 'created' => kind_of(Numeric), - 'fee_total' => { 'cents' => 100, 'currency' => nonprofit.currency }, - 'gross_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'id' => match_houid('striperef'), - 'stripe_id' => kind_of(String), - 'net_amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'stripe_transaction_refund', - 'subtransaction' => { - 'created' => kind_of(Numeric), - 'id' => match_houid('stripetrx'), - 'initial_amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'net_amount' => { 'cents' => 800, 'currency' => nonprofit.currency }, - 'nonprofit' => nonprofit.id, - 'object' => 'stripe_transaction', - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, - { - 'id' => match_houid('striperef'), - 'object' => 'stripe_transaction_refund', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction' => match_houid('trx'), - 'type' => 'subtransaction' - }, - 'supporter' => { - 'anonymous' => supporter.anonymous, - 'deleted' => supporter.deleted, - 'id' => supporter.id, - 'merged_into' => supporter.merged_into, - 'name' => supporter.name, - 'nonprofit' => nonprofit.id, - 'object' => 'supporter', - 'organization' => supporter.organization, - 'phone' => supporter.phone, - 'supporter_addresses' => [kind_of(Numeric)] - }, - 'transaction' => { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'created' => kind_of(Numeric), - 'id' => match_houid('trx'), - 'nonprofit' => nonprofit.id, - 'object' => 'transaction', - 'subtransaction' => { - 'id' => match_houid('stripetrx'), - 'object' => 'stripe_transaction', - 'type' => 'subtransaction' - }, - 'payments' => [ - { - 'id' => match_houid('stripechrg'), - 'object' => 'stripe_transaction_charge', - 'type' => 'payment' - }, { - 'id' => match_houid('striperef'), - 'object' => 'stripe_transaction_refund', - 'type' => 'payment' - } - ], - 'supporter' => supporter.id, - 'transaction_assignments' => [] - }, - 'type' => 'payment' - } - }, - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'event_type' - } - end + let(:expected_event) do + { + "data" => { + "object" => { + "created" => kind_of(Numeric), + "fee_total" => {"cents" => 100, "currency" => nonprofit.currency}, + "gross_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "id" => match_houid("striperef"), + "stripe_id" => kind_of(String), + "net_amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "stripe_transaction_refund", + "subtransaction" => { + "created" => kind_of(Numeric), + "id" => match_houid("stripetrx"), + "initial_amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "net_amount" => {"cents" => 800, "currency" => nonprofit.currency}, + "nonprofit" => nonprofit.id, + "object" => "stripe_transaction", + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, + { + "id" => match_houid("striperef"), + "object" => "stripe_transaction_refund", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction" => match_houid("trx"), + "type" => "subtransaction" + }, + "supporter" => { + "anonymous" => supporter.anonymous, + "deleted" => supporter.deleted, + "id" => supporter.id, + "merged_into" => supporter.merged_into, + "name" => supporter.name, + "nonprofit" => nonprofit.id, + "object" => "supporter", + "organization" => supporter.organization, + "phone" => supporter.phone, + "supporter_addresses" => [kind_of(Numeric)] + }, + "transaction" => { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "created" => kind_of(Numeric), + "id" => match_houid("trx"), + "nonprofit" => nonprofit.id, + "object" => "transaction", + "subtransaction" => { + "id" => match_houid("stripetrx"), + "object" => "stripe_transaction", + "type" => "subtransaction" + }, + "payments" => [ + { + "id" => match_houid("stripechrg"), + "object" => "stripe_transaction_charge", + "type" => "payment" + }, { + "id" => match_houid("striperef"), + "object" => "stripe_transaction_refund", + "type" => "payment" + } + ], + "supporter" => supporter.id, + "transaction_assignments" => [] + }, + "type" => "payment" + } + }, + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "event_type" + } + end - before do - allow(Houdini) - .to receive(:event_publisher) - .and_return(event_publisher) - force_create(:refund, payment: payment, disbursed: true, stripe_refund_id: 'some_id') - transaction - end + before do + allow(Houdini) + .to receive(:event_publisher) + .and_return(event_publisher) + force_create(:refund, payment: payment, disbursed: true, stripe_refund_id: "some_id") + transaction + end - describe 'stripe transaction refund' do - subject { stripe_transaction_refund } + describe "stripe transaction refund" do + subject { stripe_transaction_refund } - it do - is_expected - .to have_attributes( - nonprofit: an_instance_of(Nonprofit), - id: match_houid('striperef') - ) - end + it do + is_expected + .to have_attributes( + nonprofit: an_instance_of(Nonprofit), + id: match_houid("striperef") + ) + end - it { is_expected.to be_persisted } - end + it { is_expected.to be_persisted } + end - describe '.to_builder' do - subject { JSON.parse(stripe_transaction_refund.to_builder.target!) } + describe ".to_builder" do + subject { JSON.parse(stripe_transaction_refund.to_builder.target!) } - it do - is_expected - .to match_json( - { - object: 'stripe_transaction_refund', - nonprofit: nonprofit.id, - supporter: supporter.id, - id: match_houid('striperef'), - stripe_id: kind_of(String), - type: 'payment', - fee_total: { cents: 100, currency: nonprofit.currency }, - net_amount: { cents: 400, currency: nonprofit.currency }, - gross_amount: { cents: 500, currency: nonprofit.currency }, - created: kind_of(Numeric), - subtransaction: { id: match_houid('stripetrx'), object: 'stripe_transaction', type: 'subtransaction' }, - transaction: match_houid('trx') - } - ) - end - end + it do + is_expected + .to match_json( + { + object: "stripe_transaction_refund", + nonprofit: nonprofit.id, + supporter: supporter.id, + id: match_houid("striperef"), + stripe_id: kind_of(String), + type: "payment", + fee_total: {cents: 100, currency: nonprofit.currency}, + net_amount: {cents: 400, currency: nonprofit.currency}, + gross_amount: {cents: 500, currency: nonprofit.currency}, + created: kind_of(Numeric), + subtransaction: {id: match_houid("stripetrx"), object: "stripe_transaction", type: "subtransaction"}, + transaction: match_houid("trx") + } + ) + end + end - describe '.publish_created' do - before do - expected_event['type'] = 'stripe_transaction_refund.created' + describe ".publish_created" do + before do + expected_event["type"] = "stripe_transaction_refund.created" - allow(event_publisher) - .to receive(:announce) - .with(:payment_created, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :stripe_transaction_refund_created, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_created, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :stripe_transaction_refund_created, + expected_event + ) + end - it 'announces stripe_transaction_refund.created event' do - stripe_transaction_refund.publish_created + it "announces stripe_transaction_refund.created event" do + stripe_transaction_refund.publish_created - expect(event_publisher) - .to have_received(:announce) - .with( - :stripe_transaction_refund_created, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :stripe_transaction_refund_created, + expected_event + ) + end + end - describe '.publish_updated' do - before do - expected_event['type'] = 'stripe_transaction_refund.updated' + describe ".publish_updated" do + before do + expected_event["type"] = "stripe_transaction_refund.updated" - allow(event_publisher) - .to receive(:announce) - .with(:payment_updated, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :stripe_transaction_refund_updated, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_updated, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :stripe_transaction_refund_updated, + expected_event + ) + end - it 'announces stripe_transaction_refund.updated event' do - stripe_transaction_refund.publish_updated + it "announces stripe_transaction_refund.updated event" do + stripe_transaction_refund.publish_updated - expect(event_publisher) - .to have_received(:announce) - .with( - :stripe_transaction_refund_updated, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :stripe_transaction_refund_updated, + expected_event + ) + end + end - describe '.publish_deleted' do - before do - expected_event['type'] = 'stripe_transaction_refund.deleted' + describe ".publish_deleted" do + before do + expected_event["type"] = "stripe_transaction_refund.deleted" - allow(event_publisher) - .to receive(:announce) - .with(:payment_deleted, anything) - allow(event_publisher) - .to receive(:announce) - .with( - :stripe_transaction_refund_deleted, - expected_event - ) - end + allow(event_publisher) + .to receive(:announce) + .with(:payment_deleted, anything) + allow(event_publisher) + .to receive(:announce) + .with( + :stripe_transaction_refund_deleted, + expected_event + ) + end - it 'announces stripe_transaction_refund.deleted event' do - stripe_transaction_refund.publish_deleted + it "announces stripe_transaction_refund.deleted event" do + stripe_transaction_refund.publish_deleted - expect(event_publisher) - .to have_received(:announce) - .with( - :stripe_transaction_refund_deleted, - expected_event - ) - end - end + expect(event_publisher) + .to have_received(:announce) + .with( + :stripe_transaction_refund_deleted, + expected_event + ) + end + end end diff --git a/spec/models/stripe_transaction_spec.rb b/spec/models/stripe_transaction_spec.rb index fd2d8bd802..7f9ebeff23 100644 --- a/spec/models/stripe_transaction_spec.rb +++ b/spec/models/stripe_transaction_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe StripeTransaction do - pending "add some examples to (or delete) #{__FILE__}" + pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/models/subtransaction_payment_spec.rb b/spec/models/subtransaction_payment_spec.rb index e6b73da7d0..017e7183fd 100644 --- a/spec/models/subtransaction_payment_spec.rb +++ b/spec/models/subtransaction_payment_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe SubtransactionPayment do - pending "add some examples to (or delete) #{__FILE__}" + pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/models/subtransaction_spec.rb b/spec/models/subtransaction_spec.rb index 5aab8f28c8..bf6d359e78 100644 --- a/spec/models/subtransaction_spec.rb +++ b/spec/models/subtransaction_spec.rb @@ -2,8 +2,8 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Subtransaction do - pending "add some examples to (or delete) #{__FILE__}" + pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/models/supporter_note_spec.rb b/spec/models/supporter_note_spec.rb index dd2ecae467..b04dec0752 100644 --- a/spec/models/supporter_note_spec.rb +++ b/spec/models/supporter_note_spec.rb @@ -2,124 +2,124 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" # rubocop:disable RSpec/MessageSpies # rubocop:disable RSpec/ExampleLength # rubocop:disable RSpec/MultipleExpectations RSpec.describe SupporterNote do - include_context :shared_donation_charge_context - let(:content) { 'CONTENT' } - let(:content2) { 'CONTENT2' } + include_context :shared_donation_charge_context + let(:content) { "CONTENT" } + let(:content2) { "CONTENT2" } - let(:supporter_note) { supporter.supporter_notes.create(content: content, user: user) } + let(:supporter_note) { supporter.supporter_notes.create(content: content, user: user) } - it 'creates' do - expect(supporter_note.errors).to be_empty - end + it "creates" do + expect(supporter_note.errors).to be_empty + end - it 'announces created' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) - expect(Houdini.event_publisher).to receive(:announce).with( - :supporter_note_created, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'supporter_note.created', - 'data' => { - 'object' => { - 'id' => kind_of(Numeric), - 'deleted' => false, - 'content' => content, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'supporter_note', - 'user' => { - 'id' => user.id, - 'object' => 'user' - }, - 'supporter' => supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - } - } - } - ) + it "announces created" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) + expect(Houdini.event_publisher).to receive(:announce).with( + :supporter_note_created, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "supporter_note.created", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => false, + "content" => content, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "supporter_note", + "user" => { + "id" => user.id, + "object" => "user" + }, + "supporter" => supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + } + } + } + ) - supporter_note - end + supporter_note + end - it 'announces updated' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_note_created, anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with( - :supporter_note_updated, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'supporter_note.updated', - 'data' => { - 'object' => { - 'id' => kind_of(Numeric), - 'deleted' => false, - 'content' => content2, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'supporter_note', - 'user' => { - 'id' => user.id, - 'object' => 'user' - }, - 'supporter' => supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - } - } - } - ).ordered + it "announces updated" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_note_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with( + :supporter_note_updated, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "supporter_note.updated", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => false, + "content" => content2, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "supporter_note", + "user" => { + "id" => user.id, + "object" => "user" + }, + "supporter" => supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + } + } + } + ).ordered - supporter_note - supporter_note.content = content2 - supporter_note.save! - end + supporter_note + supporter_note.content = content2 + supporter_note.save! + end - it 'announces deleted' do - allow(Houdini.event_publisher) - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_note_created, anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with( - :supporter_note_deleted, - { - 'id' => match_houid('objevt'), - 'object' => 'object_event', - 'type' => 'supporter_note.deleted', - 'data' => { - 'object' => { - 'id' => kind_of(Numeric), - 'deleted' => true, - 'content' => content, - 'nonprofit' => { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }, - 'object' => 'supporter_note', - 'user' => { - 'id' => user.id, - 'object' => 'user' - }, - 'supporter' => supporter_to_builder_base.merge({ 'name' => 'Fake Supporter Name' }) - } - } - } - ).ordered + it "announces deleted" do + allow(Houdini.event_publisher) + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything) + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything) + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_note_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with( + :supporter_note_deleted, + { + "id" => match_houid("objevt"), + "object" => "object_event", + "type" => "supporter_note.deleted", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => true, + "content" => content, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "object" => "supporter_note", + "user" => { + "id" => user.id, + "object" => "user" + }, + "supporter" => supporter_to_builder_base.merge({"name" => "Fake Supporter Name"}) + } + } + } + ).ordered - supporter_note.discard! - end + supporter_note.discard! + end end # rubocop:enable all diff --git a/spec/models/supporter_spec.rb b/spec/models/supporter_spec.rb index bbc8dc4ab2..33ff295ee7 100644 --- a/spec/models/supporter_spec.rb +++ b/spec/models/supporter_spec.rb @@ -2,161 +2,159 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Supporter, type: :model do - include_context :shared_donation_charge_context - let(:supporter_name) {"CUSTOM SSUPPORTER"} - let(:merged_into_supporter_name) {"I've been merged into!"} - let(:address) { "address for supporter"} - let(:supporter) { nonprofit.supporters.create(name: supporter_name, address: address)} - let(:merged_supporter) {nonprofit.supporters.create(name: supporter_name, address: address, merged_into: merged_into_supporter, deleted: true) } - let(:merged_into_supporter) {nonprofit.supporters.create(name: merged_into_supporter_name, address: address) } - - describe 'supporter' do - it 'created' do - - supporter_result = supporter_to_builder_base.merge({ - 'supporter_addresses' => [ - supporter_address_to_builder_base - ], - 'nonprofit' => nonprofit_to_builder_base - }) - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'supporter.created', - 'data' => { - 'object' => supporter_result + include_context :shared_donation_charge_context + let(:supporter_name) { "CUSTOM SSUPPORTER" } + let(:merged_into_supporter_name) { "I've been merged into!" } + let(:address) { "address for supporter" } + let(:supporter) { nonprofit.supporters.create(name: supporter_name, address: address) } + let(:merged_supporter) { nonprofit.supporters.create(name: supporter_name, address: address, merged_into: merged_into_supporter, deleted: true) } + let(:merged_into_supporter) { nonprofit.supporters.create(name: merged_into_supporter_name, address: address) } + + describe "supporter" do + it "created" do + supporter_result = supporter_to_builder_base.merge({ + "supporter_addresses" => [ + supporter_address_to_builder_base + ], + "nonprofit" => nonprofit_to_builder_base + }) + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, { + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "supporter.created", + "data" => { + "object" => supporter_result } - }).ordered - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered + }).ordered + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered supporter - end - - it 'deletes' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created,anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered - expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated) - expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated) - - supporter_result = supporter_to_builder_base.merge({ - 'deleted' => true, - 'supporter_addresses' => [ - supporter_address_to_builder_base.merge({'deleted' => true}) - ], - 'nonprofit' => nonprofit_to_builder_base - }) - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'supporter.deleted', - 'data' => { - 'object' => supporter_result + end + + it "deletes" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered + expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated) + expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated) + + supporter_result = supporter_to_builder_base.merge({ + "deleted" => true, + "supporter_addresses" => [ + supporter_address_to_builder_base.merge({"deleted" => true}) + ], + "nonprofit" => nonprofit_to_builder_base + }) + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_deleted, { + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "supporter.deleted", + "data" => { + "object" => supporter_result } - }).ordered - - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_deleted,anything).ordered - - supporter.discard! - end - end - - describe 'supporter_address events' do - it 'creates' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'supporter_address.created', - 'data' => { - 'object' => supporter_address_to_builder_base.merge({ - 'supporter' => supporter_to_builder_base, - 'nonprofit' => nonprofit_to_builder_base - }) - } - }).ordered - - supporter - end - - it 'deletes' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created,anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered - expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated) - expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated) - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_deleted, anything) - - - supporter_address_result = supporter_address_to_builder_base.merge({ - 'deleted' => true, - 'supporter'=> supporter_to_builder_base.merge({'deleted' => true}), - 'nonprofit' => nonprofit_to_builder_base - }) - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'supporter_address.deleted', - 'data' => { - 'object' => supporter_address_result + }).ordered + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_deleted, anything).ordered + + supporter.discard! + end + end + + describe "supporter_address events" do + it "creates" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, { + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "supporter_address.created", + "data" => { + "object" => supporter_address_to_builder_base.merge({ + "supporter" => supporter_to_builder_base, + "nonprofit" => nonprofit_to_builder_base + }) } - }).ordered - - - supporter.discard! - end - end - - describe 'supporter and supporter_address events update events are separate' do - it 'only fires supporter on supporter only change' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'supporter.updated', - 'data' => { - 'object' => supporter_to_builder_base.merge({ - 'name' => merged_into_supporter_name, - 'supporter_addresses' => [ - supporter_address_to_builder_base - ], - 'nonprofit' => nonprofit_to_builder_base - }) - - }}).ordered - expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated, anything) - - supporter.update(name: merged_into_supporter_name) - end - - it 'only fires supporter_address on supporter_address only change' do - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered - - expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'supporter_address.updated', - 'data' => { - 'object' => supporter_address_to_builder_base.merge({ - 'city' => 'new_city', - 'supporter'=> supporter_to_builder_base, - 'nonprofit' => nonprofit_to_builder_base - }) - }}).ordered - - #expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated, anything) - - supporter.update(city: 'new_city') - end - end -end \ No newline at end of file + }).ordered + + supporter + end + + it "deletes" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered + expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated) + expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated) + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_deleted, anything) + + supporter_address_result = supporter_address_to_builder_base.merge({ + "deleted" => true, + "supporter" => supporter_to_builder_base.merge({"deleted" => true}), + "nonprofit" => nonprofit_to_builder_base + }) + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_deleted, { + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "supporter_address.deleted", + "data" => { + "object" => supporter_address_result + } + }).ordered + + supporter.discard! + end + end + + describe "supporter and supporter_address events update events are separate" do + it "only fires supporter on supporter only change" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_updated, { + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "supporter.updated", + "data" => { + "object" => supporter_to_builder_base.merge({ + "name" => merged_into_supporter_name, + "supporter_addresses" => [ + supporter_address_to_builder_base + ], + "nonprofit" => nonprofit_to_builder_base + }) + + } + }).ordered + expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_address_updated, anything) + + supporter.update(name: merged_into_supporter_name) + end + + it "only fires supporter_address on supporter_address only change" do + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_created, anything).ordered + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_created, anything).ordered + + expect(Houdini.event_publisher).to receive(:announce).with(:supporter_address_updated, { + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "supporter_address.updated", + "data" => { + "object" => supporter_address_to_builder_base.merge({ + "city" => "new_city", + "supporter" => supporter_to_builder_base, + "nonprofit" => nonprofit_to_builder_base + }) + } + }).ordered + + # expect(Houdini.event_publisher).to_not receive(:announce).with(:supporter_updated, anything) + + supporter.update(city: "new_city") + end + end +end diff --git a/spec/models/tag_definition_spec.rb b/spec/models/tag_definition_spec.rb index b00400209c..ec4d626529 100644 --- a/spec/models/tag_definition_spec.rb +++ b/spec/models/tag_definition_spec.rb @@ -2,61 +2,61 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe TagDefinition, type: :model do include_context :shared_donation_charge_context - let(:name) { "TAGNAME"} + let(:name) { "TAGNAME" } let(:tag_definition) { nonprofit.tag_definitions.create(name: name) } - let(:np_builder_expanded) { { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - }} - it 'creates' do + let(:np_builder_expanded) { + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } + } + + it "creates" do expect(tag_definition.errors).to be_empty end - - - it 'announces create' do + it "announces create" do expect(Houdini.event_publisher).to receive(:announce).with(:tag_definition_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'tag_definition.created', - 'data' => { - 'object' => { - 'id'=> kind_of(Numeric), - 'deleted' => false, - 'name' => name, - 'nonprofit'=> np_builder_expanded, - 'object' => 'tag_definition' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "tag_definition.created", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => false, + "name" => name, + "nonprofit" => np_builder_expanded, + "object" => "tag_definition" } } }) tag_definition end - - it 'announces deleted' do + + it "announces deleted" do expect(Houdini.event_publisher).to receive(:announce).with(:tag_definition_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:tag_definition_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'tag_definition.deleted', - 'data' => { - 'object' => { - 'id'=> kind_of(Numeric), - 'deleted' => true, - 'name' => name, - 'nonprofit'=> np_builder_expanded, - 'object' => 'tag_definition' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "tag_definition.deleted", + "data" => { + "object" => { + "id" => kind_of(Numeric), + "deleted" => true, + "name" => name, + "nonprofit" => np_builder_expanded, + "object" => "tag_definition" } } }).ordered - - tag_definition.discard! + tag_definition.discard! end end diff --git a/spec/models/ticket_level_spec.rb b/spec/models/ticket_level_spec.rb index de16fcc0f7..3e0fd5ad4e 100644 --- a/spec/models/ticket_level_spec.rb +++ b/spec/models/ticket_level_spec.rb @@ -2,115 +2,114 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe TicketLevel, type: :model do include_context :shared_donation_charge_context - let(:ticket_level_name) {"TICKET LEVEL"} - let(:order) { 3} - let(:free_amount) { 0} - let(:non_free_amount) {7500} - let(:ticket_limit) {4} - let(:description) {"Description"} + let(:ticket_level_name) { "TICKET LEVEL" } + let(:order) { 3 } + let(:free_amount) { 0 } + let(:non_free_amount) { 7500 } + let(:ticket_limit) { 4 } + let(:description) { "Description" } - - let(:ticket_level_1) { event.ticket_levels.create( - name: ticket_level_name, - limit: ticket_limit, - admin_only: true, - order: order, - amount: free_amount, - description: description - - ) } + let(:ticket_level_1) { + event.ticket_levels.create( + name: ticket_level_name, + limit: ticket_limit, + admin_only: true, + order: order, + amount: free_amount, + description: description + ) + } let(:ticket_level_2) { event.ticket_levels.create( - name: ticket_level_name, + name: ticket_level_name, limit: nil, admin_only: false, order: order, amount: non_free_amount, description: description - ) } - describe 'create' do - describe 'ticket_level_1' do - it 'is without error' do + describe "create" do + describe "ticket_level_1" do + it "is without error" do expect(ticket_level_1.errors).to be_empty end - it 'announces create' do + it "announces create" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'ticket_level.created', - 'data' => { - 'object' => { - 'amount' => {'cents' => 0, 'currency' => 'usd'}, - 'available_to' => 'admins', - 'deleted' => false, - 'description' => description, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'limit' => 4, - 'name' => ticket_level_name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "ticket_level.created", + "data" => { + "object" => { + "amount" => {"cents" => 0, "currency" => "usd"}, + "available_to" => "admins", + "deleted" => false, + "description" => description, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id + }, + "id" => kind_of(Numeric), + "limit" => 4, + "name" => ticket_level_name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'event_discounts' => [], - 'object' => 'ticket_level', - 'order' => order + "event_discounts" => [], + "object" => "ticket_level", + "order" => order } } }) ticket_level_1 end - end - describe 'ticket_level_2' do - it 'is without error' do + + describe "ticket_level_2" do + it "is without error" do expect(ticket_level_2.errors).to be_empty end - it 'announces create' do + it "announces create" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'ticket_level.created', - 'data' => { - 'object' => { - 'amount' => {'cents' => non_free_amount, 'currency' => 'usd'}, - 'available_to' => 'everyone', - 'deleted' => false, - 'description' => description, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'limit' => nil, - 'name' => ticket_level_name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "ticket_level.created", + "data" => { + "object" => { + "amount" => {"cents" => non_free_amount, "currency" => "usd"}, + "available_to" => "everyone", + "deleted" => false, + "description" => description, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id }, - 'event_discounts' => [], - 'object' => 'ticket_level', - 'order' => order + "id" => kind_of(Numeric), + "limit" => nil, + "name" => ticket_level_name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + }, + "event_discounts" => [], + "object" => "ticket_level", + "order" => order } } }) @@ -120,43 +119,43 @@ end end - describe 'update' do - describe 'ticket_level_1' do - it 'is without error' do + describe "update" do + describe "ticket_level_1" do + it "is without error" do ticket_level_1.amount = 5000 ticket_level_1.save expect(ticket_level_1.errors).to be_empty end - it 'announces updated' do + it "announces updated" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'ticket_level.updated', - 'data' => { - 'object' => { - 'amount' => {'cents' => 5000, 'currency' => 'usd'}, - 'available_to' => 'admins', - 'deleted' => false, - 'description' => description, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'limit' => 4, - 'name' => ticket_level_name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "ticket_level.updated", + "data" => { + "object" => { + "amount" => {"cents" => 5000, "currency" => "usd"}, + "available_to" => "admins", + "deleted" => false, + "description" => description, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id + }, + "id" => kind_of(Numeric), + "limit" => 4, + "name" => ticket_level_name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'event_discounts' => [], - 'object' => 'ticket_level', - 'order' => order + "event_discounts" => [], + "object" => "ticket_level", + "order" => order } } }) @@ -165,44 +164,44 @@ ticket_level_1.amount = 5000 ticket_level_1.save end - end - describe 'ticket_level_2' do - it 'is without error' do + + describe "ticket_level_2" do + it "is without error" do ticket_level_2.amount = 0 ticket_level_2.save expect(ticket_level_2.errors).to be_empty end - it 'announces updated' do + it "announces updated" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_updated, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'ticket_level.updated', - 'data' => { - 'object' => { - 'amount' => {'cents' => 0, 'currency' => 'usd'}, - 'available_to' => 'everyone', - 'deleted' => false, - 'description' => description, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'limit' => nil, - 'name' => ticket_level_name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "ticket_level.updated", + "data" => { + "object" => { + "amount" => {"cents" => 0, "currency" => "usd"}, + "available_to" => "everyone", + "deleted" => false, + "description" => description, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id + }, + "id" => kind_of(Numeric), + "limit" => nil, + "name" => ticket_level_name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'event_discounts' => [], - 'object' => 'ticket_level', - 'order' => order + "event_discounts" => [], + "object" => "ticket_level", + "order" => order } } }) @@ -214,86 +213,84 @@ end end - - describe 'deleted' do - describe 'ticket_level_1' do - it 'is without error' do - + describe "deleted" do + describe "ticket_level_1" do + it "is without error" do ticket_level_1.discard! - expect(ticket_level_1.deleted).to eq true + expect(ticket_level_1.deleted).to eq true end - it 'announces deleted' do + it "announces deleted" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'ticket_level.deleted', - 'data' => { - 'object' => { - 'amount' => {'cents' => 0, 'currency' => 'usd'}, - 'available_to' => 'admins', - 'deleted' => true, - 'description' => description, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'limit' => 4, - 'name' => ticket_level_name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "ticket_level.deleted", + "data" => { + "object" => { + "amount" => {"cents" => 0, "currency" => "usd"}, + "available_to" => "admins", + "deleted" => true, + "description" => description, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id + }, + "id" => kind_of(Numeric), + "limit" => 4, + "name" => ticket_level_name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'event_discounts' => [], - 'object' => 'ticket_level', - 'order' => order + "event_discounts" => [], + "object" => "ticket_level", + "order" => order } } }).ordered ticket_level_1.discard! end - end - describe 'ticket_level_2' do - it 'is without error' do + + describe "ticket_level_2" do + it "is without error" do expect(ticket_level_2.errors).to be_empty end - it 'announces deleted' do + it "announces deleted" do expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_created, anything).ordered expect(Houdini.event_publisher).to receive(:announce).with(:ticket_level_deleted, { - 'id' => match(/objevt_[a-zA-Z0-9]{22}/), - 'object' => 'object_event', - 'type' => 'ticket_level.deleted', - 'data' => { - 'object' => { - 'amount' => {'cents' => non_free_amount, 'currency' => 'usd'}, - 'available_to' => 'everyone', - 'deleted' => true, - 'description' => description, - 'event' => { - 'id' => event.id, - 'name' => event.name, - 'object' => 'event', - 'nonprofit' => nonprofit.id - }, - 'id'=> kind_of(Numeric), - 'limit' => nil, - 'name' => ticket_level_name, - 'nonprofit'=> { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' + "id" => match(/objevt_[a-zA-Z0-9]{22}/), + "object" => "object_event", + "type" => "ticket_level.deleted", + "data" => { + "object" => { + "amount" => {"cents" => non_free_amount, "currency" => "usd"}, + "available_to" => "everyone", + "deleted" => true, + "description" => description, + "event" => { + "id" => event.id, + "name" => event.name, + "object" => "event", + "nonprofit" => nonprofit.id + }, + "id" => kind_of(Numeric), + "limit" => nil, + "name" => ticket_level_name, + "nonprofit" => { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" }, - 'event_discounts' => [], - 'object' => 'ticket_level', - 'order' => order + "event_discounts" => [], + "object" => "ticket_level", + "order" => order } } }) diff --git a/spec/models/ticket_purchase_spec.rb b/spec/models/ticket_purchase_spec.rb index cb624ad629..0ed5c3ced6 100644 --- a/spec/models/ticket_purchase_spec.rb +++ b/spec/models/ticket_purchase_spec.rb @@ -2,69 +2,66 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe TicketPurchase, type: :model do include_context :shared_donation_charge_context - describe 'to_builder' do - include_context :shared_donation_charge_context + describe "to_builder" do + include_context :shared_donation_charge_context - let(:legacy_free_tickets) do - force_create(:ticket, - event: event, - supporter: supporter, - ticket_level:free_ticket_level, - quantity: 4) - end + let(:legacy_free_tickets) do + force_create(:ticket, + event: event, + supporter: supporter, + ticket_level: free_ticket_level, + quantity: 4) + end - let(:legacy_nonfree_tickets) do - force_create(:ticket, - event: event, - supporter: supporter, - ticket_level:ticket_level, - quantity: 3) - end + let(:legacy_nonfree_tickets) do + force_create(:ticket, + event: event, + supporter: supporter, + ticket_level: ticket_level, + quantity: 3) + end + describe "full-priced tickets" do + # TODO Why are we manually setting everything here? It's not clear what order things should + # go in for a transaction. Therefore, we don't assume the order for now and just make sure the + # the output of to_builder is right + let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200) } - describe 'full-priced tickets' do + let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event, amount: 1200) } - # TODO Why are we manually setting everything here? It's not clear what order things should - # go in for a transaction. Therefore, we don't assume the order for now and just make sure the - # the output of to_builder is right - let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200)} + let(:tickets_for_ticket_purchase) do + legacy_free_tickets.quantity.times do |i| + ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: legacy_free_tickets.ticket_level.amount) + end + legacy_nonfree_tickets.quantity.times do |i| + ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: legacy_nonfree_tickets.ticket_level.amount) + end + end - let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event, amount: 1200)} - - let(:tickets_for_ticket_purchase) do - legacy_free_tickets.quantity.times do |i| - ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: legacy_free_tickets.ticket_level.amount) - - end - legacy_nonfree_tickets.quantity.times do |i| - ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: legacy_nonfree_tickets.ticket_level.amount) - end - end + let(:tktpur_default) do + { + "id" => match_houid("tktpur"), + "object" => "ticket_purchase", + "nonprofit" => nonprofit.id, + "event" => event.id, + "supporter" => supporter.id, + "tickets" => match_array(ticket_purchase.ticket_to_legacy_tickets.pluck(:id)), + "amount" => {"currency" => "usd", "cents" => 1200}, + "original_discount" => {"percent" => 0}, + "event_discount" => nil, + "transaction" => trx.id, + "type" => "trx_assignment" + } + end - let(:tktpur_default) do - { - 'id' => match_houid('tktpur'), - 'object' => 'ticket_purchase', - 'nonprofit' => nonprofit.id, - 'event' => event.id, - 'supporter' => supporter.id, - 'tickets' => match_array(ticket_purchase.ticket_to_legacy_tickets.pluck(:id)), - 'amount' => {'currency' => 'usd', 'cents' => 1200}, - 'original_discount' => { 'percent' => 0}, - 'event_discount' => nil, - 'transaction' => trx.id, - 'type' => 'trx_assignment' - } - end - - it 'is valid' do - expect(ticket_purchase.to_builder.attributes!).to match(tktpur_default) - end - end - end + it "is valid" do + expect(ticket_purchase.to_builder.attributes!).to match(tktpur_default) + end + end + end end diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index 2c6246444a..de25b7679c 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Ticket, type: :model do let(:payment1) { force_create(:payment) } @@ -12,26 +12,26 @@ let(:ticket3) { force_create(:ticket, payment: payment1) } let(:ticket4) { force_create(:ticket, payment: payment2) } - before(:each) do + before do ticket1 ticket2 ticket3 ticket4 end - it 'has ticket1 getting ticket2 and ticket3 for related_tickets' do + it "has ticket1 getting ticket2 and ticket3 for related_tickets" do expect(ticket1.related_tickets).to contain_exactly(ticket2, ticket3) end - it 'has ticket2 getting ticket1 and ticket3 for related_tickets' do + it "has ticket2 getting ticket1 and ticket3 for related_tickets" do expect(ticket2.related_tickets).to contain_exactly(ticket1, ticket3) end - it 'has ticket3 getting ticket1 and ticket2 for related_tickets' do + it "has ticket3 getting ticket1 and ticket2 for related_tickets" do expect(ticket3.related_tickets).to contain_exactly(ticket1, ticket2) end - it 'has ticket4 getting no related tickets' do + it "has ticket4 getting no related tickets" do expect(ticket4.related_tickets).to be_empty end end diff --git a/spec/models/ticket_to_legacy_ticket_spec.rb b/spec/models/ticket_to_legacy_ticket_spec.rb index 1b2a9996b6..d7081037d3 100644 --- a/spec/models/ticket_to_legacy_ticket_spec.rb +++ b/spec/models/ticket_to_legacy_ticket_spec.rb @@ -2,37 +2,35 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe TicketToLegacyTicket, type: :model do include_context :shared_donation_charge_context let(:legacy_free_tickets) do - force_create(:ticket, - event: event, - supporter: supporter, - ticket_level:free_ticket_level, + force_create(:ticket, + event: event, + supporter: supporter, + ticket_level: free_ticket_level, quantity: 4) end let(:legacy_nonfree_tickets) do - force_create(:ticket, - event: event, - supporter: supporter, - ticket_level:ticket_level, + force_create(:ticket, + event: event, + supporter: supporter, + ticket_level: ticket_level, quantity: 3) end + describe "full-priced tickets" do + let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200) } - describe 'full-priced tickets' do - let(:trx) { force_create(:transaction, supporter: supporter, amount: 1200)} + let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event) } - let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event)} - - let(:tickets_for_ticket_purchase) do + let(:tickets_for_ticket_purchase) do legacy_free_tickets.quantity.times do |i| ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: legacy_free_tickets.ticket_level.amount) - end legacy_nonfree_tickets.quantity.times do |i| ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: legacy_nonfree_tickets.ticket_level.amount) @@ -41,91 +39,92 @@ let(:ticket_purchase_to_id) do { - 'id' => ticket_purchase.id, - 'object' => 'ticket_purchase', - 'type' => 'trx_assignment' + "id" => ticket_purchase.id, + "object" => "ticket_purchase", + "type" => "trx_assignment" } end - let(:ticket_default) do + let(:ticket_default) do { - 'id' => match_houid('tkt'), - 'checked_in' => false, - 'deleted' => false, - 'note' => nil, - 'object' => 'ticket', - 'nonprofit' => nonprofit.id, - 'event' => event.id, - 'supporter' => supporter.id, - 'ticket_purchase' => ticket_purchase_to_id, - 'original_discount' => { 'percent' => 0}, - 'event_discount' => nil + "id" => match_houid("tkt"), + "checked_in" => false, + "deleted" => false, + "note" => nil, + "object" => "ticket", + "nonprofit" => nonprofit.id, + "event" => event.id, + "supporter" => supporter.id, + "ticket_purchase" => ticket_purchase_to_id, + "original_discount" => {"percent" => 0}, + "event_discount" => nil } end let(:free_ticket_default) { ticket_default.merge({ - 'ticket_level' => legacy_free_tickets.ticket_level.id, - 'amount' => {'currency' => 'usd', 'cents' => 0} + "ticket_level" => legacy_free_tickets.ticket_level.id, + "amount" => {"currency" => "usd", "cents" => 0} }) } let(:nonfree_ticket_default) { ticket_default.merge({ - 'ticket_level' => legacy_nonfree_tickets.ticket_level.id, - 'amount' => {'currency' => 'usd', 'cents' => legacy_nonfree_tickets.ticket_level.amount} + "ticket_level" => legacy_nonfree_tickets.ticket_level.id, + "amount" => {"currency" => "usd", "cents" => legacy_nonfree_tickets.ticket_level.amount} }) } - subject { tickets_for_ticket_purchase; TicketToLegacyTicket} + subject { + tickets_for_ticket_purchase + TicketToLegacyTicket + } - it 'has 7 TicketToLegacyTicket' do + it "has 7 TicketToLegacyTicket" do expect(subject.count).to eq 7 end - it 'has 3 pointing at legacy_free_tickets' do + it "has 3 pointing at legacy_free_tickets" do expect(subject.where(ticket: legacy_free_tickets).count).to eq 4 end - it 'has 4 pointing at legacy_nonfree_tickets' do + it "has 4 pointing at legacy_nonfree_tickets" do expect(subject.where(ticket: legacy_nonfree_tickets).count).to eq 3 end - it 'has a valid free_ticket' do + it "has a valid free_ticket" do expect(subject.where(ticket: legacy_free_tickets).first.to_builder.attributes!).to match(free_ticket_default) end - it 'has a valid nonfree ticket' do + it "has a valid nonfree ticket" do expect(subject.where(ticket: legacy_nonfree_tickets).first.to_builder.attributes!).to match(nonfree_ticket_default) end - it 'has all free checked in' do + it "has all free checked in" do legacy_free_tickets.checked_in = true legacy_free_tickets.note = "NOTE" legacy_free_tickets.deleted = true legacy_free_tickets.save! - subject.where(ticket: legacy_free_tickets).each do |item| json = item.to_builder.attributes! expect(json).to match(free_ticket_default.merge({ - 'deleted' => true, - 'checked_in' => true, - 'note' => "NOTE" + "deleted" => true, + "checked_in" => true, + "note" => "NOTE" })) end end end - describe 'discounted tickets' do + describe "discounted tickets" do let(:trx) { force_create(:transaction, supporter: supporter, amount: 960) } let(:ticket_purchase) { force_create(:ticket_purchase, trx: trx, event: event, event_discount: event_discount, original_discount: 20) } - let(:tickets_for_ticket_purchase) do + let(:tickets_for_ticket_purchase) do legacy_free_tickets.quantity.times do |i| ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_free_tickets, amount: 0) - end legacy_nonfree_tickets.quantity.times do |i| ticket_purchase.ticket_to_legacy_tickets.create(ticket: legacy_nonfree_tickets, amount: 320) @@ -134,81 +133,81 @@ let(:ticket_purchase_to_id) do { - 'id' => ticket_purchase.id, - 'object'=> 'ticket_purchase', - 'type' => 'trx_assignment' + "id" => ticket_purchase.id, + "object" => "ticket_purchase", + "type" => "trx_assignment" } end - let(:ticket_default) do + let(:ticket_default) do { - 'id' => match_houid('tkt'), - 'checked_in' => false, - 'deleted' => false, - 'note' => nil, - 'object' => 'ticket', - 'nonprofit' => nonprofit.id, - 'event' => event.id, - 'supporter' => supporter.id, - 'ticket_purchase' => ticket_purchase_to_id, - 'original_discount' => { 'percent' => 20}, - 'event_discount' => event_discount.id + "id" => match_houid("tkt"), + "checked_in" => false, + "deleted" => false, + "note" => nil, + "object" => "ticket", + "nonprofit" => nonprofit.id, + "event" => event.id, + "supporter" => supporter.id, + "ticket_purchase" => ticket_purchase_to_id, + "original_discount" => {"percent" => 20}, + "event_discount" => event_discount.id } end let(:free_ticket_default) { ticket_default.merge({ - 'ticket_level' => legacy_free_tickets.ticket_level.id, - 'amount' => {'currency' => 'usd', 'cents' => 0} + "ticket_level" => legacy_free_tickets.ticket_level.id, + "amount" => {"currency" => "usd", "cents" => 0} }) } let(:nonfree_ticket_default) { ticket_default.merge({ - 'ticket_level' => legacy_nonfree_tickets.ticket_level.id, - 'amount' => {'currency' => 'usd', 'cents' => 320 } + "ticket_level" => legacy_nonfree_tickets.ticket_level.id, + "amount" => {"currency" => "usd", "cents" => 320} }) } - subject { tickets_for_ticket_purchase; TicketToLegacyTicket} + subject { + tickets_for_ticket_purchase + TicketToLegacyTicket + } - it 'has 7 TicketToLegacyTicket' do + it "has 7 TicketToLegacyTicket" do expect(subject.count).to eq 7 end - it 'has 3 pointing at legacy_free_tickets' do + it "has 3 pointing at legacy_free_tickets" do expect(subject.where(ticket: legacy_free_tickets).count).to eq 4 end - it 'has 4 pointing at legacy_nonfree_tickets' do + it "has 4 pointing at legacy_nonfree_tickets" do expect(subject.where(ticket: legacy_nonfree_tickets).count).to eq 3 end - - it 'has a valid free_ticket' do + it "has a valid free_ticket" do expect(subject.where(ticket: legacy_free_tickets).first.to_builder.attributes!).to match(free_ticket_default) end - it 'has a valid nonfree ticket' do + it "has a valid nonfree ticket" do expect(subject.where(ticket: legacy_nonfree_tickets).first.to_builder.attributes!).to match(nonfree_ticket_default) end - it 'has all free checked in' do + it "has all free checked in" do legacy_free_tickets.checked_in = true legacy_free_tickets.note = "NOTE" legacy_free_tickets.deleted = true legacy_free_tickets.save! - subject.where(ticket: legacy_free_tickets).each do |item| json = item.to_builder.attributes! expect(json).to match(free_ticket_default.merge({ - 'deleted' => true, - 'checked_in' => true, - 'note' => "NOTE" + "deleted" => true, + "checked_in" => true, + "note" => "NOTE" })) end end end - end diff --git a/spec/models/transaction_assignment_spec.rb b/spec/models/transaction_assignment_spec.rb index b36f74f9ce..4c10d007ef 100644 --- a/spec/models/transaction_assignment_spec.rb +++ b/spec/models/transaction_assignment_spec.rb @@ -2,7 +2,7 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe TransactionAssignment, type: :model do pending "add some examples to (or delete) #{__FILE__}" diff --git a/spec/models/transaction_spec.rb b/spec/models/transaction_spec.rb index adb70799a3..41d286ab15 100644 --- a/spec/models/transaction_spec.rb +++ b/spec/models/transaction_spec.rb @@ -2,38 +2,41 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Transaction, type: :model do include_context :shared_donation_charge_context - describe 'validation' do - it {is_expected.to validate_presence_of(:supporter)} + describe "validation" do + it { is_expected.to validate_presence_of(:supporter) } end - describe 'to_builder' do - subject { supporter.transactions.create( + describe "to_builder" do + subject { + supporter.transactions.create( amount: 1000, - transaction_assignments: [TransactionAssignment.new(assignable:ModernDonation.new(amount: 1000))] - ).to_builder.attributes!} - it 'will create a proper builder result' do + transaction_assignments: [TransactionAssignment.new(assignable: ModernDonation.new(amount: 1000))] + ).to_builder.attributes! + } + + it "will create a proper builder result" do is_expected.to match({ - 'id' => match_houid('trx'), - 'nonprofit' => nonprofit.id, - 'supporter' => supporter.id, - 'object' => 'transaction', - 'created' => Time.current.to_i, - 'amount' => { - 'cents' => 1000, - 'currency' => 'usd' + "id" => match_houid("trx"), + "nonprofit" => nonprofit.id, + "supporter" => supporter.id, + "object" => "transaction", + "created" => Time.current.to_i, + "amount" => { + "cents" => 1000, + "currency" => "usd" }, - 'subtransaction' => nil, - 'payments' => [], - 'transaction_assignments' => [ + "subtransaction" => nil, + "payments" => [], + "transaction_assignments" => [ { - 'object' => 'donation', - 'id' => match_houid('don'), - 'type' => 'trx_assignment' + "object" => "donation", + "id" => match_houid("don"), + "type" => "trx_assignment" } ] }) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a20ca04058..213607eb19 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2,39 +2,39 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe User, type: :model do - describe 'super_admin?' do - let(:super_admin) { - sa = create(:user) - - sa.roles.create(name: 'super_admin') - sa - } - - let(:not_super_admin) { - sa = create(:user) - sa.roles.create(name: 'nonprofit_admin') - sa.roles.create(name: 'nonprofit_associate') - sa - } - - let(:no_roles) { - sa = create(:user) - sa - } - - it 'returns true for super admin' do - expect(super_admin).to be_super_admin - end - - it 'returns false for not super admin' do - expect(not_super_admin).to_not be_super_admin - end - - it 'returns false when has no roles' do - expect(no_roles).to_not be_super_admin - end - end -end \ No newline at end of file + describe "super_admin?" do + let(:super_admin) { + sa = create(:user) + + sa.roles.create(name: "super_admin") + sa + } + + let(:not_super_admin) { + sa = create(:user) + sa.roles.create(name: "nonprofit_admin") + sa.roles.create(name: "nonprofit_associate") + sa + } + + let(:no_roles) { + sa = create(:user) + sa + } + + it "returns true for super admin" do + expect(super_admin).to be_super_admin + end + + it "returns false for not super admin" do + expect(not_super_admin).to_not be_super_admin + end + + it "returns false when has no roles" do + expect(no_roles).to_not be_super_admin + end + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 426351399d..277f452184 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -3,22 +3,22 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # This file is copied to spec/ when you run 'rails generate rspec:install' -require 'spec_helper' -ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../../config/environment', __FILE__) +require "spec_helper" +ENV["RAILS_ENV"] ||= "test" +require File.expand_path("../../config/environment", __FILE__) # Prevent database truncation if the environment is production abort("The Rails environment is running in production mode!") if Rails.env.production? -require 'rspec/rails' +require "rspec/rails" # Add additional requires below this line. Rails is not loaded until this point! -require 'devise' -require 'support/factory_bot' -require 'support/mock_helpers' -require 'action_mailer_matchers' -require 'active_job' -require 'wisper/rspec/matchers' -require 'support/contexts' -require 'support/stripe_mock_helper' -require 'validate_url/rspec_matcher' +require "devise" +require "support/factory_bot" +require "support/mock_helpers" +require "action_mailer_matchers" +require "active_job" +require "wisper/rspec/matchers" +require "support/contexts" +require "support/stripe_mock_helper" +require "validate_url/rspec_matcher" include ActiveJob::TestHelper # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are @@ -49,8 +49,8 @@ ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - + config.fixture_path = "#{Rails.root.join("spec/fixtures")}" + ActiveJob::Base.queue_adapter = :test # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false @@ -84,18 +84,18 @@ config.include ActionMailerMatchers config.before(:suite) do DatabaseCleaner.strategy = :transaction - DatabaseCleaner.clean_with(:truncation, except: %w(ar_internal_metadata)) + DatabaseCleaner.clean_with(:truncation, except: %w[ar_internal_metadata]) Rails.application.load_seed end - config.around(:each) do |example| + config.around do |example| DatabaseCleaner.cleaning do example.run end clear_enqueued_jobs end - config.after(:each) do + config.after do StripeMockHelper.stop end @@ -104,5 +104,5 @@ with.test_framework :rspec with.library :rails end - end + end end diff --git a/spec/requests/api/campaign_gift_options_controller_request_spec.rb b/spec/requests/api/campaign_gift_options_controller_request_spec.rb index c958e15d46..d106386d40 100644 --- a/spec/requests/api/campaign_gift_options_controller_request_spec.rb +++ b/spec/requests/api/campaign_gift_options_controller_request_spec.rb @@ -2,533 +2,533 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::CampaignGiftOptionsController do - let(:campaign) { campaign_gift_option_with_campaign_with_one_time_amount.campaign } - let(:nonprofit) { campaign.nonprofit } - let(:user) { create(:user) } - - let(:campaign_gift_option_with_campaign_with_one_time_amount) do - create(:campaign_gift_option_with_campaign_with_one_time_amount) - end - let(:campaign_gift_option_with_campaign_with_recurring_amount) do - create(:campaign_gift_option_with_campaign_with_recurring_amount, - campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) - end - let(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount) do - create(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount, - campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) - end - - before do - campaign_gift_option_with_campaign_with_one_time_amount - campaign_gift_option_with_campaign_with_recurring_amount - campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount - end - - def base_path(nonprofit_id, campaign_id) - "/api/nonprofits/#{nonprofit_id}/campaigns/#{campaign_id}/campaign_gift_options" - end - - def base_url(nonprofit_id, campaign_id) - "http://www.example.com#{base_path(nonprofit_id, campaign_id)}" - end - - describe 'GET /:id' do - context 'with nonprofit user' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get base_path( - nonprofit.id, - campaign.id - ) + - "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option_with_campaign_with_one_time_amount.id) - } - - it { - is_expected.to include('name' => 'has one time amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time description') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => nil) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 200, 'currency' => nonprofit.currency }, - 'recurrence' => nil - }] - )) - } - - it { - is_expected.to include('url' => - base_url( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}") - } - end - - context 'with campaign editor' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'campaign_editor', host: campaign) - sign_in user - get base_path( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}" - end - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option_with_campaign_with_one_time_amount.id) - } - - it { - is_expected.to include('name' => 'has one time amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time description') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => nil) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 200, 'currency' => nonprofit.currency }, - 'recurrence' => nil - }] - )) - } - - it { - is_expected.to include('url' => - base_url( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}") - } - end - - context 'with no user' do - it 'returns unauthorized' do - get base_path( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}" - expect(response).to have_http_status(:unauthorized) - end - end - end - - describe 'GET /' do - shared_context 'when campaign_gift_option_with_campaign_with_one_time_amount' do - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has one time amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time description') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => nil) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 200, 'currency' => nonprofit.currency }, - 'recurrence' => nil - }] - )) - } - - it { - is_expected.to include('url' => - base_url( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option.id}") - } - end - - shared_context 'when campaign_gift_option_with_campaign_with_recurring_amount' do - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has recurring amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'a recurring description!') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => 4) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly' } - }] - )) - } - - it { - is_expected.to include('url' => - a_string_matching( - base_url( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option.id}" - )) - } - end - - shared_context 'when campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount' do - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has both one time and recurring amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time AND recurring') - } - - it { - is_expected.to include('hide_contributions' => true) - } - - it { - is_expected.to include('order' => 5) - } - - it { - is_expected.to include('to_ship' => true) - } - - it { - is_expected.to include('quantity' => 50) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [ - { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly' } - }, - { - 'amount' => { 'cents' => 300, 'currency' => nonprofit.currency }, - 'recurrence' => nil - } - - ] - )) - } - - it { - is_expected.to include('url' => - base_url( - nonprofit.id, - campaign.id - ) + "/#{campaign_gift_option.id}") - } - end - - context 'with nonprofit user' do - subject(:json) do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get base_path(nonprofit.id, campaign.id) - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(json['data'].count).to eq 3 - } - - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 3) } - - describe 'for campaign_gift_option_with_campaign_with_one_time_amount' do - subject(:first) do - json['data'][2] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_one_time_amount } - - include_context 'when campaign_gift_option_with_campaign_with_one_time_amount' - end - - describe 'for campaign_gift_option_with_campaign_with_recurring_amount' do - subject(:second) do - json['data'][1] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_recurring_amount } - - include_context 'when campaign_gift_option_with_campaign_with_recurring_amount' - end - - describe 'for campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount' do - subject(:third) do - json['data'][0] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount } - - include_context 'when campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount' - end - end - - context 'with campaign editor' do - subject(:json) do - response.parsed_body - end - - before do - user.roles.create(name: 'campaign_editor', host: campaign) - sign_in user - get base_path(nonprofit.id, campaign.id) - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(json['data'].count).to eq 3 - } - - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 3) } - - describe 'for campaign_gift_option_with_campaign_with_one_time_amount' do - subject(:first) do - json['data'][2] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_one_time_amount } - - include_context 'when campaign_gift_option_with_campaign_with_one_time_amount' - end - - describe 'for campaign_gift_option_with_campaign_with_recurring_amount' do - subject(:second) do - json['data'][1] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_recurring_amount } - - include_context 'when campaign_gift_option_with_campaign_with_recurring_amount' - end - - describe 'for campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount' do - subject(:third) do - json['data'][0] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount } - - include_context 'when campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount' - end - end - - context 'with no user' do - it 'returns unauthorized' do - get base_path(nonprofit.id, campaign.id) - expect(response).to have_http_status(:unauthorized) - end - end - end + let(:campaign) { campaign_gift_option_with_campaign_with_one_time_amount.campaign } + let(:nonprofit) { campaign.nonprofit } + let(:user) { create(:user) } + + let(:campaign_gift_option_with_campaign_with_one_time_amount) do + create(:campaign_gift_option_with_campaign_with_one_time_amount) + end + let(:campaign_gift_option_with_campaign_with_recurring_amount) do + create(:campaign_gift_option_with_campaign_with_recurring_amount, + campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) + end + let(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount) do + create(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount, + campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) + end + + before do + campaign_gift_option_with_campaign_with_one_time_amount + campaign_gift_option_with_campaign_with_recurring_amount + campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount + end + + def base_path(nonprofit_id, campaign_id) + "/api/nonprofits/#{nonprofit_id}/campaigns/#{campaign_id}/campaign_gift_options" + end + + def base_url(nonprofit_id, campaign_id) + "http://www.example.com#{base_path(nonprofit_id, campaign_id)}" + end + + describe "GET /:id" do + context "with nonprofit user" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get base_path( + nonprofit.id, + campaign.id + ) + + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option_with_campaign_with_one_time_amount.id) + } + + it { + is_expected.to include("name" => "has one time amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time description") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => nil) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 200, "currency" => nonprofit.currency}, + "recurrence" => nil + }] + )) + } + + it { + is_expected.to include("url" => + base_url( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}") + } + end + + context "with campaign editor" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "campaign_editor", host: campaign) + sign_in user + get base_path( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}" + end + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option_with_campaign_with_one_time_amount.id) + } + + it { + is_expected.to include("name" => "has one time amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time description") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => nil) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 200, "currency" => nonprofit.currency}, + "recurrence" => nil + }] + )) + } + + it { + is_expected.to include("url" => + base_url( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}") + } + end + + context "with no user" do + it "returns unauthorized" do + get base_path( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option_with_campaign_with_one_time_amount.id}" + expect(response).to have_http_status(:unauthorized) + end + end + end + + describe "GET /" do + shared_context "when campaign_gift_option_with_campaign_with_one_time_amount" do + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has one time amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time description") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => nil) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 200, "currency" => nonprofit.currency}, + "recurrence" => nil + }] + )) + } + + it { + is_expected.to include("url" => + base_url( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option.id}") + } + end + + shared_context "when campaign_gift_option_with_campaign_with_recurring_amount" do + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has recurring amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "a recurring description!") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => 4) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} + }] + )) + } + + it { + is_expected.to include("url" => + a_string_matching( + base_url( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option.id}" + )) + } + end + + shared_context "when campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount" do + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has both one time and recurring amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time AND recurring") + } + + it { + is_expected.to include("hide_contributions" => true) + } + + it { + is_expected.to include("order" => 5) + } + + it { + is_expected.to include("to_ship" => true) + } + + it { + is_expected.to include("quantity" => 50) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [ + { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} + }, + { + "amount" => {"cents" => 300, "currency" => nonprofit.currency}, + "recurrence" => nil + } + + ] + )) + } + + it { + is_expected.to include("url" => + base_url( + nonprofit.id, + campaign.id + ) + "/#{campaign_gift_option.id}") + } + end + + context "with nonprofit user" do + subject(:json) do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get base_path(nonprofit.id, campaign.id) + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(json["data"].count).to eq 3 + } + + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 3) } + + describe "for campaign_gift_option_with_campaign_with_one_time_amount" do + subject(:first) do + json["data"][2] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_one_time_amount } + + include_context "when campaign_gift_option_with_campaign_with_one_time_amount" + end + + describe "for campaign_gift_option_with_campaign_with_recurring_amount" do + subject(:second) do + json["data"][1] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_recurring_amount } + + include_context "when campaign_gift_option_with_campaign_with_recurring_amount" + end + + describe "for campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount" do + subject(:third) do + json["data"][0] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount } + + include_context "when campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount" + end + end + + context "with campaign editor" do + subject(:json) do + response.parsed_body + end + + before do + user.roles.create(name: "campaign_editor", host: campaign) + sign_in user + get base_path(nonprofit.id, campaign.id) + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(json["data"].count).to eq 3 + } + + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 3) } + + describe "for campaign_gift_option_with_campaign_with_one_time_amount" do + subject(:first) do + json["data"][2] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_one_time_amount } + + include_context "when campaign_gift_option_with_campaign_with_one_time_amount" + end + + describe "for campaign_gift_option_with_campaign_with_recurring_amount" do + subject(:second) do + json["data"][1] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_recurring_amount } + + include_context "when campaign_gift_option_with_campaign_with_recurring_amount" + end + + describe "for campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount" do + subject(:third) do + json["data"][0] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount } + + include_context "when campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount" + end + end + + context "with no user" do + it "returns unauthorized" do + get base_path(nonprofit.id, campaign.id) + expect(response).to have_http_status(:unauthorized) + end + end + end end diff --git a/spec/requests/api/campaigns_controller_request_spec.rb b/spec/requests/api/campaigns_controller_request_spec.rb index ca35767fd8..73f6d46579 100644 --- a/spec/requests/api/campaigns_controller_request_spec.rb +++ b/spec/requests/api/campaigns_controller_request_spec.rb @@ -2,98 +2,98 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::CampaignsController do - let(:campaign) { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } - let(:nonprofit) { campaign.nonprofit } - let(:user) { create(:user) } - - before do - campaign - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - describe 'GET /:id' do - context 'with nonprofit user' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get "/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - it { - is_expected.to include('object' => 'campaign') - } - - it { - is_expected.to include('id' => campaign.id) - } - - it { - is_expected.to include('name' => campaign.name) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}})) - } - end - - context 'with campaign editor' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'campaign_editor', host: campaign) - sign_in user - get "/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - it { - is_expected.to include('object' => 'campaign') - } - - it { - is_expected.to include('id' => campaign.id) - } - - it { - is_expected.to include('name' => campaign.name) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}})) - } - end - - context 'with no user' do - it 'returns http success when logged in' do - get "/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}" - expect(response).to have_http_status(:unauthorized) - end - end - end + let(:campaign) { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } + let(:nonprofit) { campaign.nonprofit } + let(:user) { create(:user) } + + before do + campaign + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + describe "GET /:id" do + context "with nonprofit user" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get "/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + is_expected.to include("object" => "campaign") + } + + it { + is_expected.to include("id" => campaign.id) + } + + it { + is_expected.to include("name" => campaign.name) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}})) + } + end + + context "with campaign editor" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "campaign_editor", host: campaign) + sign_in user + get "/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + is_expected.to include("object" => "campaign") + } + + it { + is_expected.to include("id" => campaign.id) + } + + it { + is_expected.to include("name" => campaign.name) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}})) + } + end + + context "with no user" do + it "returns http success when logged in" do + get "/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}" + expect(response).to have_http_status(:unauthorized) + end + end + end end diff --git a/spec/requests/api/custom_field_definitions_controller_request_spec.rb b/spec/requests/api/custom_field_definitions_controller_request_spec.rb index a9ce7bd6eb..147895987d 100644 --- a/spec/requests/api/custom_field_definitions_controller_request_spec.rb +++ b/spec/requests/api/custom_field_definitions_controller_request_spec.rb @@ -2,198 +2,198 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::CustomFieldDefinitionsController do - let(:custom_field_definition) { create(:custom_field_definition_with_nonprofit) } - let(:nonprofit) { custom_field_definition.nonprofit } - let(:user) { create(:user) } - - before do - custom_field_definition - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - describe 'GET /' do - let(:nonprofit) { Nonprofit.first } - - context 'when logged in successfully' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions" - end - - it { - expect(response).to have_http_status(:success) - } - - describe 'with a response' do - subject(:json) do - response.parsed_body - end - - it { - expect(json['data'].count).to eq 1 - } - - describe 'and a first item' do - subject(:first) { json['data'][0] } - - it { - is_expected.to include('object' => 'custom_field_definition') - } - - it { - is_expected.to include('id' => custom_field_definition.id) - } - - it { - is_expected.to include('name' => 'Def Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} # rubocop:disable Layout/LineLength - )) - } - end - end - - context 'when paging' do - before do - custom_field_definition - 6.times do |i| - create(:custom_field_definition_with_nonprofit, - nonprofit: nonprofit, - name: i) - end - sign_in user - end - - context 'when on page 0' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions", params: { page: 0, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end - - context 'when on page 1' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions", params: { page: 1, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq CustomFieldDefinition.order('id DESC').limit(5).pluck(:id) - } - end - - context 'when on page 2' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions", params: { page: 2, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 2)) } - it { is_expected.to include('first_page' => false) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 2) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq CustomFieldDefinition.order('id DESC').limit(2).offset(5).pluck(:id) - } - end - end - end - - it 'returns http unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions" - expect(response).to have_http_status(:unauthorized) - end - end - - describe 'GET /:id' do - context 'when logged in' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - describe 'with a response' do - subject do - response.parsed_body - end - - it { - is_expected.to include('object' => 'custom_field_definition') - } - - it { - is_expected.to include('id' => custom_field_definition.id) - } - - it { - is_expected.to include('name' => 'Def Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} # rubocop:disable Layout/LineLength - )) - } - end - end - - it 'returns unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}" - expect(response).to have_http_status(:unauthorized) - end - end + let(:custom_field_definition) { create(:custom_field_definition_with_nonprofit) } + let(:nonprofit) { custom_field_definition.nonprofit } + let(:user) { create(:user) } + + before do + custom_field_definition + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + describe "GET /" do + let(:nonprofit) { Nonprofit.first } + + context "when logged in successfully" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions" + end + + it { + expect(response).to have_http_status(:success) + } + + describe "with a response" do + subject(:json) do + response.parsed_body + end + + it { + expect(json["data"].count).to eq 1 + } + + describe "and a first item" do + subject(:first) { json["data"][0] } + + it { + is_expected.to include("object" => "custom_field_definition") + } + + it { + is_expected.to include("id" => custom_field_definition.id) + } + + it { + is_expected.to include("name" => "Def Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} # rubocop:disable Layout/LineLength + )) + } + end + end + + context "when paging" do + before do + custom_field_definition + 6.times do |i| + create(:custom_field_definition_with_nonprofit, + nonprofit: nonprofit, + name: i) + end + sign_in user + end + + context "when on page 0" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions", params: {page: 0, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end + + context "when on page 1" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions", params: {page: 1, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq CustomFieldDefinition.order("id DESC").limit(5).pluck(:id) + } + end + + context "when on page 2" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions", params: {page: 2, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 2)) } + it { is_expected.to include("first_page" => false) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 2) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq CustomFieldDefinition.order("id DESC").limit(2).offset(5).pluck(:id) + } + end + end + end + + it "returns http unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions" + expect(response).to have_http_status(:unauthorized) + end + end + + describe "GET /:id" do + context "when logged in" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + describe "with a response" do + subject do + response.parsed_body + end + + it { + is_expected.to include("object" => "custom_field_definition") + } + + it { + is_expected.to include("id" => custom_field_definition.id) + } + + it { + is_expected.to include("name" => "Def Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} # rubocop:disable Layout/LineLength + )) + } + end + end + + it "returns unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}" + expect(response).to have_http_status(:unauthorized) + end + end end diff --git a/spec/requests/api/events_controller_request_spec.rb b/spec/requests/api/events_controller_request_spec.rb index 4ddda8e7ee..dba7031d09 100644 --- a/spec/requests/api/events_controller_request_spec.rb +++ b/spec/requests/api/events_controller_request_spec.rb @@ -2,86 +2,86 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.shared_examples 'common event api result' do - it { - expect(response).to have_http_status(:success) - } +RSpec.shared_examples "common event api result" do + it { + expect(response).to have_http_status(:success) + } - it { - is_expected.to include('object' => 'event') - } + it { + is_expected.to include("object" => "event") + } - it { - is_expected.to include('id' => event.id) - } + it { + is_expected.to include("id" => event.id) + } - it { - is_expected.to include('name' => event.name) - } + it { + is_expected.to include("name" => event.name) + } - it { - is_expected.to include('nonprofit' => nonprofit.id) - } + it { + is_expected.to include("nonprofit" => nonprofit.id) + } - it { - is_expected.to include('url' => base_url(nonprofit.id, event.id)) - } + it { + is_expected.to include("url" => base_url(nonprofit.id, event.id)) + } end RSpec.describe Api::EventsController do - let(:event) { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } - let(:nonprofit) { event.nonprofit } - let(:user) { create(:user) } - - before do - event - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - def base_path(nonprofit_id, event_id) - "/api/nonprofits/#{nonprofit_id}/events/#{event_id}" - end - - def base_url(nonprofit_id, event_id) - "http://www.example.com#{base_path(nonprofit_id, event_id)}" - end - - describe 'GET /:id' do - context 'with nonprofit user' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get base_url(nonprofit.id, event.id) - end - - include_context 'common event api result' - end - - context 'with event editor' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'event_editor', host: event) - sign_in user - get base_url(nonprofit.id, event.id) - end - - include_context 'common event api result' - end - - context 'with no user' do - it 'returns http unauthorized when not logged in' do - get base_url(nonprofit.id, event.id) - expect(response).to have_http_status(:unauthorized) - end - end - end + let(:event) { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } + let(:nonprofit) { event.nonprofit } + let(:user) { create(:user) } + + before do + event + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + def base_path(nonprofit_id, event_id) + "/api/nonprofits/#{nonprofit_id}/events/#{event_id}" + end + + def base_url(nonprofit_id, event_id) + "http://www.example.com#{base_path(nonprofit_id, event_id)}" + end + + describe "GET /:id" do + context "with nonprofit user" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get base_url(nonprofit.id, event.id) + end + + include_context "common event api result" + end + + context "with event editor" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "event_editor", host: event) + sign_in user + get base_url(nonprofit.id, event.id) + end + + include_context "common event api result" + end + + context "with no user" do + it "returns http unauthorized when not logged in" do + get base_url(nonprofit.id, event.id) + expect(response).to have_http_status(:unauthorized) + end + end + end end diff --git a/spec/requests/api/nonprofits_controller_requests_spec.rb b/spec/requests/api/nonprofits_controller_requests_spec.rb index b151117a6d..690963a41c 100644 --- a/spec/requests/api/nonprofits_controller_requests_spec.rb +++ b/spec/requests/api/nonprofits_controller_requests_spec.rb @@ -2,69 +2,69 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Api::NonprofitsController do - describe 'GET /api/nonprofits/:id' do - context "when nonprofit doesn't exists", pending: "the user gets a 401 but it's should be 404" do - before do - get '/api/nonprofits/1414140o' - end + describe "GET /api/nonprofits/:id" do + context "when nonprofit doesn't exists", pending: "the user gets a 401 but it's should be 404" do + before do + get "/api/nonprofits/1414140o" + end - it { - expect(response).to have_http_status(:not_found) - } - end + it { + expect(response).to have_http_status(:not_found) + } + end - context 'when not logged in' do - before do - get "/api/nonprofits/#{create(:fv_poverty).id}" - end + context "when not logged in" do + before do + get "/api/nonprofits/#{create(:fv_poverty).id}" + end - it { - expect(response).to have_http_status(:unauthorized) - } + it { + expect(response).to have_http_status(:unauthorized) + } - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } - end + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } + end - context 'when logged in' do - subject do - response.parsed_body - end + context "when logged in" do + subject do + response.parsed_body + end - let(:user) { create(:user) } - let(:nonprofit) { create(:fv_poverty) } + let(:user) { create(:user) } + let(:nonprofit) { create(:fv_poverty) } - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get "/api/nonprofits/#{nonprofit.id}" - end + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get "/api/nonprofits/#{nonprofit.id}" + end - it { - expect(response).to have_http_status(:success) - } + it { + expect(response).to have_http_status(:success) + } - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } - context 'with response' do - it { - is_expected.to include('id' => nonprofit.id) - } + context "with response" do + it { + is_expected.to include("id" => nonprofit.id) + } - it { - is_expected.to include('name' => nonprofit.name) - } + it { + is_expected.to include("name" => nonprofit.name) + } - it { - is_expected.to include('object' => 'nonprofit') - } - end - end - end + it { + is_expected.to include("object" => "nonprofit") + } + end + end + end end diff --git a/spec/requests/api/payments_controller_request_spec.rb b/spec/requests/api/payments_controller_request_spec.rb index d6c892e292..a0f748242a 100644 --- a/spec/requests/api/payments_controller_request_spec.rb +++ b/spec/requests/api/payments_controller_request_spec.rb @@ -2,144 +2,144 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::PaymentsController do - let(:nonprofit) { transaction_for_donation.nonprofit } - let(:user) { create(:user) } - let(:supporter) { transaction_for_donation.supporter } - - let(:transaction_for_donation) do - create(:transaction_for_donation) - end - - before do - transaction_for_donation - end - - def index_base_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction/payments" - end - - def index_base_url(nonprofit_id, transaction_id) - "http://www.example.com#{index_base_path(nonprofit_id, transaction_id)}" - end - - describe 'GET /:id' do - let(:transaction) { transaction_for_donation } - let(:payment) { transaction.subtransaction.payments.first } - - def base_path(nonprofit_id, transaction_id, payment_id) - index_base_path(nonprofit_id, transaction_id) + "/#{payment_id}" - end - - def base_url(nonprofit_id, transaction_id, payment_id) - "http://www.example.com#{base_path(nonprofit_id, transaction_id, payment_id)}" - end - - def subtransaction_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" - end - - def subtransaction_url(nonprofit_id, transaction_id) - "http://www.example.com#{subtransaction_path(nonprofit_id, transaction_id)}" - end - - def payment_path(nonprofit_id, transaction_id, payment_id) - "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" - end - - def payment_url(nonprofit_id, transaction_id, payment_id) - "http://www.example.com#{payment_path(nonprofit_id, transaction_id, payment_id)}" - end - - context 'with nonprofit user' do - subject(:json) do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get payment_path( - nonprofit.id, - transaction.id, - payment.paymentable.id - ) - end - - it { - expect(response).to have_http_status(:success) - } - - include_context 'with json results for first payment on transaction_for_donation' - end - - context 'with no user' do - it 'returns unauthorized' do - get payment_path( - nonprofit.id, - transaction.id, - payment.paymentable.id - ) - expect(response).to have_http_status(:unauthorized) - end - end - end - - describe 'GET /' do - context 'with nonprofit user' do - subject(:outer_json) do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get index_base_path(nonprofit.id, transaction.id) - end - - let(:transaction) { transaction_for_donation } - - it { - expect(response).to have_http_status(:success) - } - - it { expect(outer_json['data'].count).to eq 1 } - - describe 'for transaction_for_donation' do - subject(:json) do - outer_json['data'].first - end - - def payment_path(nonprofit_id, transaction_id, payment_id) - index_base_path(nonprofit_id, transaction_id) + "/#{payment_id}" - end - - let(:payment) { transaction.subtransaction.payments.first } - let(:transaction) { transaction_for_donation } - - def payment_url(nonprofit_id, transaction_id, payment_id) - "http://www.example.com#{payment_path(nonprofit_id, transaction_id, payment_id)}" - end - - include_context 'with json results for first payment on transaction_for_donation' - end - - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 1) } - end - - context 'with no user' do - let(:transaction) { transaction_for_donation } - - it 'returns unauthorized' do - get index_base_path(nonprofit.id, transaction.id) - expect(response).to have_http_status(:unauthorized) - end - end - end + let(:nonprofit) { transaction_for_donation.nonprofit } + let(:user) { create(:user) } + let(:supporter) { transaction_for_donation.supporter } + + let(:transaction_for_donation) do + create(:transaction_for_donation) + end + + before do + transaction_for_donation + end + + def index_base_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction/payments" + end + + def index_base_url(nonprofit_id, transaction_id) + "http://www.example.com#{index_base_path(nonprofit_id, transaction_id)}" + end + + describe "GET /:id" do + let(:transaction) { transaction_for_donation } + let(:payment) { transaction.subtransaction.payments.first } + + def base_path(nonprofit_id, transaction_id, payment_id) + index_base_path(nonprofit_id, transaction_id) + "/#{payment_id}" + end + + def base_url(nonprofit_id, transaction_id, payment_id) + "http://www.example.com#{base_path(nonprofit_id, transaction_id, payment_id)}" + end + + def subtransaction_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" + end + + def subtransaction_url(nonprofit_id, transaction_id) + "http://www.example.com#{subtransaction_path(nonprofit_id, transaction_id)}" + end + + def payment_path(nonprofit_id, transaction_id, payment_id) + "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" + end + + def payment_url(nonprofit_id, transaction_id, payment_id) + "http://www.example.com#{payment_path(nonprofit_id, transaction_id, payment_id)}" + end + + context "with nonprofit user" do + subject(:json) do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get payment_path( + nonprofit.id, + transaction.id, + payment.paymentable.id + ) + end + + it { + expect(response).to have_http_status(:success) + } + + include_context "with json results for first payment on transaction_for_donation" + end + + context "with no user" do + it "returns unauthorized" do + get payment_path( + nonprofit.id, + transaction.id, + payment.paymentable.id + ) + expect(response).to have_http_status(:unauthorized) + end + end + end + + describe "GET /" do + context "with nonprofit user" do + subject(:outer_json) do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get index_base_path(nonprofit.id, transaction.id) + end + + let(:transaction) { transaction_for_donation } + + it { + expect(response).to have_http_status(:success) + } + + it { expect(outer_json["data"].count).to eq 1 } + + describe "for transaction_for_donation" do + subject(:json) do + outer_json["data"].first + end + + def payment_path(nonprofit_id, transaction_id, payment_id) + index_base_path(nonprofit_id, transaction_id) + "/#{payment_id}" + end + + let(:payment) { transaction.subtransaction.payments.first } + let(:transaction) { transaction_for_donation } + + def payment_url(nonprofit_id, transaction_id, payment_id) + "http://www.example.com#{payment_path(nonprofit_id, transaction_id, payment_id)}" + end + + include_context "with json results for first payment on transaction_for_donation" + end + + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 1) } + end + + context "with no user" do + let(:transaction) { transaction_for_donation } + + it "returns unauthorized" do + get index_base_path(nonprofit.id, transaction.id) + expect(response).to have_http_status(:unauthorized) + end + end + end end diff --git a/spec/requests/api/roles_controller_request_spec.rb b/spec/requests/api/roles_controller_request_spec.rb index 0d75deceb2..a54826ab9d 100644 --- a/spec/requests/api/roles_controller_request_spec.rb +++ b/spec/requests/api/roles_controller_request_spec.rb @@ -2,72 +2,72 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Api::RolesController do - describe 'GET /api/nonprofits/:id/roles' do - context "when nonprofit doesn't exists", pending: "the user gets a 401 but it's should be 404" do - before do - get '/api/nonprofits/1414140o/roles' - end + describe "GET /api/nonprofits/:id/roles" do + context "when nonprofit doesn't exists", pending: "the user gets a 401 but it's should be 404" do + before do + get "/api/nonprofits/1414140o/roles" + end - it { - expect(response).to have_http_status(:not_found) - } - end + it { + expect(response).to have_http_status(:not_found) + } + end - context 'when not logged in' do - before do - get "/api/nonprofits/#{create(:fv_poverty).id}" - end + context "when not logged in" do + before do + get "/api/nonprofits/#{create(:fv_poverty).id}" + end - it { - expect(response).to have_http_status(:unauthorized) - } + it { + expect(response).to have_http_status(:unauthorized) + } - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } - end + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } + end - context 'when logged in' do - subject do - response.parsed_body - end + context "when logged in" do + subject do + response.parsed_body + end - let(:user) { create(:user) } - let(:nonprofit) { create(:fv_poverty) } - let(:role) { user.roles.create(name: 'nonprofit_associate', host: nonprofit) } + let(:user) { create(:user) } + let(:nonprofit) { create(:fv_poverty) } + let(:role) { user.roles.create(name: "nonprofit_associate", host: nonprofit) } - before do - role - sign_in user - get "/api/nonprofits/#{nonprofit.id}/roles" - end + before do + role + sign_in user + get "/api/nonprofits/#{nonprofit.id}/roles" + end - it { - expect(response).to have_http_status(:success) - } + it { + expect(response).to have_http_status(:success) + } - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } - context 'with response' do - it { - is_expected.to include_json( - data: [ - { - id: role.id, - name: role.name, - user_id: role.user.id, - host: 'Nonprofit', - object: 'role' - } - ] - ) - } - end - end - end + context "with response" do + it { + is_expected.to include_json( + data: [ + { + id: role.id, + name: role.name, + user_id: role.user.id, + host: "Nonprofit", + object: "role" + } + ] + ) + } + end + end + end end diff --git a/spec/requests/api/supporter_addresses_controller_request_spec.rb b/spec/requests/api/supporter_addresses_controller_request_spec.rb index d678b71190..ef8c9d7b76 100644 --- a/spec/requests/api/supporter_addresses_controller_request_spec.rb +++ b/spec/requests/api/supporter_addresses_controller_request_spec.rb @@ -3,170 +3,170 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::SupporterAddressesController do - let(:supporter) { create(:supporter_with_fv_poverty) } - let(:nonprofit) { supporter.nonprofit } - let(:supporter_address) { supporter } - let(:user) { create(:user) } - - before do - supporter - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - describe 'GET /' do - context 'when logged in' do - subject(:json) do - response.parsed_body - end - - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses" - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(json['data'].count).to eq 1 - } - - context 'with first item' do - subject do - json['data'][0] - end - - it { - is_expected.to include('object' => 'supporter_address') - } - - it { - is_expected.to include('id' => supporter_address.id) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('address' => supporter_address.address) - } - - it { - is_expected.to include('city' => supporter_address.city) - } - - it { - is_expected.to include('state_code' => supporter_address.state_code) - } - - it { - is_expected.to include('country' => supporter_address.country) - } - - it { - is_expected.to include('zip_code' => supporter_address.zip_code) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength - )) - } - end - - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 1) } - end - - it 'returns http unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses" - expect(response).to have_http_status(:unauthorized) - end - end - - describe 'GET /:id' do - context 'when logged in' do - subject do - response.parsed_body - end - - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - it { - is_expected.to include('object' => 'supporter_address') - } - - it { - is_expected.to include('id' => supporter_address.id) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('address' => supporter_address.address) - } - - it { - is_expected.to include('city' => supporter_address.city) - } - - it { - is_expected.to include('state_code' => supporter_address.state_code) - } - - it { - is_expected.to include('country' => supporter_address.country) - } - - it { - is_expected.to include('zip_code' => supporter_address.zip_code) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength - )) - } - end - - it 'returns http success when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}" - expect(response).to have_http_status(:unauthorized) - end - end + let(:supporter) { create(:supporter_with_fv_poverty) } + let(:nonprofit) { supporter.nonprofit } + let(:supporter_address) { supporter } + let(:user) { create(:user) } + + before do + supporter + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + describe "GET /" do + context "when logged in" do + subject(:json) do + response.parsed_body + end + + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(json["data"].count).to eq 1 + } + + context "with first item" do + subject do + json["data"][0] + end + + it { + is_expected.to include("object" => "supporter_address") + } + + it { + is_expected.to include("id" => supporter_address.id) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("address" => supporter_address.address) + } + + it { + is_expected.to include("city" => supporter_address.city) + } + + it { + is_expected.to include("state_code" => supporter_address.state_code) + } + + it { + is_expected.to include("country" => supporter_address.country) + } + + it { + is_expected.to include("zip_code" => supporter_address.zip_code) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength + )) + } + end + + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 1) } + end + + it "returns http unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses" + expect(response).to have_http_status(:unauthorized) + end + end + + describe "GET /:id" do + context "when logged in" do + subject do + response.parsed_body + end + + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + is_expected.to include("object" => "supporter_address") + } + + it { + is_expected.to include("id" => supporter_address.id) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("address" => supporter_address.address) + } + + it { + is_expected.to include("city" => supporter_address.city) + } + + it { + is_expected.to include("state_code" => supporter_address.state_code) + } + + it { + is_expected.to include("country" => supporter_address.country) + } + + it { + is_expected.to include("zip_code" => supporter_address.zip_code) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength + )) + } + end + + it "returns http success when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}" + expect(response).to have_http_status(:unauthorized) + end + end end diff --git a/spec/requests/api/supporter_notes_controller_request_spec.rb b/spec/requests/api/supporter_notes_controller_request_spec.rb index bcdc9732c4..ee2694da85 100644 --- a/spec/requests/api/supporter_notes_controller_request_spec.rb +++ b/spec/requests/api/supporter_notes_controller_request_spec.rb @@ -3,206 +3,206 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::SupporterNotesController do - let(:supporter) { supporter_note.supporter } - let(:nonprofit) { supporter.nonprofit } - let(:supporter_note) { create(:supporter_note_with_fv_poverty_with_user) } - let(:user) { supporter_note.user } - - before do - supporter - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - describe 'GET /' do - context 'when logged in' do - subject(:json) do - response.parsed_body - end - - describe 'with a response' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes" - end - - it { - expect(response).to have_http_status(:success) - } - - it { - is_expected.to include('data' => have_attributes(count: 1)) - } - - context 'with first item' do - subject do - json['data'][0] - end - - it { - is_expected.to include('object' => 'supporter_note') - } - - it { - is_expected.to include('id' => supporter_note.id) - } - - it { - is_expected.to include('content' => 'Some content in our note') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('user' => user.id) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} # rubocop:disable Layout/LineLength - )) - } - end - end - - context 'when paging' do - before do - 6.times do |i| - create(:supporter_note_with_fv_poverty_with_user, supporter: supporter, content: "content for #{i}") - end - sign_in user - end - - context 'when on page 0' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes", params: { page: 0, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end - - context 'when on page 1' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes", params: { page: 1, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq SupporterNote.order('id DESC').limit(5).pluck(:id) - } - end - - context 'when on page 2' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes", params: { page: 2, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 2)) } - it { is_expected.to include('first_page' => false) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 2) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq SupporterNote.order('id DESC').limit(2).offset(5).pluck(:id) - } - end - end - end - - it 'returns http unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes" - expect(response).to have_http_status(:unauthorized) - end - end - - describe 'GET /:id' do - context 'when logged in' do - subject do - response.parsed_body - end - - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}" - end - - it { - is_expected.to include('object' => 'supporter_note') - } - - it { - is_expected.to include('id' => supporter_note.id) - } - - it { - is_expected.to include('content' => 'Some content in our note') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('user' => user.id) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} # rubocop:disable Layout/LineLength - )) - } - end - - it 'returns http success when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}" - expect(response).to have_http_status(:unauthorized) - end - end + let(:supporter) { supporter_note.supporter } + let(:nonprofit) { supporter.nonprofit } + let(:supporter_note) { create(:supporter_note_with_fv_poverty_with_user) } + let(:user) { supporter_note.user } + + before do + supporter + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + describe "GET /" do + context "when logged in" do + subject(:json) do + response.parsed_body + end + + describe "with a response" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + is_expected.to include("data" => have_attributes(count: 1)) + } + + context "with first item" do + subject do + json["data"][0] + end + + it { + is_expected.to include("object" => "supporter_note") + } + + it { + is_expected.to include("id" => supporter_note.id) + } + + it { + is_expected.to include("content" => "Some content in our note") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("user" => user.id) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} # rubocop:disable Layout/LineLength + )) + } + end + end + + context "when paging" do + before do + 6.times do |i| + create(:supporter_note_with_fv_poverty_with_user, supporter: supporter, content: "content for #{i}") + end + sign_in user + end + + context "when on page 0" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes", params: {page: 0, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end + + context "when on page 1" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes", params: {page: 1, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq SupporterNote.order("id DESC").limit(5).pluck(:id) + } + end + + context "when on page 2" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes", params: {page: 2, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 2)) } + it { is_expected.to include("first_page" => false) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 2) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq SupporterNote.order("id DESC").limit(2).offset(5).pluck(:id) + } + end + end + end + + it "returns http unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes" + expect(response).to have_http_status(:unauthorized) + end + end + + describe "GET /:id" do + context "when logged in" do + subject do + response.parsed_body + end + + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}" + end + + it { + is_expected.to include("object" => "supporter_note") + } + + it { + is_expected.to include("id" => supporter_note.id) + } + + it { + is_expected.to include("content" => "Some content in our note") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("user" => user.id) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} # rubocop:disable Layout/LineLength + )) + } + end + + it "returns http success when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}" + expect(response).to have_http_status(:unauthorized) + end + end end diff --git a/spec/requests/api/supporters_controller_request_spec.rb b/spec/requests/api/supporters_controller_request_spec.rb index a174dbd858..7ccc670924 100644 --- a/spec/requests/api/supporters_controller_request_spec.rb +++ b/spec/requests/api/supporters_controller_request_spec.rb @@ -2,234 +2,234 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::SupportersController do - let(:supporter) { create(:supporter_with_fv_poverty) } - let(:nonprofit) { supporter.nonprofit } - let(:user) { create(:user) } - - before do - supporter - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - describe 'GET /' do - context 'when logged in successfully' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/supporters" - end - - it { - expect(response).to have_http_status(:success) - } - - describe 'with a response' do - subject(:json) do - response.parsed_body - end - - it { - is_expected.to include('data' => have_attributes(count: 1)) - } - - describe 'and a first item' do - subject(:first) { json['data'][0] } - - let(:id) { first['id'] } - - it { - is_expected.to include('object' => 'supporter') - } - - it { - is_expected.to include('id' => supporter.id) - } - - it { - is_expected.to include('name' => 'Fake Supporter Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('anonymous' => false) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('merged_into' => nil) - } - - it { - is_expected.to include('organization' => nil) - } - - it { - is_expected.to include('phone' => nil) - } - - it { - is_expected.to include('supporter_addresses' => [id]) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) - } - end - end - - context 'when paging' do - before do - supporter - 6.times do |i| - create(:supporter_with_fv_poverty, nonprofit: supporter.nonprofit, name: i, email: "email#{i}@email#{i}.com") - end - sign_in user - end - - context 'when on page 0' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/supporters", params: { page: 0, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end - - context 'when on page 1' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/supporters", params: { page: 1, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq Supporter.order('id DESC').limit(5).pluck(:id) - } - end - - context 'when on page 2' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/supporters", params: { page: 2, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 2)) } - it { is_expected.to include('first_page' => false) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 2) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq Supporter.order('id DESC').limit(2).offset(5).pluck(:id) - } - end - end - end - - it 'returns http unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/supporters" - expect(response).to have_http_status(:unauthorized) - end - end - - describe 'GET /:id' do - context 'when logged in' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - describe 'with a response' do - subject(:json) do - response.parsed_body - end - - let(:id) { json['id'] } - - it { - is_expected.to include('object' => 'supporter') - } - - it { - is_expected.to include('id' => supporter.id) - } - - it { - is_expected.to include('name' => 'Fake Supporter Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('anonymous' => false) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('merged_into' => nil) - } - - it { - is_expected.to include('organization' => nil) - } - - it { - is_expected.to include('phone' => nil) - } - - it { - is_expected.to include('supporter_addresses' => [id]) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) - } - end - end - - it 'returns unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}" - expect(response).to have_http_status(:unauthorized) - end - end + let(:supporter) { create(:supporter_with_fv_poverty) } + let(:nonprofit) { supporter.nonprofit } + let(:user) { create(:user) } + + before do + supporter + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + describe "GET /" do + context "when logged in successfully" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/supporters" + end + + it { + expect(response).to have_http_status(:success) + } + + describe "with a response" do + subject(:json) do + response.parsed_body + end + + it { + is_expected.to include("data" => have_attributes(count: 1)) + } + + describe "and a first item" do + subject(:first) { json["data"][0] } + + let(:id) { first["id"] } + + it { + is_expected.to include("object" => "supporter") + } + + it { + is_expected.to include("id" => supporter.id) + } + + it { + is_expected.to include("name" => "Fake Supporter Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("anonymous" => false) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("merged_into" => nil) + } + + it { + is_expected.to include("organization" => nil) + } + + it { + is_expected.to include("phone" => nil) + } + + it { + is_expected.to include("supporter_addresses" => [id]) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) + } + end + end + + context "when paging" do + before do + supporter + 6.times do |i| + create(:supporter_with_fv_poverty, nonprofit: supporter.nonprofit, name: i, email: "email#{i}@email#{i}.com") + end + sign_in user + end + + context "when on page 0" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/supporters", params: {page: 0, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end + + context "when on page 1" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/supporters", params: {page: 1, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq Supporter.order("id DESC").limit(5).pluck(:id) + } + end + + context "when on page 2" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/supporters", params: {page: 2, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 2)) } + it { is_expected.to include("first_page" => false) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 2) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq Supporter.order("id DESC").limit(2).offset(5).pluck(:id) + } + end + end + end + + it "returns http unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/supporters" + expect(response).to have_http_status(:unauthorized) + end + end + + describe "GET /:id" do + context "when logged in" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + describe "with a response" do + subject(:json) do + response.parsed_body + end + + let(:id) { json["id"] } + + it { + is_expected.to include("object" => "supporter") + } + + it { + is_expected.to include("id" => supporter.id) + } + + it { + is_expected.to include("name" => "Fake Supporter Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("anonymous" => false) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("merged_into" => nil) + } + + it { + is_expected.to include("organization" => nil) + } + + it { + is_expected.to include("phone" => nil) + } + + it { + is_expected.to include("supporter_addresses" => [id]) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) + } + end + end + + it "returns unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}" + expect(response).to have_http_status(:unauthorized) + end + end end diff --git a/spec/requests/api/tag_definitions_controller_request_spec.rb b/spec/requests/api/tag_definitions_controller_request_spec.rb index 3123153072..e15e27ccdf 100644 --- a/spec/requests/api/tag_definitions_controller_request_spec.rb +++ b/spec/requests/api/tag_definitions_controller_request_spec.rb @@ -2,198 +2,198 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::TagDefinitionsController do - let(:tag_definition) { create(:tag_definition_with_nonprofit) } - let(:nonprofit) { tag_definition.nonprofit } - let(:user) { create(:user) } - - before do - tag_definition - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - end - - describe 'GET /' do - let(:nonprofit) { Nonprofit.first } - - context 'when logged in successfully' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/tag_definitions" - end - - it { - expect(response).to have_http_status(:success) - } - - describe 'with a response' do - subject(:json) do - response.parsed_body - end - - it { - expect(json['data'].count).to eq 1 - } - - describe 'and a first item' do - subject(:first) { json['data'][0] } - - it { - is_expected.to include('object' => 'tag_definition') - } - - it { - is_expected.to include('id' => tag_definition.id) - } - - it { - is_expected.to include('name' => 'Tag Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} - )) - } - end - end - - context 'when paging' do - before do - tag_definition - 6.times do |i| - create(:tag_definition_with_nonprofit, - nonprofit: nonprofit, - name: i) - end - sign_in user - end - - context 'when on page 0' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/tag_definitions", params: { page: 0, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end - - context 'when on page 1' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/tag_definitions", params: { page: 1, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq TagDefinition.order('id DESC').limit(5).pluck(:id) - } - end - - context 'when on page 2' do - subject(:json) do - response.parsed_body - end - - before do - get "/api/nonprofits/#{nonprofit.id}/tag_definitions", params: { page: 2, per: 5 } - end - - it { is_expected.to include('data' => have_attributes(count: 2)) } - it { is_expected.to include('first_page' => false) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 2) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - - it { - expect(json['data'].pluck('id')).to eq TagDefinition.order('id DESC').limit(2).offset(5).pluck(:id) - } - end - end - end - - it 'returns http unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/tag_definitions" - expect(response).to have_http_status(:unauthorized) - end - end - - describe 'GET /:id' do - context 'when logged in' do - before do - sign_in user - get "/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}" - end - - it { - expect(response).to have_http_status(:success) - } - - describe 'with a response' do - subject do - response.parsed_body - end - - it { - is_expected.to include('object' => 'tag_definition') - } - - it { - is_expected.to include('id' => tag_definition.id) - } - - it { - is_expected.to include('name' => 'Tag Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} - )) - } - end - end - - it 'returns unauthorized when not logged in' do - get "/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}" - expect(response).to have_http_status(:unauthorized) - end - end + let(:tag_definition) { create(:tag_definition_with_nonprofit) } + let(:nonprofit) { tag_definition.nonprofit } + let(:user) { create(:user) } + + before do + tag_definition + user.roles.create(name: "nonprofit_associate", host: nonprofit) + end + + describe "GET /" do + let(:nonprofit) { Nonprofit.first } + + context "when logged in successfully" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/tag_definitions" + end + + it { + expect(response).to have_http_status(:success) + } + + describe "with a response" do + subject(:json) do + response.parsed_body + end + + it { + expect(json["data"].count).to eq 1 + } + + describe "and a first item" do + subject(:first) { json["data"][0] } + + it { + is_expected.to include("object" => "tag_definition") + } + + it { + is_expected.to include("id" => tag_definition.id) + } + + it { + is_expected.to include("name" => "Tag Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} + )) + } + end + end + + context "when paging" do + before do + tag_definition + 6.times do |i| + create(:tag_definition_with_nonprofit, + nonprofit: nonprofit, + name: i) + end + sign_in user + end + + context "when on page 0" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/tag_definitions", params: {page: 0, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end + + context "when on page 1" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/tag_definitions", params: {page: 1, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq TagDefinition.order("id DESC").limit(5).pluck(:id) + } + end + + context "when on page 2" do + subject(:json) do + response.parsed_body + end + + before do + get "/api/nonprofits/#{nonprofit.id}/tag_definitions", params: {page: 2, per: 5} + end + + it { is_expected.to include("data" => have_attributes(count: 2)) } + it { is_expected.to include("first_page" => false) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 2) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + + it { + expect(json["data"].pluck("id")).to eq TagDefinition.order("id DESC").limit(2).offset(5).pluck(:id) + } + end + end + end + + it "returns http unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/tag_definitions" + expect(response).to have_http_status(:unauthorized) + end + end + + describe "GET /:id" do + context "when logged in" do + before do + sign_in user + get "/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}" + end + + it { + expect(response).to have_http_status(:success) + } + + describe "with a response" do + subject do + response.parsed_body + end + + it { + is_expected.to include("object" => "tag_definition") + } + + it { + is_expected.to include("id" => tag_definition.id) + } + + it { + is_expected.to include("name" => "Tag Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://www\.example\.com/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} + )) + } + end + end + + it "returns unauthorized when not logged in" do + get "/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}" + expect(response).to have_http_status(:unauthorized) + end + end end diff --git a/spec/requests/api/ticket_levels_controller_request_spec.rb b/spec/requests/api/ticket_levels_controller_request_spec.rb index d741eeb4bc..c330213a97 100644 --- a/spec/requests/api/ticket_levels_controller_request_spec.rb +++ b/spec/requests/api/ticket_levels_controller_request_spec.rb @@ -2,191 +2,191 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::TicketLevelsController do - let(:event) { ticket_level_with_event_non_admin__order_3__not_deleted.event } - let(:nonprofit) { event.nonprofit } - let(:user) { create(:user) } - - let(:ticket_level_with_event_non_admin__order_3__not_deleted) do - create(:ticket_level_with_event_non_admin__order_3__not_deleted) - end - - before do - ticket_level_with_event_non_admin__order_3__not_deleted - end - - def index_base_path(nonprofit_id, event_id) - "/api/nonprofits/#{nonprofit_id}/events/#{event_id}/ticket_levels" - end - - def index_base_url(nonprofit_id, event_id) - "http://www.example.com#{index_base_path(nonprofit_id, event_id)}" - end - - describe 'GET /:id' do - let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } - - def base_path(nonprofit_id, event_id, ticket_level_id) - index_base_path(nonprofit_id, event_id) + "/#{ticket_level_id}" - end - - def base_url(nonprofit_id, event_id, ticket_level_id) - "http://www.example.com#{base_path(nonprofit_id, event_id, ticket_level_id)}" - end - - context 'with nonprofit user' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get base_path( - nonprofit.id, - event.id, - ticket_level_with_event_non_admin__order_3__not_deleted.id - ) - end - - it { - expect(response).to have_http_status(:success) - } - - include_context 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' - end - - context 'with event editor' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'event_editor', host: event) - sign_in user - get base_path( - nonprofit.id, - event.id, - ticket_level_with_event_non_admin__order_3__not_deleted.id - ) - end - - it { - expect(response).to have_http_status(:success) - } - - include_context 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' - end - - context 'with no user' do - it 'returns unauthorized' do - get base_path( - nonprofit.id, - event.id, - ticket_level_with_event_non_admin__order_3__not_deleted.id - ) - expect(response).to have_http_status(:unauthorized) - end - end - end - - describe 'GET /' do - context 'with nonprofit user' do - subject(:json) do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get index_base_path(nonprofit.id, event.id) - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(json['data'].count).to eq 1 - } - - # lazy testing but it works. - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 1) } - - describe 'for ticket_level_with_event_non_admin__order_3__not_deleted' do - subject(:first) do - json['data'][0] - end - - def base_path(nonprofit_id, event_id, ticket_level_id) - index_base_path(nonprofit_id, event_id) + "/#{ticket_level_id}" - end - - let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } - - def base_url(nonprofit_id, event_id, ticket_level_id) - "http://www.example.com#{base_path(nonprofit_id, event_id, ticket_level_id)}" - end - include_context 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' - end - end - - context 'with event editor' do - subject(:json) do - response.parsed_body - end - - before do - user.roles.create(name: 'event_editor', host: event) - sign_in user - get index_base_path(nonprofit.id, event.id) - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(json['data'].count).to eq 1 - } - - # lazy testing but it works. - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 1) } - - describe 'for ticket_level_with_event_non_admin__order_3__not_deleted' do - subject(:first) do - json['data'][0] - end - - let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } - - def base_path(nonprofit_id, event_id, ticket_level_id) - index_base_path(nonprofit_id, event_id) + "/#{ticket_level_id}" - end - - def base_url(nonprofit_id, event_id, ticket_level_id) - "http://www.example.com#{base_path(nonprofit_id, event_id, ticket_level_id)}" - end - - include_context 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' - end - end - - context 'with no user' do - it 'returns unauthorized' do - get index_base_path(nonprofit.id, event.id) - expect(response).to have_http_status(:unauthorized) - end - end - end + let(:event) { ticket_level_with_event_non_admin__order_3__not_deleted.event } + let(:nonprofit) { event.nonprofit } + let(:user) { create(:user) } + + let(:ticket_level_with_event_non_admin__order_3__not_deleted) do + create(:ticket_level_with_event_non_admin__order_3__not_deleted) + end + + before do + ticket_level_with_event_non_admin__order_3__not_deleted + end + + def index_base_path(nonprofit_id, event_id) + "/api/nonprofits/#{nonprofit_id}/events/#{event_id}/ticket_levels" + end + + def index_base_url(nonprofit_id, event_id) + "http://www.example.com#{index_base_path(nonprofit_id, event_id)}" + end + + describe "GET /:id" do + let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } + + def base_path(nonprofit_id, event_id, ticket_level_id) + index_base_path(nonprofit_id, event_id) + "/#{ticket_level_id}" + end + + def base_url(nonprofit_id, event_id, ticket_level_id) + "http://www.example.com#{base_path(nonprofit_id, event_id, ticket_level_id)}" + end + + context "with nonprofit user" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get base_path( + nonprofit.id, + event.id, + ticket_level_with_event_non_admin__order_3__not_deleted.id + ) + end + + it { + expect(response).to have_http_status(:success) + } + + include_context "json results for ticket_level_with_event_non_admin__order_3__not_deleted" + end + + context "with event editor" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "event_editor", host: event) + sign_in user + get base_path( + nonprofit.id, + event.id, + ticket_level_with_event_non_admin__order_3__not_deleted.id + ) + end + + it { + expect(response).to have_http_status(:success) + } + + include_context "json results for ticket_level_with_event_non_admin__order_3__not_deleted" + end + + context "with no user" do + it "returns unauthorized" do + get base_path( + nonprofit.id, + event.id, + ticket_level_with_event_non_admin__order_3__not_deleted.id + ) + expect(response).to have_http_status(:unauthorized) + end + end + end + + describe "GET /" do + context "with nonprofit user" do + subject(:json) do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get index_base_path(nonprofit.id, event.id) + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(json["data"].count).to eq 1 + } + + # lazy testing but it works. + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 1) } + + describe "for ticket_level_with_event_non_admin__order_3__not_deleted" do + subject(:first) do + json["data"][0] + end + + def base_path(nonprofit_id, event_id, ticket_level_id) + index_base_path(nonprofit_id, event_id) + "/#{ticket_level_id}" + end + + let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } + + def base_url(nonprofit_id, event_id, ticket_level_id) + "http://www.example.com#{base_path(nonprofit_id, event_id, ticket_level_id)}" + end + include_context "json results for ticket_level_with_event_non_admin__order_3__not_deleted" + end + end + + context "with event editor" do + subject(:json) do + response.parsed_body + end + + before do + user.roles.create(name: "event_editor", host: event) + sign_in user + get index_base_path(nonprofit.id, event.id) + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(json["data"].count).to eq 1 + } + + # lazy testing but it works. + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 1) } + + describe "for ticket_level_with_event_non_admin__order_3__not_deleted" do + subject(:first) do + json["data"][0] + end + + let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } + + def base_path(nonprofit_id, event_id, ticket_level_id) + index_base_path(nonprofit_id, event_id) + "/#{ticket_level_id}" + end + + def base_url(nonprofit_id, event_id, ticket_level_id) + "http://www.example.com#{base_path(nonprofit_id, event_id, ticket_level_id)}" + end + + include_context "json results for ticket_level_with_event_non_admin__order_3__not_deleted" + end + end + + context "with no user" do + it "returns unauthorized" do + get index_base_path(nonprofit.id, event.id) + expect(response).to have_http_status(:unauthorized) + end + end + end end diff --git a/spec/requests/api/transactions_controller_request_spec.rb b/spec/requests/api/transactions_controller_request_spec.rb index 35c7e5b950..fb5fc0d81a 100644 --- a/spec/requests/api/transactions_controller_request_spec.rb +++ b/spec/requests/api/transactions_controller_request_spec.rb @@ -2,174 +2,174 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" RSpec.describe Api::TransactionsController do - let(:nonprofit) { transaction_for_donation.nonprofit } - let(:user) { create(:user) } - let(:supporter) { transaction_for_donation.supporter } - - let(:transaction_for_donation) do - create(:transaction_for_donation) - end - - before do - transaction_for_donation - end - - def index_base_path(nonprofit_id) - "/api/nonprofits/#{nonprofit_id}/transactions" - end - - def index_base_url(nonprofit_id, _event_id) - "http://www.example.com#{index_base_path(nonprofit_id)}" - end - - describe 'GET /:id' do - let(:transaction) { transaction_for_donation } - - def base_path(nonprofit_id, transaction_id) - index_base_path(nonprofit_id) + "/#{transaction_id}" - end - - def base_url(nonprofit_id, transaction_id) - "http://www.example.com#{base_path(nonprofit_id, transaction_id)}" - end - - context 'with nonprofit user' do - subject do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get base_path( - nonprofit.id, - transaction.id - ) - end - - it { - expect(response).to have_http_status(:success) - } - - include_context 'with json results for transaction_for_donation' - end - - context 'with no user' do - it 'returns unauthorized' do - get base_path( - nonprofit.id, - transaction.id - ) - expect(response).to have_http_status(:unauthorized) - end - end - end - - # describe 'GET /:id/subtransaction' do - # def subtransaction_path(nonprofit_id, transaction_id) - # "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" - # end - - # def subtransaction_url(nonprofit_id, transaction_id) - # "http://www.example.com#{subtransaction_path(nonprofit_id, transaction_id)}" - # end - - # def payment_path(nonprofit_id, transaction_id, payment_id) - # "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" - # end - - # def payment_url(nonprofit_id, transaction_id, payment_id) - # "http://www.example.com#{payment_path(nonprofit_id, transaction_id, payment_id)}" - # end - - # let(:transaction) { transaction_for_donation } - # let(:subtransaction) { transaction.subtransaction } - # let(:supporter) { subtransaction.supporter } - - # let(:nonprofit) { subtransaction.nonprofit } - - # context 'with nonprofit user' do - # subject(:json) do - # response.parsed_body - # end - - # before do - # user.roles.create(name: 'nonprofit_associate', host: nonprofit) - # sign_in user - # get subtransaction_path( - # nonprofit.id, - # transaction.id - # ) - # end - - # it { - # expect(response).to have_http_status(:success) - # } - - # include_context 'with json results for subtransaction on transaction_for_donation' - # end - - # context 'with no user' do - # it 'returns unauthorized' do - # get subtransaction_path( - # nonprofit.id, - # transaction.id - # ) - # expect(response).to have_http_status(:unauthorized) - # end - # end - # end - - describe 'GET /' do - context 'with nonprofit user' do - subject(:json) do - response.parsed_body - end - - before do - user.roles.create(name: 'nonprofit_associate', host: nonprofit) - sign_in user - get index_base_path(nonprofit.id) - end - - it { - expect(response).to have_http_status(:success) - } - - it { expect(json['data'].count).to eq 1 } - - describe 'for transaction_for_donation' do - subject(:first) do - json['data'].first - end - - def base_path(nonprofit_id, transaction_id) - index_base_path(nonprofit_id) + "/#{transaction_id}" - end - - let(:transaction) { transaction_for_donation } - - def base_url(nonprofit_id, transaction_id) - "http://www.example.com#{base_path(nonprofit_id, transaction_id)}" - end - include_context 'with json results for transaction_for_donation' - end - - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 1) } - end - - context 'with no user' do - it 'returns unauthorized' do - get index_base_path(nonprofit.id) - expect(response).to have_http_status(:unauthorized) - end - end - end + let(:nonprofit) { transaction_for_donation.nonprofit } + let(:user) { create(:user) } + let(:supporter) { transaction_for_donation.supporter } + + let(:transaction_for_donation) do + create(:transaction_for_donation) + end + + before do + transaction_for_donation + end + + def index_base_path(nonprofit_id) + "/api/nonprofits/#{nonprofit_id}/transactions" + end + + def index_base_url(nonprofit_id, _event_id) + "http://www.example.com#{index_base_path(nonprofit_id)}" + end + + describe "GET /:id" do + let(:transaction) { transaction_for_donation } + + def base_path(nonprofit_id, transaction_id) + index_base_path(nonprofit_id) + "/#{transaction_id}" + end + + def base_url(nonprofit_id, transaction_id) + "http://www.example.com#{base_path(nonprofit_id, transaction_id)}" + end + + context "with nonprofit user" do + subject do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get base_path( + nonprofit.id, + transaction.id + ) + end + + it { + expect(response).to have_http_status(:success) + } + + include_context "with json results for transaction_for_donation" + end + + context "with no user" do + it "returns unauthorized" do + get base_path( + nonprofit.id, + transaction.id + ) + expect(response).to have_http_status(:unauthorized) + end + end + end + + # describe 'GET /:id/subtransaction' do + # def subtransaction_path(nonprofit_id, transaction_id) + # "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" + # end + + # def subtransaction_url(nonprofit_id, transaction_id) + # "http://www.example.com#{subtransaction_path(nonprofit_id, transaction_id)}" + # end + + # def payment_path(nonprofit_id, transaction_id, payment_id) + # "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" + # end + + # def payment_url(nonprofit_id, transaction_id, payment_id) + # "http://www.example.com#{payment_path(nonprofit_id, transaction_id, payment_id)}" + # end + + # let(:transaction) { transaction_for_donation } + # let(:subtransaction) { transaction.subtransaction } + # let(:supporter) { subtransaction.supporter } + + # let(:nonprofit) { subtransaction.nonprofit } + + # context 'with nonprofit user' do + # subject(:json) do + # response.parsed_body + # end + + # before do + # user.roles.create(name: 'nonprofit_associate', host: nonprofit) + # sign_in user + # get subtransaction_path( + # nonprofit.id, + # transaction.id + # ) + # end + + # it { + # expect(response).to have_http_status(:success) + # } + + # include_context 'with json results for subtransaction on transaction_for_donation' + # end + + # context 'with no user' do + # it 'returns unauthorized' do + # get subtransaction_path( + # nonprofit.id, + # transaction.id + # ) + # expect(response).to have_http_status(:unauthorized) + # end + # end + # end + + describe "GET /" do + context "with nonprofit user" do + subject(:json) do + response.parsed_body + end + + before do + user.roles.create(name: "nonprofit_associate", host: nonprofit) + sign_in user + get index_base_path(nonprofit.id) + end + + it { + expect(response).to have_http_status(:success) + } + + it { expect(json["data"].count).to eq 1 } + + describe "for transaction_for_donation" do + subject(:first) do + json["data"].first + end + + def base_path(nonprofit_id, transaction_id) + index_base_path(nonprofit_id) + "/#{transaction_id}" + end + + let(:transaction) { transaction_for_donation } + + def base_url(nonprofit_id, transaction_id) + "http://www.example.com#{base_path(nonprofit_id, transaction_id)}" + end + include_context "with json results for transaction_for_donation" + end + + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 1) } + end + + context "with no user" do + it "returns unauthorized" do + get index_base_path(nonprofit.id) + expect(response).to have_http_status(:unauthorized) + end + end + end end diff --git a/spec/requests/api/users_controller_request_spec.rb b/spec/requests/api/users_controller_request_spec.rb index 068a9eb337..20dfdb5f38 100644 --- a/spec/requests/api/users_controller_request_spec.rb +++ b/spec/requests/api/users_controller_request_spec.rb @@ -2,39 +2,39 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe Api::UsersController do - describe 'GET /api/users/current' do - context 'when not logged in' do - before { get '/api/users/current' } - - it { - expect(response).to have_http_status(:unauthorized) - } - - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } - end - - context 'when logged in' do - before do - sign_in create(:user) - get '/api/users/current' - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } - - it { - expect(response.parsed_body['id']).to be_a Numeric - } - end - end + describe "GET /api/users/current" do + context "when not logged in" do + before { get "/api/users/current" } + + it { + expect(response).to have_http_status(:unauthorized) + } + + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } + end + + context "when logged in" do + before do + sign_in create(:user) + get "/api/users/current" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } + + it { + expect(response.parsed_body["id"]).to be_a Numeric + } + end + end end diff --git a/spec/requests/api/users_controller_spec.rb b/spec/requests/api/users_controller_spec.rb index 522a84629e..8941046b25 100644 --- a/spec/requests/api/users_controller_spec.rb +++ b/spec/requests/api/users_controller_spec.rb @@ -2,39 +2,39 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE -require 'rails_helper' +require "rails_helper" describe Api::UsersController do - describe 'GET /api/users/current' do - context 'when not logged in' do - before { get '/api/users/current' } - - it { - expect(response).to have_http_status(:unauthorized) - } - - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } - end - - context 'when logged in' do - before do - sign_in create(:user) - get '/api/users/current' - end - - it { - expect(response).to have_http_status(:success) - } - - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } - - it { - expect(response.parsed_body['id']).to be_a Numeric - } - end - end + describe "GET /api/users/current" do + context "when not logged in" do + before { get "/api/users/current" } + + it { + expect(response).to have_http_status(:unauthorized) + } + + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } + end + + context "when logged in" do + before do + sign_in create(:user) + get "/api/users/current" + end + + it { + expect(response).to have_http_status(:success) + } + + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } + + it { + expect(response.parsed_body["id"]).to be_a Numeric + } + end + end end diff --git a/spec/requests/direct_uploads_controller_spec.rb b/spec/requests/direct_uploads_controller_spec.rb index d8d8ddee33..ae97f9d1e2 100644 --- a/spec/requests/direct_uploads_controller_spec.rb +++ b/spec/requests/direct_uploads_controller_spec.rb @@ -2,34 +2,34 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe DirectUploadsController do - describe 'POST /rails/active_storage/direct_uploads' do - context 'when not logged in' do - it { - expect { post '/rails/active_storage/direct_uploads.json' }.to raise_error(AuthenticationError) - } - end + describe "POST /rails/active_storage/direct_uploads" do + context "when not logged in" do + it { + expect { post "/rails/active_storage/direct_uploads.json" }.to raise_error(AuthenticationError) + } + end - context 'when logged in but not confirmed' do - before do - sign_in create(:user) - end + context "when logged in but not confirmed" do + before do + sign_in create(:user) + end - it { - expect { post '/rails/active_storage/direct_uploads.json' }.to raise_error(AuthenticationError) - } - end + it { + expect { post "/rails/active_storage/direct_uploads.json" }.to raise_error(AuthenticationError) + } + end - context 'when logged in but confirmed' do - before do - sign_in create(:confirmed_user) - end + context "when logged in but confirmed" do + before do + sign_in create(:confirmed_user) + end - it { - expect { post '/rails/active_storage/direct_uploads.json' }.to_not raise_error(AuthenticationError) - } - end - end + it { + expect { post "/rails/active_storage/direct_uploads.json" }.to_not raise_error(AuthenticationError) + } + end + end end diff --git a/spec/requests/events_controller_request_spec.rb b/spec/requests/events_controller_request_spec.rb index d31bb5ac6b..a899f16b97 100644 --- a/spec/requests/events_controller_request_spec.rb +++ b/spec/requests/events_controller_request_spec.rb @@ -1,44 +1,44 @@ # frozen_string_literal: true # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require 'rails_helper' +require "rails_helper" describe EventsController do - def event_setup - nonprofit = create(:nonprofit_base, register_np_only: true) - OpenStruct.new( # rubocop:disable Style/OpenStructUse - deleted: create(:event_base, nonprofit: nonprofit, deleted: true), - last: create(:event_base, nonprofit: nonprofit, name: 'Last event'), - first: create(:event_base, nonprofit: nonprofit, name: 'First event'), - nonprofit: nonprofit - ) - end - - def login_as_associate(nonprofit) - user = create(:user_base, roles: [build(:role_base, name: 'nonprofit_associate', host: nonprofit)]) - sign_in user - end - - it 'contains the events in order from first, to last with no deleted events' do - events = event_setup - - login_as_associate(events.nonprofit) - - get "/nonprofits/#{events.nonprofit.id}/events/name_and_id" - - result = response.parsed_body - - expect(result).to include_json( - [ - { - name: events.first.name, - id: events.first.id - }, - { - name: events.last.name, - id: events.last.id - } - ] - ) - end + def event_setup + nonprofit = create(:nonprofit_base, register_np_only: true) + OpenStruct.new( # rubocop:disable Style/OpenStructUse + deleted: create(:event_base, nonprofit: nonprofit, deleted: true), + last: create(:event_base, nonprofit: nonprofit, name: "Last event"), + first: create(:event_base, nonprofit: nonprofit, name: "First event"), + nonprofit: nonprofit + ) + end + + def login_as_associate(nonprofit) + user = create(:user_base, roles: [build(:role_base, name: "nonprofit_associate", host: nonprofit)]) + sign_in user + end + + it "contains the events in order from first, to last with no deleted events" do + events = event_setup + + login_as_associate(events.nonprofit) + + get "/nonprofits/#{events.nonprofit.id}/events/name_and_id" + + result = response.parsed_body + + expect(result).to include_json( + [ + { + name: events.first.name, + id: events.first.id + }, + { + name: events.last.name, + id: events.last.id + } + ] + ) + end end diff --git a/spec/requests/good_job_protection_spec.rb b/spec/requests/good_job_protection_spec.rb index 8ca132116d..ac56adf7fa 100644 --- a/spec/requests/good_job_protection_spec.rb +++ b/spec/requests/good_job_protection_spec.rb @@ -2,31 +2,31 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -describe 'GoodJob protection' do - let(:user) { create(:user) } +require "rails_helper" +describe "GoodJob protection" do + let(:user) { create(:user) } - describe 'when it is a super_admin' do - it 'shows the good job dashboard' do - user.roles.create(name: 'super_admin') - sign_in user - get('/good_job/jobs') - expect(response).to have_http_status(:success) - end - end + describe "when it is a super_admin" do + it "shows the good job dashboard" do + user.roles.create(name: "super_admin") + sign_in user + get("/good_job/jobs") + expect(response).to have_http_status(:success) + end + end - describe 'when not logged in' do - it 'is redirected to log in page' do # rubocop:disable RSpec/MultipleExpectations - get('/good_job/jobs') - expect(response).to have_http_status(:redirect) - expect(response.header['location']).to eq 'http://www.example.com/users/sign_in' - end - end + describe "when not logged in" do + it "is redirected to log in page" do # rubocop:disable RSpec/MultipleExpectations + get("/good_job/jobs") + expect(response).to have_http_status(:redirect) + expect(response.header["location"]).to eq "http://www.example.com/users/sign_in" + end + end - describe 'when logged in but is not super_admin' do - it 'raises RoutingError' do - sign_in user - expect { get('/good_job/jobs') }.to raise_error(ActionController::RoutingError) - end - end + describe "when logged in but is not super_admin" do + it "raises RoutingError" do + sign_in user + expect { get("/good_job/jobs") }.to raise_error(ActionController::RoutingError) + end + end end diff --git a/spec/requests/maintenance_spec.rb b/spec/requests/maintenance_spec.rb index fe9fbbe8cc..bab39db11c 100644 --- a/spec/requests/maintenance_spec.rb +++ b/spec/requests/maintenance_spec.rb @@ -2,119 +2,119 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' -require 'controllers/support/shared_user_context' +require "rails_helper" +require "controllers/support/shared_user_context" # rubocop:disable RSpec/InstanceVariable -describe 'Maintenance Mode' do - page = 'http://commet' - token = 'thoathioa' - include_context :shared_user_context - - describe SettingsController, type: :controller do - describe '(Settings is just a basic example controller)' - it 'not in maintenance mode' do - get :index - expect(response).to have_http_status(:found) - end - - describe 'in maintenance' do - before do - Houdini.maintenance = Houdini::Maintenance.new(active: true, token: token, page: page) - end - - it 'redirects for settings' do - get :index - expect(response).to have_attributes(code: '302', location: page) - end - - it 'allows access to non-sign_in pages if youre logged in' do - sign_in user_as_np_associate - get :index - expect(response).to have_http_status(:ok) - end - end - end - - describe Users::SessionsController, type: :controller do - after do - Houdini.maintenance.active = false - end - - describe 'in maintenance' do - include_context :shared_user_context - - before do - @request.env['devise.mapping'] = Devise.mappings[:user] - end - - describe 'in maintenance' do - before do - Houdini.maintenance = Houdini::Maintenance.new(active: true, token: token, page: page) - end - - describe 'redirects sign_in if the token is wrong' do - subject do - get(:new, params: { maintenance_token: "#{token}3" }) - response - end - - it { is_expected.to have_attributes(code: '302', location: page) } - end - - describe 'redirects to sign_in' do - subject do - get(:new) - response - end - - it { is_expected.to have_attributes(code: '302', location: page) } - end - - describe 'redirects to sign_in if token passed on wrong param' do - subject do - get(:new, params: { maintnancerwrwer_token: token.to_s }) - response - end - - it { is_expected.to have_attributes(code: '302', location: page) } - end - - describe 'allows sign_in if the token is passed' do - subject do - get(:new, params: { maintenance_token: token.to_s }) - response - end - - it { is_expected.to have_attributes(code: '200') } - end - - describe 'allows sign_in.json if the token is passed' do - subject do - get(:new, params: { maintenance_token: token.to_s, format: 'json' }) - response - end - - it { is_expected.to have_attributes(code: '200') } - end - end - end - - describe 'in maintenance without maintenance_token set' do - before do - @request.env['devise.mapping'] = Devise.mappings[:user] - Houdini.maintenance = Houdini::Maintenance.new(active: true, token: nil, page: page) - end - - describe 'redirects sign_in if the token is nil' do - subject do - get(:new) - response - end - - it { is_expected.to have_attributes(code: '302', location: page) } - end - end - end +describe "Maintenance Mode" do + page = "http://commet" + token = "thoathioa" + include_context :shared_user_context + + describe SettingsController, type: :controller do + describe "(Settings is just a basic example controller)" + it "not in maintenance mode" do + get :index + expect(response).to have_http_status(:found) + end + + describe "in maintenance" do + before do + Houdini.maintenance = Houdini::Maintenance.new(active: true, token: token, page: page) + end + + it "redirects for settings" do + get :index + expect(response).to have_attributes(code: "302", location: page) + end + + it "allows access to non-sign_in pages if youre logged in" do + sign_in user_as_np_associate + get :index + expect(response).to have_http_status(:ok) + end + end + end + + describe Users::SessionsController, type: :controller do + after do + Houdini.maintenance.active = false + end + + describe "in maintenance" do + include_context :shared_user_context + + before do + @request.env["devise.mapping"] = Devise.mappings[:user] + end + + describe "in maintenance" do + before do + Houdini.maintenance = Houdini::Maintenance.new(active: true, token: token, page: page) + end + + describe "redirects sign_in if the token is wrong" do + subject do + get(:new, params: {maintenance_token: "#{token}3"}) + response + end + + it { is_expected.to have_attributes(code: "302", location: page) } + end + + describe "redirects to sign_in" do + subject do + get(:new) + response + end + + it { is_expected.to have_attributes(code: "302", location: page) } + end + + describe "redirects to sign_in if token passed on wrong param" do + subject do + get(:new, params: {maintnancerwrwer_token: token.to_s}) + response + end + + it { is_expected.to have_attributes(code: "302", location: page) } + end + + describe "allows sign_in if the token is passed" do + subject do + get(:new, params: {maintenance_token: token.to_s}) + response + end + + it { is_expected.to have_attributes(code: "200") } + end + + describe "allows sign_in.json if the token is passed" do + subject do + get(:new, params: {maintenance_token: token.to_s, format: "json"}) + response + end + + it { is_expected.to have_attributes(code: "200") } + end + end + end + + describe "in maintenance without maintenance_token set" do + before do + @request.env["devise.mapping"] = Devise.mappings[:user] + Houdini.maintenance = Houdini::Maintenance.new(active: true, token: nil, page: page) + end + + describe "redirects sign_in if the token is nil" do + subject do + get(:new) + response + end + + it { is_expected.to have_attributes(code: "302", location: page) } + end + end + end end # rubocop:enable all diff --git a/spec/requests/nonprofits/direct_debit_details_spec.rb b/spec/requests/nonprofits/direct_debit_details_spec.rb index 582215e74e..0e47cc99ef 100644 --- a/spec/requests/nonprofits/direct_debit_details_spec.rb +++ b/spec/requests/nonprofits/direct_debit_details_spec.rb @@ -2,44 +2,44 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" describe DirectDebitDetailsController, type: :request do - describe 'POST /sepa' do - let!(:nonprofit) { Nonprofit.create(name: 'new', city: 'NY', state_code: 'NY') } + describe "POST /sepa" do + let!(:nonprofit) { Nonprofit.create(name: "new", city: "NY", state_code: "NY") } let(:supporter) { Supporter.create(nonprofit: nonprofit) } let(:valid_params) do { supporter_id: supporter.id, sepa_params: { - iban: 'iban', - bic: 'bic', - name: 'name' + iban: "iban", + bic: "bic", + name: "name" } } end - describe 'requires params' do - it 'is valid when sepa_params, donation_id and supporter_id are present' do - post '/sepa', params: valid_params + describe "requires params" do + it "is valid when sepa_params, donation_id and supporter_id are present" do + post "/sepa", params: valid_params assert_response 200 - assert_nil JSON.parse(@response.body)['errors'] + assert_nil JSON.parse(@response.body)["errors"] end - it 'is not valid without sepa_params' do - post '/sepa', params: valid_params.except(:sepa_params) + it "is not valid without sepa_params" do + post "/sepa", params: valid_params.except(:sepa_params) assert_response 422 - assert_equal ['sepa_params required'], JSON.parse(@response.body)['errors'] + assert_equal ["sepa_params required"], JSON.parse(@response.body)["errors"] end - it 'is not valid without supporter_id' do - post '/sepa', params: valid_params.except(:supporter_id) + it "is not valid without supporter_id" do + post "/sepa", params: valid_params.except(:supporter_id) assert_response 422 - assert_equal ['supporter_id required'], JSON.parse(@response.body)['errors'] + assert_equal ["supporter_id required"], JSON.parse(@response.body)["errors"] end end end diff --git a/spec/requests/users/sessions_controller_request_spec.rb b/spec/requests/users/sessions_controller_request_spec.rb index ed8d51a67b..8f88632d0e 100644 --- a/spec/requests/users/sessions_controller_request_spec.rb +++ b/spec/requests/users/sessions_controller_request_spec.rb @@ -2,33 +2,33 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE -require 'rails_helper' +require "rails_helper" describe Users::SessionsController do - describe 'POST /users/sign_in' do - context 'with successful login' do - let(:user) { create(:user) } - let(:json) { response.parsed_body } + describe "POST /users/sign_in" do + context "with successful login" do + let(:user) { create(:user) } + let(:json) { response.parsed_body } - before do - post '/users/sign_in', params: { user: { email: user.email, password: user.password } } - end + before do + post "/users/sign_in", params: {user: {email: user.email, password: user.password}} + end - it { - expect(response).to have_http_status(:ok) - } + it { + expect(response).to have_http_status(:ok) + } - it { - expect(response).to have_attributes(content_type: starting_with('application/json')) - } + it { + expect(response).to have_attributes(content_type: starting_with("application/json")) + } - it { - expect(json).to eq({ - 'id' => user.id, - 'object' => 'user', - 'roles' => [] - }) - } - end - end + it { + expect(json).to eq({ + "id" => user.id, + "object" => "user", + "roles" => [] + }) + } + end + end end diff --git a/spec/routing/campaign_locateable_spec.rb b/spec/routing/campaign_locateable_spec.rb index 1dccbe8d79..79727382a2 100644 --- a/spec/routing/campaign_locateable_spec.rb +++ b/spec/routing/campaign_locateable_spec.rb @@ -2,26 +2,26 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -describe 'campaign_locatable' do - # for reasons I don't understand, routing specs don't have the defautlt_url_options set so we set them here. - around do |example| - original_url_options = Rails.application.routes.default_url_options.dup - Rails.application.routes.default_url_options.merge!(protocol: 'http', host: 'test.example.com', port: 3001) - example.run - Rails.application.routes.default_url_options = original_url_options - end +describe "campaign_locatable" do + # for reasons I don't understand, routing specs don't have the defautlt_url_options set so we set them here. + around do |example| + original_url_options = Rails.application.routes.default_url_options.dup + Rails.application.routes.default_url_options.merge!(protocol: "http", host: "test.example.com", port: 3001) + example.run + Rails.application.routes.default_url_options = original_url_options + end - let(:campaign) { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } - let(:nonprofit) { campaign.nonprofit } + let(:campaign) { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } + let(:nonprofit) { campaign.nonprofit } - it 'routes with campaign' do - expect(get: campaign_locateable_path(campaign)).to route_to( - controller: 'campaigns', - action: 'show', - state_code: nonprofit.state_code_slug, city: nonprofit.city_slug, name: nonprofit.slug, - campaign_slug: campaign.slug - ) - end + it "routes with campaign" do + expect(get: campaign_locateable_path(campaign)).to route_to( + controller: "campaigns", + action: "show", + state_code: nonprofit.state_code_slug, city: nonprofit.city_slug, name: nonprofit.slug, + campaign_slug: campaign.slug + ) + end end diff --git a/spec/routing/event_locateable_spec.rb b/spec/routing/event_locateable_spec.rb index c5e201206c..3e3c9ba7eb 100644 --- a/spec/routing/event_locateable_spec.rb +++ b/spec/routing/event_locateable_spec.rb @@ -2,26 +2,26 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -describe 'event_locatable' do - # for reasons I don't understand, routing specs don't have the defautlt_url_options set so we set them here. - around do |example| - original_url_options = Rails.application.routes.default_url_options.dup - Rails.application.routes.default_url_options.merge!(protocol: 'http', host: 'test.example.com', port: 3001) - example.run - Rails.application.routes.default_url_options = original_url_options - end +describe "event_locatable" do + # for reasons I don't understand, routing specs don't have the defautlt_url_options set so we set them here. + around do |example| + original_url_options = Rails.application.routes.default_url_options.dup + Rails.application.routes.default_url_options.merge!(protocol: "http", host: "test.example.com", port: 3001) + example.run + Rails.application.routes.default_url_options = original_url_options + end - let(:event) { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } - let(:nonprofit) { event.nonprofit } + let(:event) { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } + let(:nonprofit) { event.nonprofit } - it 'routes with event' do - expect(get: event_locateable_path(event)).to route_to( - controller: 'events', - action: 'show', - state_code: nonprofit.state_code_slug, city: nonprofit.city_slug, name: nonprofit.slug, - event_slug: event.slug - ) - end + it "routes with event" do + expect(get: event_locateable_path(event)).to route_to( + controller: "events", + action: "show", + state_code: nonprofit.state_code_slug, city: nonprofit.city_slug, name: nonprofit.slug, + event_slug: event.slug + ) + end end diff --git a/spec/routing/state_code_routing_spec.rb b/spec/routing/state_code_routing_spec.rb index a156001fb2..0fccbe66ef 100644 --- a/spec/routing/state_code_routing_spec.rb +++ b/spec/routing/state_code_routing_spec.rb @@ -4,40 +4,40 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE require "rails_helper" -describe 'Routing by state code in lower case', type: :routing do - it 'routes by state-codes for lower case' do - expect(post: "/wi/appleton/name").to route_to( - controller: 'nonprofits', - action: "show", - state_code: "wi", - city: "appleton", - name: "name" - ) - end - - it 'routes by state-codes in upper case' do - expect(get: "/WI/appleton/fox-valley-fighting-poverty").to route_to( - controller: 'nonprofits', - action: "show", - state_code: "WI", - city: "appleton", - name: "fox-valley-fighting-poverty" - ) - end - - it 'fails to route for an incorrect upper case two letter state' do - expect(get: "/FR/appleton/fox-valley-fighting-poverty").to_not be_routable - end - - it 'fails to route for an incorrect lower case two letter state' do - expect(post: "/us/appleton/fox-valley-fighting-poverty").to_not be_routable - end +describe "Routing by state code in lower case", type: :routing do + it "routes by state-codes for lower case" do + expect(post: "/wi/appleton/name").to route_to( + controller: "nonprofits", + action: "show", + state_code: "wi", + city: "appleton", + name: "name" + ) + end - it 'fails to route if a valid state code is in the middle of the state_code' do - expect(get: '/hoho/cleveland/interesting-name').to_not be_routable - end + it "routes by state-codes in upper case" do + expect(get: "/WI/appleton/fox-valley-fighting-poverty").to route_to( + controller: "nonprofits", + action: "show", + state_code: "WI", + city: "appleton", + name: "fox-valley-fighting-poverty" + ) + end - it 'fails to route if a valid state code is in the middle of the state_code regardless of the letter case' do - expect(get: '/HOho/cleveland/interesting-name').to_not be_routable - end + it "fails to route for an incorrect upper case two letter state" do + expect(get: "/FR/appleton/fox-valley-fighting-poverty").to_not be_routable + end + + it "fails to route for an incorrect lower case two letter state" do + expect(post: "/us/appleton/fox-valley-fighting-poverty").to_not be_routable + end + + it "fails to route if a valid state code is in the middle of the state_code" do + expect(get: "/hoho/cleveland/interesting-name").to_not be_routable + end + + it "fails to route if a valid state code is in the middle of the state_code regardless of the letter case" do + expect(get: "/HOho/cleveland/interesting-name").to_not be_routable + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1bc88f414c..3b07394280 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,8 +13,8 @@ # it. # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration -require 'timecop' -require 'support/expect' +require "timecop" +require "support/expect" RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate @@ -49,57 +49,55 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = "doc" + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = "doc" - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end - - config.example_status_persistence_file_path = 'tmp/example_status_persistence_file_path.txt' + config.example_status_persistence_file_path = "tmp/example_status_persistence_file_path.txt" config.include Expect end diff --git a/spec/support/contexts.rb b/spec/support/contexts.rb index ee5103c892..569fbf301d 100644 --- a/spec/support/contexts.rb +++ b/spec/support/contexts.rb @@ -3,6 +3,6 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE - Dir["#{File.dirname (__FILE__)}/contexts/*"].each do |file| - require_relative "./contexts/#{File.basename(file, ".rb")}" +Dir["#{File.dirname(__FILE__)}/contexts/*"].each do |file| + require_relative "./contexts/#{File.basename(file, ".rb")}" end diff --git a/spec/support/contexts/general_shared_user_context.rb b/spec/support/contexts/general_shared_user_context.rb index 3093668aba..42183ae5d6 100644 --- a/spec/support/contexts/general_shared_user_context.rb +++ b/spec/support/contexts/general_shared_user_context.rb @@ -27,7 +27,7 @@ __create(:campaign_editor, campaign) end - let(:confirmed_user) do + let(:confirmed_user) do force_create(:user, confirmed_at: Time.current) end @@ -46,42 +46,42 @@ end let(:all_users) do - { user_as_np_admin: user_as_np_admin, - user_as_other_np_admin: user_as_other_np_admin, - user_as_np_associate: user_as_np_associate, - user_as_other_np_associate: user_as_other_np_associate, - unauth_user: unauth_user, - campaign_editor: campaign_editor, - event_editor: event_editor, - super_admin: super_admin, - user_with_profile: user_with_profile } + {user_as_np_admin: user_as_np_admin, + user_as_other_np_admin: user_as_other_np_admin, + user_as_np_associate: user_as_np_associate, + user_as_other_np_associate: user_as_other_np_associate, + unauth_user: unauth_user, + campaign_editor: campaign_editor, + event_editor: event_editor, + super_admin: super_admin, + user_with_profile: user_with_profile} end let(:roles__open_to_all) do [nil, :user_as_np_admin, - :user_as_other_np_admin, - :user_as_np_associate, - :user_as_other_np_associate, - :unauth_user, - :campaign_editor, - :event_editor, - :super_admin, - :user_with_profile] + :user_as_other_np_admin, + :user_as_np_associate, + :user_as_other_np_associate, + :unauth_user, + :campaign_editor, + :event_editor, + :super_admin, + :user_with_profile] end let(:roles__open_to_np_associate) do %i[user_as_np_admin - user_as_np_associate + user_as_np_associate - super_admin] + super_admin] end let(:roles__open_to_campaign_editor) do %i[user_as_np_admin - user_as_np_associate - campaign_editor - super_admin] + user_as_np_associate + campaign_editor + super_admin] end def __create(name, host) diff --git a/spec/support/contexts/payment_context.rb b/spec/support/contexts/payment_context.rb index c6f8a0425a..483aee6faf 100644 --- a/spec/support/contexts/payment_context.rb +++ b/spec/support/contexts/payment_context.rb @@ -3,95 +3,95 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -shared_context 'with json results for first payment on transaction_for_donation' do - subject(:payment_json) do - json - end - - around do |ex| - Timecop.freeze(2020, 5, 4) do - ex.run - end - end - - it { - is_expected.to include('id' => match_houid('offtrxchrg')) - } - - it { - is_expected.to include('type' => 'payment') - } - - it { - is_expected.to include('object' => 'offline_transaction_charge') - } - - it { - is_expected.to include('created' => Time.current.to_i) - } - - it { - is_expected.to include('gross_amount' => { - 'cents' => 4000, - 'currency' => 'usd' - }) - } - - it { - is_expected.to include('fee_total' => { - 'cents' => 300, - 'currency' => 'usd' - }) - } - - it { - is_expected.to include('net_amount' => { - 'cents' => 3700, - 'currency' => 'usd' - }) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('subtransaction' => { - 'id' => match_houid('offlinetrx'), - 'object' => 'offline_transaction', - 'type' => 'subtransaction' - }) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include( - 'url' => - payment_url( - nonprofit.id, - transaction.id, - transaction.subtransaction.payments.first.paymentable.id - ) - ) - } - - # describe('subtransaction') do - # subject { - # payment_json["subtransaction"] - # } - # it { - # is_expected.to include('object' => 'offline_transaction') - # } - - # it { - # is_expected.to include('id' => match_houid('offlinetrx')) - # } - - # it { - # is_expected.to include('type' => 'subtransaction') - # } - # end +shared_context "with json results for first payment on transaction_for_donation" do + subject(:payment_json) do + json + end + + around do |ex| + Timecop.freeze(2020, 5, 4) do + ex.run + end + end + + it { + is_expected.to include("id" => match_houid("offtrxchrg")) + } + + it { + is_expected.to include("type" => "payment") + } + + it { + is_expected.to include("object" => "offline_transaction_charge") + } + + it { + is_expected.to include("created" => Time.current.to_i) + } + + it { + is_expected.to include("gross_amount" => { + "cents" => 4000, + "currency" => "usd" + }) + } + + it { + is_expected.to include("fee_total" => { + "cents" => 300, + "currency" => "usd" + }) + } + + it { + is_expected.to include("net_amount" => { + "cents" => 3700, + "currency" => "usd" + }) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("subtransaction" => { + "id" => match_houid("offlinetrx"), + "object" => "offline_transaction", + "type" => "subtransaction" + }) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include( + "url" => + payment_url( + nonprofit.id, + transaction.id, + transaction.subtransaction.payments.first.paymentable.id + ) + ) + } + + # describe('subtransaction') do + # subject { + # payment_json["subtransaction"] + # } + # it { + # is_expected.to include('object' => 'offline_transaction') + # } + + # it { + # is_expected.to include('id' => match_houid('offlinetrx')) + # } + + # it { + # is_expected.to include('type' => 'subtransaction') + # } + # end end diff --git a/spec/support/contexts/shared_donation_charge_context.rb b/spec/support/contexts/shared_donation_charge_context.rb index 2022389a2b..712db1087c 100644 --- a/spec/support/contexts/shared_donation_charge_context.rb +++ b/spec/support/contexts/shared_donation_charge_context.rb @@ -2,13 +2,13 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'stripe_mock' +require "stripe_mock" RSpec.shared_context :shared_donation_charge_context do - let(:nonprofit) { force_create(:nm_justice, name: 'nonprofit name', slug: 'nonprofit_nameo') } + let(:nonprofit) { force_create(:nm_justice, name: "nonprofit name", slug: "nonprofit_nameo") } let(:other_nonprofit) { force_create(:fv_poverty) } - let(:supporter) { force_create(:supporter, nonprofit: nonprofit, locale: 'locale_one') } - let(:other_nonprofit_supporter) { force_create(:supporter, nonprofit: other_nonprofit, locale: 'locale_two') } + let(:supporter) { force_create(:supporter, nonprofit: nonprofit, locale: "locale_one") } + let(:other_nonprofit_supporter) { force_create(:supporter, nonprofit: other_nonprofit, locale: "locale_two") } let(:card) { force_create(:card, holder: supporter) } let(:card_for_other_supporter) { force_create(:card, holder: other_nonprofit_supporter) } let(:card_with_valid_stripe_id) { force_create(:card, holder: supporter) } @@ -29,61 +29,60 @@ let(:other_event_discount) { force_create(:event_discount, event: other_event) } let(:profile) { force_create(:profile) } let(:user) { force_create(:user) } - let(:ticket_level) { force_create(:ticket_level, event: event, amount: 400, name: '1') } - let(:ticket_level2) { force_create(:ticket_level, event: event, amount: 500, name: '2') } - let(:free_ticket_level) { force_create(:ticket_level, event: event, amount: 0, name: 'free ticket level') } - let(:other_ticket_level) { force_create(:ticket_level, event: other_event, name: '3') } + let(:ticket_level) { force_create(:ticket_level, event: event, amount: 400, name: "1") } + let(:ticket_level2) { force_create(:ticket_level, event: event, amount: 500, name: "2") } + let(:free_ticket_level) { force_create(:ticket_level, event: event, amount: 0, name: "free ticket level") } + let(:other_ticket_level) { force_create(:ticket_level, event: other_event, name: "3") } let(:donation_for_rd) { force_create(:donation, recurring: true, nonprofit: nonprofit, supporter: supporter, card: card_with_valid_stripe_id, amount: 500) } - let(:recurring_donation) { force_create(:recurring_donation, donation: donation_for_rd, nonprofit: nonprofit, supporter: supporter, start_date: Time.now, interval: 1, time_unit: 'month') } - let(:recurrence) { force_create(:recurrence, recurring_donation: recurring_donation, supporter: supporter, amount: 500, start_date: Time.now)} + let(:recurring_donation) { force_create(:recurring_donation, donation: donation_for_rd, nonprofit: nonprofit, supporter: supporter, start_date: Time.now, interval: 1, time_unit: "month") } + let(:recurrence) { force_create(:recurrence, recurring_donation: recurring_donation, supporter: supporter, amount: 500, start_date: Time.now) } let(:stripe_helper) { StripeMockHelper.default_helper } - let(:supporter_name) {'Fake Supporter Name'} + let(:supporter_name) { "Fake Supporter Name" } - let(:nonprofit_to_builder_base) do - { - 'id' => nonprofit.id, - 'name' => nonprofit.name, - 'object' => 'nonprofit' - } + let(:nonprofit_to_builder_base) do + { + "id" => nonprofit.id, + "name" => nonprofit.name, + "object" => "nonprofit" + } end - let(:supporter_to_builder_base) do - { - 'anonymous' => false, - 'deleted' => false, - 'name' => supporter_name, - 'organization' => nil, - 'phone' => nil, - 'supporter_addresses' => [kind_of(Numeric)], - 'id'=> kind_of(Numeric), - 'merged_into' => nil, - 'nonprofit'=> nonprofit.id, - 'object' => 'supporter' - } - end + { + "anonymous" => false, + "deleted" => false, + "name" => supporter_name, + "organization" => nil, + "phone" => nil, + "supporter_addresses" => [kind_of(Numeric)], + "id" => kind_of(Numeric), + "merged_into" => nil, + "nonprofit" => nonprofit.id, + "object" => "supporter" + } + end - let(:supporter_address_to_builder_base) do - { - 'id' => kind_of(Numeric), - 'deleted' => false, - 'address' => address, - 'city' => nil, - 'state_code' => nil, - 'zip_code' => nil, - 'country' => 'United States', - 'object' => 'supporter_address', - 'supporter' => kind_of(Numeric), - 'nonprofit'=> nonprofit.id - } - end + let(:supporter_address_to_builder_base) do + { + "id" => kind_of(Numeric), + "deleted" => false, + "address" => address, + "city" => nil, + "state_code" => nil, + "zip_code" => nil, + "country" => "United States", + "object" => "supporter_address", + "supporter" => kind_of(Numeric), + "nonprofit" => nonprofit.id + } + end - around(:each) do |example| + around do |example| Timecop.freeze(2020, 5, 4) do - StripeMockHelper.mock do + StripeMockHelper.mock do example.run end end diff --git a/spec/support/contexts/shared_rd_donation_value_context.rb b/spec/support/contexts/shared_rd_donation_value_context.rb index 7339784d6f..435222c752 100644 --- a/spec/support/contexts/shared_rd_donation_value_context.rb +++ b/spec/support/contexts/shared_rd_donation_value_context.rb @@ -6,9 +6,9 @@ RSpec.shared_context :shared_rd_donation_value_context do include_context :shared_donation_charge_context - let(:fake_uuid) { '53a6bc06-0789-11e8-bb3f-f34cac607737' } - let(:valid_uuid) { 'fcf61bac-078a-11e8-aa53-cba5bdb8dcdd' } - let(:other_uuid) { 'a713018c-078f-11e8-ae3b-bf5007844fea' } + let(:fake_uuid) { "53a6bc06-0789-11e8-bb3f-f34cac607737" } + let(:valid_uuid) { "fcf61bac-078a-11e8-aa53-cba5bdb8dcdd" } + let(:other_uuid) { "a713018c-078f-11e8-ae3b-bf5007844fea" } let(:source_token) { force_create(:source_token, tokenizable: card, expiration: Time.now + 1.day, max_uses: 1, token: valid_uuid) } let(:source_tokens) do (0..10).map do |_i| @@ -20,15 +20,15 @@ let(:charge_amount) { 100 } - let(:default_edit_token) { '7903e34c-10fe-11e8-9ead-d302c690bee4' } - before(:each) do + let(:default_edit_token) { "7903e34c-10fe-11e8-9ead-d302c690bee4" } + before do end def generate_expected(donation_id, payment_id, charge_id, card, supporter, nonprofit, stripe_charge_id, data = {}) payment_stuff = {} payment_stuff[:card_id] = card.id if card.is_a? Card payment_stuff[:direct_debit_detail_id] = card.id if card.is_a? DirectDebitDetail - payment_stuff[:provider] = card.is_a?(Card) ? 'credit_card' : 'sepa' + payment_stuff[:provider] = card.is_a?(Card) ? "credit_card" : "sepa" payment_stuff[:fee] = card.is_a?(Card) ? 33 : 0 result = { @@ -47,8 +47,8 @@ def generate_expected(donation_id, payment_id, charge_id, card, supporter, nonpr anonymous: nil, amount: charge_amount, comment: nil, - dedication: {'type' => 'honor', 'name' => 'a name'}, - designation: 'designation', + dedication: {"type" => "honor", "name" => "a name"}, + designation: "designation", imported_at: nil, manual: nil, offsite: nil, @@ -75,12 +75,12 @@ def generate_expected(donation_id, payment_id, charge_id, card, supporter, nonpr fee_total: -payment_stuff[:fee], gross_amount: 100, id: payment_id || 55_555, - kind: data[:recurring_donation] ? 'RecurringDonation' : 'Donation', + kind: data[:recurring_donation] ? "RecurringDonation" : "Donation", net_amount: 100 - payment_stuff[:fee], nonprofit_id: nonprofit.id, refund_total: 0, supporter_id: supporter.id, - towards: 'designation', + towards: "designation", created_at: Time.now, updated_at: Time.now, search_vectors: nil @@ -99,7 +99,7 @@ def generate_expected(donation_id, payment_id, charge_id, card, supporter, nonpr failure_message: nil, payment_id: payment_id || 55_555, nonprofit_id: nonprofit.id, - status: 'pending', + status: "pending", profile_id: nil, supporter_id: supporter.id, ticket_id: nil, @@ -147,8 +147,7 @@ def generate_expected(donation_id, payment_id, charge_id, card, supporter, nonpr end def generate_expected_refund(_data = {}) - result = {}.with_indifferent_access - result + {}.with_indifferent_access end def validation_unauthorized @@ -168,21 +167,21 @@ def validation_expired def validation_basic_validation expect { yield() }.to raise_error { |e| expect(e).to be_a(ParamValidation::ValidationError) - expect(e.message).to start_with 'amount' + expect(e.message).to start_with "amount" expect_validation_errors(e.data, [ - { key: :amount, name: :required }, - { key: :amount, name: :is_integer }, - { key: :nonprofit_id, name: :required }, - { key: :nonprofit_id, name: :is_reference }, - { key: :supporter_id, name: :required }, - { key: :supporter_id, name: :is_reference }, - { key: :designation, name: :is_a }, - { key: :dedication, name: :is_a }, - { key: :campaign_id, name: :is_reference }, - { key: :event_id, name: :is_reference }, - { key: :token, name: :required }, - { key: :token, name: :format } - ]) + {key: :amount, name: :required}, + {key: :amount, name: :is_integer}, + {key: :nonprofit_id, name: :required}, + {key: :nonprofit_id, name: :is_reference}, + {key: :supporter_id, name: :required}, + {key: :supporter_id, name: :is_reference}, + {key: :designation, name: :is_a}, + {key: :dedication, name: :is_a}, + {key: :campaign_id, name: :is_reference}, + {key: :event_id, name: :is_reference}, + {key: :token, name: :required}, + {key: :token, name: :format} + ]) } end @@ -197,14 +196,14 @@ def find_error_supporter expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :supporter_id }]) + expect_validation_errors(e.data, [{key: :supporter_id}]) } end def find_error_nonprofit expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :nonprofit_id }]) + expect_validation_errors(e.data, [{key: :nonprofit_id}]) } end @@ -212,28 +211,28 @@ def find_error_campaign expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :campaign_id }]) + expect_validation_errors(e.data, [{key: :campaign_id}]) } end def find_error_event expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :event_id }]) + expect_validation_errors(e.data, [{key: :event_id}]) } end def find_error_ticket expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :ticket_id }]) + expect_validation_errors(e.data, [{key: :ticket_id}]) } end def find_error_profile expect { yield() }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect_validation_errors(e.data, [{ key: :profile_id }]) + expect_validation_errors(e.data, [{key: :profile_id}]) } end @@ -243,8 +242,8 @@ def validation_supporter_deleted supporter.save! expect { yield }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect(e.message).to include 'deleted' - expect_validation_errors(e.data, [{ key: :supporter_id }]) + expect(e.message).to include "deleted" + expect_validation_errors(e.data, [{key: :supporter_id}]) } end @@ -254,8 +253,8 @@ def validation_event_deleted expect { yield }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :event_id }]) - expect(error.message).to include 'deleted' + expect_validation_errors(error.data, [{key: :event_id}]) + expect(error.message).to include "deleted" expect(error.message).to include "Event #{event.id}" } end @@ -266,8 +265,8 @@ def validation_campaign_deleted expect { yield }.to raise_error { |error| expect(error).to be_a ParamValidation::ValidationError - expect_validation_errors(error.data, [{ key: :campaign_id }]) - expect(error.message).to include 'deleted' + expect_validation_errors(error.data, [{key: :campaign_id}]) + expect(error.message).to include "deleted" expect(error.message).to include "Campaign #{campaign.id}" } end @@ -275,43 +274,43 @@ def validation_campaign_deleted def validation_supporter_not_with_nonprofit expect { yield }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect(e.message).to include 'Supporter' - expect(e.message).to include 'does not belong to nonprofit' - expect_validation_errors(e.data, [{ key: :supporter_id }]) + expect(e.message).to include "Supporter" + expect(e.message).to include "does not belong to nonprofit" + expect_validation_errors(e.data, [{key: :supporter_id}]) } end def validation_campaign_not_with_nonprofit expect { yield }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect(e.message).to include 'Campaign' - expect(e.message).to include 'does not belong to nonprofit' - expect_validation_errors(e.data, [{ key: :campaign_id }]) + expect(e.message).to include "Campaign" + expect(e.message).to include "does not belong to nonprofit" + expect_validation_errors(e.data, [{key: :campaign_id}]) } end def validation_event_not_with_nonprofit expect { yield }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect(e.message).to include 'Event' - expect(e.message).to include 'does not belong to nonprofit' - expect_validation_errors(e.data, [{ key: :event_id }]) + expect(e.message).to include "Event" + expect(e.message).to include "does not belong to nonprofit" + expect_validation_errors(e.data, [{key: :event_id}]) } end def validation_card_not_with_supporter expect { yield }.to raise_error { |e| expect(e).to be_a ParamValidation::ValidationError - expect(e.message).to include 'Supporter' - expect(e.message).to include 'does not own card' - expect_validation_errors(e.data, [{ key: :token }]) + expect(e.message).to include "Supporter" + expect(e.message).to include "does not own card" + expect_validation_errors(e.data, [{key: :token}]) } end def handle_charge_failed - failure_message = 'failure message' + failure_message = "failure message" - expect(InsertCharge).to receive(:with_stripe).and_return('charge' => { 'status' => 'failed', 'failure_message' => failure_message }) + expect(InsertCharge).to receive(:with_stripe).and_return("charge" => {"status" => "failed", "failure_message" => failure_message}) expect { yield }.to raise_error { |e| expect(e).to be_a ChargeError @@ -332,16 +331,16 @@ def before_each_success(expect_charge = true) end if expect_charge - nonprofit.stripe_account_id = Stripe::Account.create['id'] + nonprofit.stripe_account_id = Stripe::Account.create["id"] nonprofit.save! - card.stripe_customer_id = 'some other id' + card.stripe_customer_id = "some other id" cust = Stripe::Customer.create - card.stripe_customer_id = cust['id'] + card.stripe_customer_id = cust["id"] card.save! expect(Stripe::Charge).to receive(:create).and_wrap_original { |m, *args| a = m.call(*args) - @stripe_charge_id = a['id'] + @stripe_charge_id = a["id"] a } end @@ -358,13 +357,13 @@ def before_each_successful_refund expect(Stripe::Refund).to receive(:create).and_wrap_original do |m, *args| a = m.call(*args) - @stripe_refund_ids&.unshift(a['id']) || @stripe_refund_ids = [a['id']] + @stripe_refund_ids&.unshift(a["id"]) || @stripe_refund_ids = [a["id"]] a end end def before_each_sepa_success - expect(InsertDonation).to receive(:insert_donation).and_wrap_original do |m, *args| + expect(InsertDonation).to receive(:insert_donation).and_wrap_original do |m, *args| result = m.call(*args) @donation_id = result.id result @@ -373,22 +372,22 @@ def before_each_sepa_success def process_event_donation(data = {}) pay_method = data[:sepa] ? direct_debit_detail : card - - unless (data[:recurring_donation]) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale ) + + if data[:recurring_donation] + expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create, instance_of(Donation), supporter.locale) else - expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale ) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_create, instance_of(Donation), supporter.locale) end result = yield - expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, event: event, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation']) + expected = generate_expected(@donation_id, result["payment"].id, result["charge"].id, pay_method, supporter, nonprofit, @stripe_charge_id, event: event, recurring_donation_expected: data[:recurring_donation], recurring_donation: result["recurring_donation"]) expect(result.count).to eq expected.count - expect(result['donation'].attributes).to eq expected[:donation] - expect(result['charge'].attributes).to eq expected[:charge] + expect(result["donation"].attributes).to eq expected[:donation] + expect(result["charge"].attributes).to eq expected[:charge] # expect(result[:json]['activity']).to eq expected[:activity] - expect(result['payment'].attributes).to eq expected[:payment] + expect(result["payment"].attributes).to eq expected[:payment] if data[:recurring_donation] - expect(result['recurring_donation'].attributes).to eq expected[:recurring_donation] + expect(result["recurring_donation"].attributes).to eq expected[:recurring_donation] end result @@ -397,49 +396,49 @@ def process_event_donation(data = {}) def process_campaign_donation(data = {}) pay_method = data[:sepa] ? direct_debit_detail : card - unless (data[:recurring_donation]) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale ) + if data[:recurring_donation] + expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create, instance_of(Donation), supporter.locale) else - expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale ) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_create, instance_of(Donation), supporter.locale) end result = yield - expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, campaign: campaign, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation']) + expected = generate_expected(@donation_id, result["payment"].id, result["charge"].id, pay_method, supporter, nonprofit, @stripe_charge_id, campaign: campaign, recurring_donation_expected: data[:recurring_donation], recurring_donation: result["recurring_donation"]) expect(result.count).to eq expected.count - expect(result['donation'].attributes).to eq expected[:donation] - expect(result['charge'].attributes).to eq expected[:charge] - expect(result['payment'].attributes).to eq expected[:payment] + expect(result["donation"].attributes).to eq expected[:donation] + expect(result["charge"].attributes).to eq expected[:charge] + expect(result["payment"].attributes).to eq expected[:payment] if data[:recurring_donation] - expect(result['recurring_donation'].attributes).to eq expected[:recurring_donation] + expect(result["recurring_donation"].attributes).to eq expected[:recurring_donation] end result end def process_general_donation(data = {}) pay_method = data[:sepa] ? direct_debit_detail : card - unless (data[:recurring_donation]) - expect(Houdini.event_publisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale ) + if data[:recurring_donation] + expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create, instance_of(Donation), supporter.locale) else - expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale ) + expect(Houdini.event_publisher).to receive(:announce).with(:donation_create, instance_of(Donation), supporter.locale) end result = yield expect_payment = nil_or_true(data[:expect_payment]) expect_charge = nil_or_true(data[:expect_charge]) - expected = generate_expected(@donation_id, nil_or_true(data[:expect_payment]) ? result['payment'].id : nil, nil_or_true(data[:expect_payment]) ? result['charge'].id : nil, pay_method, supporter, nonprofit, @stripe_charge_id, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation']) + expected = generate_expected(@donation_id, nil_or_true(data[:expect_payment]) ? result["payment"].id : nil, nil_or_true(data[:expect_payment]) ? result["charge"].id : nil, pay_method, supporter, nonprofit, @stripe_charge_id, recurring_donation_expected: data[:recurring_donation], recurring_donation: result["recurring_donation"]) - expected['donation'][:profile_id] = profile.id + expected["donation"][:profile_id] = profile.id expect(result.count).to eq expected.count - expect(result['donation'].attributes).to eq expected[:donation] - expect(result['charge'].attributes).to eq expected[:charge] if expect_charge + expect(result["donation"].attributes).to eq expected[:donation] + expect(result["charge"].attributes).to eq expected[:charge] if expect_charge # expect(result[:json]['activity']).to eq expected[:activity] if expect_payment - expect(result['payment'].attributes).to eq expected[:payment] + expect(result["payment"].attributes).to eq expected[:payment] end if data[:recurring_donation] - expect(result['recurring_donation'].attributes).to eq expected[:recurring_donation] + expect(result["recurring_donation"].attributes).to eq expected[:recurring_donation] end result @@ -450,8 +449,8 @@ def process_general_refund(_data = {}) expected = generate_expected_refund - expect(result['payment']).to eq expected[:payment] - expect(result['refund']).to eq expected[:refund] + expect(result["payment"]).to eq expected[:payment] + expect(result["refund"]).to eq expected[:refund] result end diff --git a/spec/support/contexts/subtransaction_context.rb b/spec/support/contexts/subtransaction_context.rb index 5c68acee9a..a93620c35b 100644 --- a/spec/support/contexts/subtransaction_context.rb +++ b/spec/support/contexts/subtransaction_context.rb @@ -3,147 +3,147 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -shared_context 'with json results for subtransaction on transaction_for_donation' do - around do |ex| - Timecop.freeze(2020, 5, 4) do - ex.run - end - end - - it { - is_expected.to include('object' => 'offline_transaction') - } - - it { - is_expected.to include('id' => match_houid('offlinetrx')) - } - - it { - is_expected.to include('created' => Time.current.to_i) - } - - it { - is_expected.to include('type' => 'subtransaction') - } - - it { - is_expected.to include('object' => 'offline_transaction') - } - - it { - is_expected.to include( - 'amount' => { - 'cents' => 4000, - 'currency' => 'usd' - } - ) - } - - it { - is_expected.to include( - 'net_amount' => { - 'cents' => 3700, - 'currency' => 'usd' - } - ) - } - - it { - is_expected.to include( - 'transaction' => match_houid('trx') - ) - } - - describe('validate payments') do - subject(:payments_json) do - json['payments'] - end - - it { - expect(payments_json.count).to eq 1 - } - - describe('and the first charge') do - subject(:payment0) do - payments_json[0] - end - - it { - is_expected.to include('id' => match_houid('offtrxchrg')) - } - - it { - is_expected.to include('type' => 'payment') - } - - it { - is_expected.to include('object' => 'offline_transaction_charge') - } - - it { - is_expected.to include('created' => Time.current.to_i) - } - - it { - is_expected.to include('gross_amount' => { - 'cents' => 4000, - 'currency' => 'usd' - }) - } - - it { - is_expected.to include('fee_total' => { - 'cents' => 300, - 'currency' => 'usd' - }) - } - - it { - is_expected.to include('net_amount' => { - 'cents' => 3700, - 'currency' => 'usd' - }) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('subtransaction' => { - 'id' => match_houid('offlinetrx'), - 'object' => 'offline_transaction', - 'type' => 'subtransaction' - }) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include( - 'url' => - payment_url( - nonprofit.id, - transaction.id, - transaction.subtransaction.payments.first.paymentable.id - ) - ) - } - end - end - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('url' => - subtransaction_url(nonprofit.id, transaction.id)) - } +shared_context "with json results for subtransaction on transaction_for_donation" do + around do |ex| + Timecop.freeze(2020, 5, 4) do + ex.run + end + end + + it { + is_expected.to include("object" => "offline_transaction") + } + + it { + is_expected.to include("id" => match_houid("offlinetrx")) + } + + it { + is_expected.to include("created" => Time.current.to_i) + } + + it { + is_expected.to include("type" => "subtransaction") + } + + it { + is_expected.to include("object" => "offline_transaction") + } + + it { + is_expected.to include( + "amount" => { + "cents" => 4000, + "currency" => "usd" + } + ) + } + + it { + is_expected.to include( + "net_amount" => { + "cents" => 3700, + "currency" => "usd" + } + ) + } + + it { + is_expected.to include( + "transaction" => match_houid("trx") + ) + } + + describe("validate payments") do + subject(:payments_json) do + json["payments"] + end + + it { + expect(payments_json.count).to eq 1 + } + + describe("and the first charge") do + subject(:payment0) do + payments_json[0] + end + + it { + is_expected.to include("id" => match_houid("offtrxchrg")) + } + + it { + is_expected.to include("type" => "payment") + } + + it { + is_expected.to include("object" => "offline_transaction_charge") + } + + it { + is_expected.to include("created" => Time.current.to_i) + } + + it { + is_expected.to include("gross_amount" => { + "cents" => 4000, + "currency" => "usd" + }) + } + + it { + is_expected.to include("fee_total" => { + "cents" => 300, + "currency" => "usd" + }) + } + + it { + is_expected.to include("net_amount" => { + "cents" => 3700, + "currency" => "usd" + }) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("subtransaction" => { + "id" => match_houid("offlinetrx"), + "object" => "offline_transaction", + "type" => "subtransaction" + }) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include( + "url" => + payment_url( + nonprofit.id, + transaction.id, + transaction.subtransaction.payments.first.paymentable.id + ) + ) + } + end + end + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("url" => + subtransaction_url(nonprofit.id, transaction.id)) + } end diff --git a/spec/support/contexts/ticket_levels_context.rb b/spec/support/contexts/ticket_levels_context.rb index 416566b5aa..ca5d75a087 100644 --- a/spec/support/contexts/ticket_levels_context.rb +++ b/spec/support/contexts/ticket_levels_context.rb @@ -3,53 +3,53 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -shared_examples 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' do - it { - is_expected.to include('object' => 'ticket_level') - } - - it { - is_expected.to include('id' => ticket_level.id) - } - - it { - is_expected.to include('name' => 'ticket level name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('event' => event.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('description' => 'desc ticket') - } - - it { - is_expected.to include('available_to' => 'everyone') - } - - it { - is_expected.to include('order' => 3) - } - - it { - is_expected.to include('limit' => 2) - } - - it { - is_expected.to include('amount' => { 'cents' => 200, 'currency' => nonprofit.currency }) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, event.id, ticket_level.id)) - } +shared_examples "json results for ticket_level_with_event_non_admin__order_3__not_deleted" do + it { + is_expected.to include("object" => "ticket_level") + } + + it { + is_expected.to include("id" => ticket_level.id) + } + + it { + is_expected.to include("name" => "ticket level name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("event" => event.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("description" => "desc ticket") + } + + it { + is_expected.to include("available_to" => "everyone") + } + + it { + is_expected.to include("order" => 3) + } + + it { + is_expected.to include("limit" => 2) + } + + it { + is_expected.to include("amount" => {"cents" => 200, "currency" => nonprofit.currency}) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, event.id, ticket_level.id)) + } end diff --git a/spec/support/contexts/transaction_context.rb b/spec/support/contexts/transaction_context.rb index 1496cab538..02621a615a 100644 --- a/spec/support/contexts/transaction_context.rb +++ b/spec/support/contexts/transaction_context.rb @@ -3,74 +3,74 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -shared_context 'with json results for transaction_for_donation' do - around do |ex| - Timecop.freeze(2020, 5, 4) do - ex.run - end - end +shared_context "with json results for transaction_for_donation" do + around do |ex| + Timecop.freeze(2020, 5, 4) do + ex.run + end + end - it { - is_expected.to include('object' => 'transaction') - } + it { + is_expected.to include("object" => "transaction") + } - it { - is_expected.to include('id' => transaction.id) - } + it { + is_expected.to include("id" => transaction.id) + } - it { - is_expected.to include('created' => Time.current.to_i) - } + it { + is_expected.to include("created" => Time.current.to_i) + } - it { - is_expected.to include( - 'amount' => { - 'cents' => 4000, - 'currency' => 'usd' - } - ) - } + it { + is_expected.to include( + "amount" => { + "cents" => 4000, + "currency" => "usd" + } + ) + } - it { - is_expected.to include( - 'subtransaction' => { - 'id' => match_houid('offlinetrx'), - 'type' => 'subtransaction', - 'object' => 'offline_transaction' - } - ) - } + it { + is_expected.to include( + "subtransaction" => { + "id" => match_houid("offlinetrx"), + "type" => "subtransaction", + "object" => "offline_transaction" + } + ) + } - it { - is_expected.to include( - 'payments' => [{ - 'id' => match_houid('offtrxchrg'), - 'type' => 'payment', - 'object' => 'offline_transaction_charge' - }] - ) - } + it { + is_expected.to include( + "payments" => [{ + "id" => match_houid("offtrxchrg"), + "type" => "payment", + "object" => "offline_transaction_charge" + }] + ) + } - it { - is_expected.to include( - 'transaction_assignments' => [{ - 'id' => match_houid('don'), - 'type' => 'trx_assignment', - 'object' => 'donation' - }] - ) - } + it { + is_expected.to include( + "transaction_assignments" => [{ + "id" => match_houid("don"), + "type" => "trx_assignment", + "object" => "donation" + }] + ) + } - it { - is_expected.to include('nonprofit' => nonprofit.id) - } + it { + is_expected.to include("nonprofit" => nonprofit.id) + } - it { - is_expected.to include('supporter' => supporter.id) - } + it { + is_expected.to include("supporter" => supporter.id) + } - it { - is_expected.to include('url' => - base_url(nonprofit.id, transaction.id)) - } + it { + is_expected.to include("url" => + base_url(nonprofit.id, transaction.id)) + } end diff --git a/spec/support/expect.rb b/spec/support/expect.rb index 11615a73a8..a8126edc5d 100644 --- a/spec/support/expect.rb +++ b/spec/support/expect.rb @@ -19,11 +19,11 @@ def expect_validation_errors(list_of_errors, validators, error_validator_length_ end end - def match_houid(prefix) + def match_houid(prefix) match(/#{prefix}_[a-zA-Z0-9]{22}/) end - def match_json(args={}) + def match_json(args = {}) match(args.deep_stringify_keys) end end diff --git a/spec/support/init_dotenv.rb b/spec/support/init_dotenv.rb index 5728f62a14..588a5690c0 100644 --- a/spec/support/init_dotenv.rb +++ b/spec/support/init_dotenv.rb @@ -2,5 +2,5 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'dotenv' +require "dotenv" Dotenv.load diff --git a/spec/support/mock_helpers.rb b/spec/support/mock_helpers.rb index e28812db4c..cce735cabb 100644 --- a/spec/support/mock_helpers.rb +++ b/spec/support/mock_helpers.rb @@ -4,17 +4,17 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE module MockHelpers def self.payment_export_headers - ['Date', 'Gross Amount', 'Fee Total', 'Net Amount', 'Type', 'Last Name', 'First Name', 'Full Name', 'Organization', 'Email', 'Phone', 'Address', 'City', 'State', 'Postal Code', 'Country', 'Anonymous?', 'Supporter Id', 'Designation', 'Dedication Type', - 'Dedicated To: Name', - 'Dedicated To: Supporter Id', - 'Dedicated To: Email', - 'Dedicated To: Phone', - 'Dedicated To: Address', - 'Dedicated To: Note', 'Anonymous', 'Comment', 'Campaign', 'Campaign Id', 'Campaign Creator Email', 'Campaign Gift Level', 'Event Name', 'Payment', 'Check Number', 'Donation Note'] + ["Date", "Gross Amount", "Fee Total", "Net Amount", "Type", "Last Name", "First Name", "Full Name", "Organization", "Email", "Phone", "Address", "City", "State", "Postal Code", "Country", "Anonymous?", "Supporter Id", "Designation", "Dedication Type", + "Dedicated To: Name", + "Dedicated To: Supporter Id", + "Dedicated To: Email", + "Dedicated To: Phone", + "Dedicated To: Address", + "Dedicated To: Note", "Anonymous", "Comment", "Campaign", "Campaign Id", "Campaign Creator Email", "Campaign Gift Level", "Event Name", "Payment", "Check Number", "Donation Note"] end def self.recurring_donation_export_headers - ['Created At', 'Amount', 'Interval', 'Total Contributed', 'Campaign Name', 'Supporter Name', 'Supporter Email', 'Phone', 'Address', 'City', 'State', 'Zip Code', 'Card Name', 'Recurring Donation Id', 'Donation Id', 'Cancelled', 'Failed', 'Cancelled At', 'Donation Management Url'] + ["Created At", "Amount", "Interval", "Total Contributed", "Campaign Name", "Supporter Name", "Supporter Email", "Phone", "Address", "City", "State", "Zip Code", "Card Name", "Recurring Donation Id", "Donation Id", "Cancelled", "Failed", "Cancelled At", "Donation Management Url"] end def self.generate_expected_rd_management_url(root_url, rd) diff --git a/spec/support/payments_for_a_payout.rb b/spec/support/payments_for_a_payout.rb index e15e7ceae0..9ad5e28efa 100644 --- a/spec/support/payments_for_a_payout.rb +++ b/spec/support/payments_for_a_payout.rb @@ -2,8 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -shared_context 'payments for a payout' do - before(:each) { @expect_marked = { charges: [], disputes: [], refunds: [], payouts_records: [] } } +shared_context "payments for a payout" do + before { @expect_marked = {charges: [], disputes: [], refunds: [], payouts_records: []} } + let(:all_payments) do payment_with_charge_to_output partial_refunded_payment @@ -19,14 +20,14 @@ # net amount: 1600 let(:payment_with_charge_to_output) do p = create_marked_payment - create_marked_charge(payment: p, amount: 2000, fee: -400, status: 'available') + create_marked_charge(payment: p, amount: 2000, fee: -400, status: "available") return p end # net amount: 1100 let(:partial_refunded_payment) do p = create_marked_payment - c = create_marked_charge(payment: p, amount: 2000, fee: -400, status: 'available') + c = create_marked_charge(payment: p, amount: 2000, fee: -400, status: "available") refund_payment = create_marked_payment(gross_amount: -500, fee_total: 0, net_amount: -500) create_marked_refund(charge: c, payment: refund_payment, amount: 500) @@ -36,7 +37,7 @@ # net amount: 0 let(:refunded_payment) do p = create_marked_payment - c = create_marked_charge(payment: p, amount: 2000, status: 'available') + c = create_marked_charge(payment: p, amount: 2000, status: "available") refund_payment = create_marked_payment(gross_amount: -2000, fee_total: 400, net_amount: -1600) create_marked_refund(charge: c, payment: refund_payment, amount: 2000, disbursed: false) return p @@ -45,10 +46,10 @@ # net amount: 0 let(:disputed_payment) do p = create_marked_payment - c = create_marked_charge(payment: p, amount: 2000, status: 'available') + c = create_marked_charge(payment: p, amount: 2000, status: "available") p2 = create_marked_payment(gross_amount: -2000, fee_total: 400, net_amount: -1600) - create_marked_dispute(charge: c, payment: p2, gross_amount: 2000, status: 'lost') + create_marked_dispute(charge: c, payment: p2, gross_amount: 2000, status: "lost") return p end @@ -56,7 +57,7 @@ let(:late_payment) do is_this_marked = Time.now.beginning_of_day <= date_for_marking.beginning_of_day p = create_payment(date: Time.now, marked: is_this_marked) - c = create_charge(payment: p, amount: 2000, status: 'available', marked: is_this_marked) + create_charge(payment: p, amount: 2000, status: "available", marked: is_this_marked) return p end @@ -64,31 +65,31 @@ # net amount: 0 let(:paid_out_payment) do p = create_payment - c = create_charge(payment: p, amount: 2000, status: 'disbursed') + create_charge(payment: p, amount: 2000, status: "disbursed") return p end # net amount: 0 let(:paid_out_refund) do p = create_payment - c = create_charge(payment: p, amount: 2000, status: 'disbursed') + create_charge(payment: p, amount: 2000, status: "disbursed") refunded_payment = create_payment(gross_amount: -2000, fee_total: 400, net_amount: -1600) - refund = create_refund(payment: refunded_payment, disbursed: true) + create_refund(payment: refunded_payment, disbursed: true) return p end # net amount: 0 let(:paid_out_dispute) do p = create_payment - c = create_charge(payment: p, amount: 2000, status: 'disbursed') + c = create_charge(payment: p, amount: 2000, status: "disbursed") dispute_payment = create_payment(gross_amount: -2000, fee_total: 400, net_amount: -1600) - dispute = create_dispute(charge: c, payment: dispute_payment, gross_amount: 2000, status: 'lost_and_paid') + create_dispute(charge: c, payment: dispute_payment, gross_amount: 2000, status: "lost_and_paid") return p end let(:other_np_payment) do p = create_payment(nonprofit: force_create(:fv_poverty)) - create_charge(payment: p, amount: 2000, fee: -400, status: 'available') + create_charge(payment: p, amount: 2000, fee: -400, status: "available") return p end @@ -98,7 +99,7 @@ def create_marked_payment(args = {}) def create_payment(args = {}) expect_payment = args[:marked] - p = force_create(:payment, { nonprofit: np, date: Time.now - 1.day, gross_amount: 2000, fee_total: -400, net_amount: 1600 }.merge(args.except(:marked))) + p = force_create(:payment, {nonprofit: np, date: Time.now - 1.day, gross_amount: 2000, fee_total: -400, net_amount: 1600}.merge(args.except(:marked))) @expect_marked[:payouts_records].push(p) if expect_payment p end diff --git a/spec/support/stripe_mock_helper.rb b/spec/support/stripe_mock_helper.rb index 65934d739d..9ff11daedc 100644 --- a/spec/support/stripe_mock_helper.rb +++ b/spec/support/stripe_mock_helper.rb @@ -7,49 +7,49 @@ # to get the StripeTestHelper for the session. # @see StripeMock StripeMockHelper = Class.new do - delegate_missing_to :StripeMock + delegate_missing_to :StripeMock - # Most StripeMock sessions only need a single test helper so you can get it here - # @return a Stripe test helper or nil if none is set - def default_helper - @default_helper if defined? @default_helper - end + # Most StripeMock sessions only need a single test helper so you can get it here + # @return a Stripe test helper or nil if none is set + def default_helper + @default_helper if defined? @default_helper + end - alias_method :stripe_helper, :default_helper + alias_method :stripe_helper, :default_helper - # sets up a StripeMock session and sets up StripeMock::default_helper - # note: Rspec is set up to autostop a StripeMock session when an example finishes - def start - return if default_helper + # sets up a StripeMock session and sets up StripeMock::default_helper + # note: Rspec is set up to autostop a StripeMock session when an example finishes + def start + return if default_helper - StripeMock.start - create_default_helper - end + StripeMock.start + create_default_helper + end - # stops a StripeMock session and clears StripeMock::default_helper - def stop - clear_default_helper - StripeMock.stop - end + # stops a StripeMock session and clears StripeMock::default_helper + def stop + clear_default_helper + StripeMock.stop + end - # wraps a block in a StripeMock session and sets up StripeMock::default_helper - def mock(&block) - start + # wraps a block in a StripeMock session and sets up StripeMock::default_helper + def mock(&block) + start - block.call + block.call - stop - end + stop + end - private + private - # Clears the default test helper for the current StripeMock session - def clear_default_helper - remove_instance_variable :@default_helper if defined? @default_helper - end + # Clears the default test helper for the current StripeMock session + def clear_default_helper + remove_instance_variable :@default_helper if defined? @default_helper + end - # Creates a default test helper for the current StripeMock session - def create_default_helper - @default_helper ||= StripeMock.create_test_helper # rubocop:disable Naming/MemoizedInstanceVariableName - end + # Creates a default test helper for the current StripeMock session + def create_default_helper + @default_helper ||= StripeMock.create_test_helper # rubocop:disable Naming/MemoizedInstanceVariableName + end end.new diff --git a/spec/support/test/stripe_mock_helper_spec.rb b/spec/support/test/stripe_mock_helper_spec.rb index 8e193cd492..2372fe047e 100644 --- a/spec/support/test/stripe_mock_helper_spec.rb +++ b/spec/support/test/stripe_mock_helper_spec.rb @@ -4,34 +4,34 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE describe StripeMockHelper do - describe '#stripe_helper' do - it 'starts unset' do - expect(described_class.stripe_helper).to be_falsy - end + describe "#stripe_helper" do + it "starts unset" do + expect(described_class.stripe_helper).to be_falsy + end - it 'is set on start' do - described_class.mock do - expect(described_class.stripe_helper).to be_truthy - end - end + it "is set on start" do + described_class.mock do + expect(described_class.stripe_helper).to be_truthy + end + end - it 'clears stripe_helper when finished' do - described_class.mock do # rubocop:disable Lint/EmptyBlock - end - expect(described_class.stripe_helper).to be_falsy - end - end + it "clears stripe_helper when finished" do + described_class.mock do # rubocop:disable Lint/EmptyBlock + end + expect(described_class.stripe_helper).to be_falsy + end + end - describe '#start' do - it 'is safely reentrant' do - described_class.mock do - # create a plan - described_class.stripe_helper.create_plan(id: 'test_str_plan', amount: 0, currency: 'usd', interval: 'year', - name: 'test PLan') - described_class.start - expect { Stripe::Plan.retrieve('test_str_plan') }.to_not(raise_error, "If this object is not available, \ + describe "#start" do + it "is safely reentrant" do + described_class.mock do + # create a plan + described_class.stripe_helper.create_plan(id: "test_str_plan", amount: 0, currency: "usd", interval: "year", + name: "test PLan") + described_class.start + expect { Stripe::Plan.retrieve("test_str_plan") }.to_not(raise_error, "If this object is not available, \ then the StripeMockHelper.start is incorrectly creating a new StripeMock session") - end - end - end + end + end + end end diff --git a/spec/support/test_upload_service.rb b/spec/support/test_upload_service.rb index b61f600fc5..96c9d5652c 100755 --- a/spec/support/test_upload_service.rb +++ b/spec/support/test_upload_service.rb @@ -2,9 +2,9 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'stringio' +require "stringio" class TestUploadService < ActiveStorage::Service - TEST_ERROR_MESSAGE = 'test exception thrown' + TEST_ERROR_MESSAGE = "test exception thrown" attr_reader :output, :options def clear @@ -18,7 +18,7 @@ def raise_error @raise_error = true end - def upload(key, io, checksum:nil, **options) + def upload(key, io, checksum: nil, **options) @options = options @output = io.read diff --git a/spec/tasks/i18n_js_spec.rb b/spec/tasks/i18n_js_spec.rb index 0288d1efad..1232058db7 100644 --- a/spec/tasks/i18n_js_spec.rb +++ b/spec/tasks/i18n_js_spec.rb @@ -2,58 +2,58 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" Rails.application.load_tasks -describe 'i18n_js.rake' do # rubocop:disable RSpec/DescribeClass - def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") - end - - let(:locales_dir) { Rails.root.join('app/javascript/i18n/locales') } - - def wrap_task(rake_taskname) - task = Rake::Task[rake_taskname] - Rake.application.tasks.each(&:reenable) - task.invoke - yield - Rake.application.tasks.each(&:reenable) - end - - def verify_cleaned(rake_taskname) - wrap_task(rake_taskname) do - expect(!Dir.exist?(locales_dir) || Dir[locales_dir].none?).to( - be(true), - "#{locales_dir} wasn't cleaned by bin/rails #{rake_taskname}" - ) - end - end - - def verify_task_generate(rake_taskname) - wrap_task(rake_taskname) do - expect(Dir.exist?(locales_dir) && Dir[locales_dir].any?).to( - be(true), - "#{locales_dir} wasn't generated by bin/rails #{rake_taskname}" - ) - end - end - - def verify_generate(command_line) - system!(command_line) - expect(Dir.exist?(locales_dir) && Dir[locales_dir].any?).to( - be(true), - "#{locales_dir} wasn't generated by #{command_line}" - ) - end - - it 'export and clean' do # rubocop:disable RSpec/NoExpectationExample - verify_task_generate('i18n:js:export') - verify_cleaned('webpacker:clean') - verify_task_generate('webpacker:compile') - verify_cleaned('assets:clobber') - verify_task_generate('i18n:js:export') - verify_cleaned('i18n:js:clean') - verify_generate('bin/webpack') - end +describe "i18n_js.rake" do # rubocop:disable RSpec/DescribeClass + def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") + end + + let(:locales_dir) { Rails.root.join("app/javascript/i18n/locales") } + + def wrap_task(rake_taskname) + task = Rake::Task[rake_taskname] + Rake.application.tasks.each(&:reenable) + task.invoke + yield + Rake.application.tasks.each(&:reenable) + end + + def verify_cleaned(rake_taskname) + wrap_task(rake_taskname) do + expect(!Dir.exist?(locales_dir) || Dir[locales_dir].none?).to( + be(true), + "#{locales_dir} wasn't cleaned by bin/rails #{rake_taskname}" + ) + end + end + + def verify_task_generate(rake_taskname) + wrap_task(rake_taskname) do + expect(Dir.exist?(locales_dir) && Dir[locales_dir].any?).to( + be(true), + "#{locales_dir} wasn't generated by bin/rails #{rake_taskname}" + ) + end + end + + def verify_generate(command_line) + system!(command_line) + expect(Dir.exist?(locales_dir) && Dir[locales_dir].any?).to( + be(true), + "#{locales_dir} wasn't generated by #{command_line}" + ) + end + + it "export and clean" do # rubocop:disable RSpec/NoExpectationExample + verify_task_generate("i18n:js:export") + verify_cleaned("webpacker:clean") + verify_task_generate("webpacker:compile") + verify_cleaned("assets:clobber") + verify_task_generate("i18n:js:export") + verify_cleaned("i18n:js:clean") + verify_generate("bin/webpack") + end end diff --git a/spec/tasks/js_spec.rb b/spec/tasks/js_spec.rb index 46f69e1e13..665f5dd4c5 100644 --- a/spec/tasks/js_spec.rb +++ b/spec/tasks/js_spec.rb @@ -2,55 +2,55 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" Rails.application.load_tasks -describe 'js.rake' do # rubocop:disable RSpec/DescribeClass - def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") - end - - let(:js_dir) { Rails.root.join('app/javascript') } - - def wrap_task(rake_taskname) - task = Rake::Task[rake_taskname] - Rake.application.tasks.each(&:reenable) - task.invoke - yield - Rake.application.tasks.each(&:reenable) - end - - def verify_cleaned(rake_taskname) # rubocop:disable Metrics/AbcSize - wrap_task(rake_taskname) do - expect(!File.exist?(js_dir.join('routes.js'))).to( - be(true), - "#{js_dir.join('routes.js')} wasn't cleaned by bin/rails #{rake_taskname}" - ) - - expect(!File.exist?(js_dir.join('routes.d.ts'))).to( - be(true), - "#{js_dir.join('routes.d.ts')} wasn't cleaned by bin/rails #{rake_taskname}" - ) - end - end - - def verify_task_generate(rake_taskname) - wrap_task(rake_taskname) do - expect(File.exist?(js_dir.join('routes.js'))).to( - be(true), - "#{js_dir.join('routes.js')} wasn't generated by bin/rails #{rake_taskname}" - ) - - expect(File.exist?(js_dir.join('routes.d.ts'))).to( - be(true), - "#{js_dir.join('routes.d.ts')} wasn't generated by bin/rails #{rake_taskname}" - ) - end - end - - it 'export and clean' do # rubocop:disable RSpec/NoExpectationExample - verify_task_generate('js:routes:typescript') - verify_cleaned('js:routes:clean') - end +describe "js.rake" do # rubocop:disable RSpec/DescribeClass + def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") + end + + let(:js_dir) { Rails.root.join("app/javascript") } + + def wrap_task(rake_taskname) + task = Rake::Task[rake_taskname] + Rake.application.tasks.each(&:reenable) + task.invoke + yield + Rake.application.tasks.each(&:reenable) + end + + def verify_cleaned(rake_taskname) # rubocop:disable Metrics/AbcSize + wrap_task(rake_taskname) do + expect(!File.exist?(js_dir.join("routes.js"))).to( + be(true), + "#{js_dir.join("routes.js")} wasn't cleaned by bin/rails #{rake_taskname}" + ) + + expect(!File.exist?(js_dir.join("routes.d.ts"))).to( + be(true), + "#{js_dir.join("routes.d.ts")} wasn't cleaned by bin/rails #{rake_taskname}" + ) + end + end + + def verify_task_generate(rake_taskname) + wrap_task(rake_taskname) do + expect(File.exist?(js_dir.join("routes.js"))).to( + be(true), + "#{js_dir.join("routes.js")} wasn't generated by bin/rails #{rake_taskname}" + ) + + expect(File.exist?(js_dir.join("routes.d.ts"))).to( + be(true), + "#{js_dir.join("routes.d.ts")} wasn't generated by bin/rails #{rake_taskname}" + ) + end + end + + it "export and clean" do # rubocop:disable RSpec/NoExpectationExample + verify_task_generate("js:routes:typescript") + verify_cleaned("js:routes:clean") + end end diff --git a/spec/views/api/campaign_gift_options/index.json.jbuilder_spec.rb b/spec/views/api/campaign_gift_options/index.json.jbuilder_spec.rb index 4b5df97550..e16ed643e2 100644 --- a/spec/views/api/campaign_gift_options/index.json.jbuilder_spec.rb +++ b/spec/views/api/campaign_gift_options/index.json.jbuilder_spec.rb @@ -2,276 +2,276 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/campaign_gift_options/index.json.jbuilder' do - subject(:json) do - assign(:campaign_gift_options, - Kaminari.paginate_array( - [ - campaign_gift_option_with_campaign_with_one_time_amount, - campaign_gift_option_with_campaign_with_recurring_amount, - campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount - ] - ).page) - render - JSON.parse(rendered) - end - - let(:campaign_gift_option_with_campaign_with_one_time_amount) do - create(:campaign_gift_option_with_campaign_with_one_time_amount) - end - let(:campaign_gift_option_with_campaign_with_recurring_amount) do - create(:campaign_gift_option_with_campaign_with_recurring_amount, - campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) - end - let(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount) do - create(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount, - campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) - end - - def base_path(nonprofit_id, campaign_id, campaign_gift_option_id) - "/api/nonprofits/#{nonprofit_id}/campaigns/#{campaign_id}/campaign_gift_options/#{campaign_gift_option_id}" - end - - def base_url(nonprofit_id, campaign_id, campaign_gift_option_id) - "http://test.host#{base_path(nonprofit_id, campaign_id, campaign_gift_option_id)}" - end - - it { expect(json['data'].count).to eq 3 } - - describe 'details of the campaign_gift_option_with_campaign_with_one_time_amount' do - subject(:first) do - json['data'][0] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_one_time_amount } - - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has one time amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time description') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => nil) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 200, 'currency' => nonprofit.currency }, - 'recurrence' => nil - }] - )) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) - } - end - - describe 'details of the campaign_gift_option_with_campaign_with_recurring_amount' do - subject(:second) do - json['data'][1] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_recurring_amount } - - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has recurring amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'a recurring description!') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => 4) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly' } - }] - )) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) - } - end - - describe 'details of the campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount' do - subject(:third) do - json['data'][2] - end - - let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount } - - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has both one time and recurring amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time AND recurring') - } - - it { - is_expected.to include('hide_contributions' => true) - } - - it { - is_expected.to include('order' => 5) - } - - it { - is_expected.to include('to_ship' => true) - } - - it { - is_expected.to include('quantity' => 50) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [ - { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly' } - }, - { - 'amount' => { 'cents' => 300, 'currency' => nonprofit.currency }, - 'recurrence' => nil - } - - ] - )) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) - } - end - - describe 'paging' do - subject(:json) do - cgo - 6.times do |i| - create(:campaign_gift_option_with_campaign_with_one_time_amount, campaign: cgo.campaign, name: i) - end - assign(:campaign_gift_options, cgo.campaign.campaign_gift_options.order('id DESC').page.per(5)) - render - JSON.parse(rendered) - end - - let(:cgo) { create(:campaign_gift_option_with_campaign_with_one_time_amount) } - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end +require "rails_helper" + +RSpec.describe "/api/campaign_gift_options/index.json.jbuilder" do + subject(:json) do + assign(:campaign_gift_options, + Kaminari.paginate_array( + [ + campaign_gift_option_with_campaign_with_one_time_amount, + campaign_gift_option_with_campaign_with_recurring_amount, + campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount + ] + ).page) + render + JSON.parse(rendered) + end + + let(:campaign_gift_option_with_campaign_with_one_time_amount) do + create(:campaign_gift_option_with_campaign_with_one_time_amount) + end + let(:campaign_gift_option_with_campaign_with_recurring_amount) do + create(:campaign_gift_option_with_campaign_with_recurring_amount, + campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) + end + let(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount) do + create(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount, + campaign: campaign_gift_option_with_campaign_with_one_time_amount.campaign) + end + + def base_path(nonprofit_id, campaign_id, campaign_gift_option_id) + "/api/nonprofits/#{nonprofit_id}/campaigns/#{campaign_id}/campaign_gift_options/#{campaign_gift_option_id}" + end + + def base_url(nonprofit_id, campaign_id, campaign_gift_option_id) + "http://test.host#{base_path(nonprofit_id, campaign_id, campaign_gift_option_id)}" + end + + it { expect(json["data"].count).to eq 3 } + + describe "details of the campaign_gift_option_with_campaign_with_one_time_amount" do + subject(:first) do + json["data"][0] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_one_time_amount } + + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has one time amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time description") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => nil) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 200, "currency" => nonprofit.currency}, + "recurrence" => nil + }] + )) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) + } + end + + describe "details of the campaign_gift_option_with_campaign_with_recurring_amount" do + subject(:second) do + json["data"][1] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_recurring_amount } + + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has recurring amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "a recurring description!") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => 4) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} + }] + )) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) + } + end + + describe "details of the campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount" do + subject(:third) do + json["data"][2] + end + + let(:campaign_gift_option) { campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount } + + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has both one time and recurring amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time AND recurring") + } + + it { + is_expected.to include("hide_contributions" => true) + } + + it { + is_expected.to include("order" => 5) + } + + it { + is_expected.to include("to_ship" => true) + } + + it { + is_expected.to include("quantity" => 50) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [ + { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} + }, + { + "amount" => {"cents" => 300, "currency" => nonprofit.currency}, + "recurrence" => nil + } + + ] + )) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) + } + end + + describe "paging" do + subject(:json) do + cgo + 6.times do |i| + create(:campaign_gift_option_with_campaign_with_one_time_amount, campaign: cgo.campaign, name: i) + end + assign(:campaign_gift_options, cgo.campaign.campaign_gift_options.order("id DESC").page.per(5)) + render + JSON.parse(rendered) + end + + let(:cgo) { create(:campaign_gift_option_with_campaign_with_one_time_amount) } + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/campaign_gift_options/show.json.jbuilder_spec.rb b/spec/views/api/campaign_gift_options/show.json.jbuilder_spec.rb index 8ae039c00a..48e9b8f8ed 100644 --- a/spec/views/api/campaign_gift_options/show.json.jbuilder_spec.rb +++ b/spec/views/api/campaign_gift_options/show.json.jbuilder_spec.rb @@ -2,237 +2,237 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/campaign_gift_options/show.json.jbuilder' do - def base_path(nonprofit_id, campaign_id, campaign_gift_option_id) - "/api/nonprofits/#{nonprofit_id}/campaigns/#{campaign_id}/campaign_gift_options/#{campaign_gift_option_id}" - end - - def base_url(nonprofit_id, campaign_id, campaign_gift_option_id) - "http://test.host#{base_path(nonprofit_id, campaign_id, campaign_gift_option_id)}" - end - - context 'when campaign gift option only has one time amount' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:campaign_gift_option, campaign_gift_option) - render - JSON.parse(rendered) - end - - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - let(:campaign_gift_option) { create(:campaign_gift_option_with_campaign_with_one_time_amount) } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has one time amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time description') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => nil) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 200, 'currency' => nonprofit.currency }, - 'recurrence' => nil - }] - )) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) - } - end - - context 'when campaign gift option only has recurring amount' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:campaign_gift_option, campaign_gift_option) - render - JSON.parse(rendered) - end - - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - let(:campaign_gift_option) { create(:campaign_gift_option_with_campaign_with_recurring_amount) } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has recurring amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'a recurring description!') - } - - it { - is_expected.to include('hide_contributions' => false) - } - - it { - is_expected.to include('order' => nil) - } - - it { - is_expected.to include('to_ship' => false) - } - - it { - is_expected.to include('quantity' => 4) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [{ - 'amount' => { 'cents' => 400, 'currency' => nonprofit.currency }, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly' } - }] - )) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) - } - end - - context 'when campaign gift option both one time and recurring amount' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:campaign_gift_option, campaign_gift_option) - render - JSON.parse(rendered) - end - - let(:campaign) { campaign_gift_option.campaign } - let(:nonprofit) { campaign_gift_option.nonprofit } - - let(:campaign_gift_option) { create(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount) } - - it { - is_expected.to include('object' => 'campaign_gift_option') - } - - it { - is_expected.to include('id' => campaign_gift_option.id) - } - - it { - is_expected.to include('name' => 'has both one time and recurring amount') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('campaign' => campaign.id) - } - - it { - is_expected.to include('description' => 'one time AND recurring') - } - - it { - is_expected.to include('hide_contributions' => true) - } - - it { - is_expected.to include('order' => 5) - } - - it { - is_expected.to include('to_ship' => true) - } - - it { - is_expected.to include('quantity' => 50) - } - - it { - is_expected.to include('gift_option_amount' => match_array( - [ - { - 'amount' => { 'cents' => 500, 'currency' => nonprofit.currency }, - 'recurrence' => { 'interval' => 1, 'type' => 'monthly' } - }, - { - 'amount' => { 'cents' => 300, 'currency' => nonprofit.currency }, - 'recurrence' => nil - } - - ] - )) - } - - it { - is_expected.to include('url' => - base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) - } - end +require "rails_helper" + +RSpec.describe "/api/campaign_gift_options/show.json.jbuilder" do + def base_path(nonprofit_id, campaign_id, campaign_gift_option_id) + "/api/nonprofits/#{nonprofit_id}/campaigns/#{campaign_id}/campaign_gift_options/#{campaign_gift_option_id}" + end + + def base_url(nonprofit_id, campaign_id, campaign_gift_option_id) + "http://test.host#{base_path(nonprofit_id, campaign_id, campaign_gift_option_id)}" + end + + context "when campaign gift option only has one time amount" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:campaign_gift_option, campaign_gift_option) + render + JSON.parse(rendered) + end + + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + let(:campaign_gift_option) { create(:campaign_gift_option_with_campaign_with_one_time_amount) } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has one time amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time description") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => nil) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 200, "currency" => nonprofit.currency}, + "recurrence" => nil + }] + )) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) + } + end + + context "when campaign gift option only has recurring amount" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:campaign_gift_option, campaign_gift_option) + render + JSON.parse(rendered) + end + + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + let(:campaign_gift_option) { create(:campaign_gift_option_with_campaign_with_recurring_amount) } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has recurring amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "a recurring description!") + } + + it { + is_expected.to include("hide_contributions" => false) + } + + it { + is_expected.to include("order" => nil) + } + + it { + is_expected.to include("to_ship" => false) + } + + it { + is_expected.to include("quantity" => 4) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [{ + "amount" => {"cents" => 400, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} + }] + )) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) + } + end + + context "when campaign gift option both one time and recurring amount" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:campaign_gift_option, campaign_gift_option) + render + JSON.parse(rendered) + end + + let(:campaign) { campaign_gift_option.campaign } + let(:nonprofit) { campaign_gift_option.nonprofit } + + let(:campaign_gift_option) { create(:campaign_gift_option_with_campaign_with_both_one_time_and_recurring_amount) } + + it { + is_expected.to include("object" => "campaign_gift_option") + } + + it { + is_expected.to include("id" => campaign_gift_option.id) + } + + it { + is_expected.to include("name" => "has both one time and recurring amount") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("campaign" => campaign.id) + } + + it { + is_expected.to include("description" => "one time AND recurring") + } + + it { + is_expected.to include("hide_contributions" => true) + } + + it { + is_expected.to include("order" => 5) + } + + it { + is_expected.to include("to_ship" => true) + } + + it { + is_expected.to include("quantity" => 50) + } + + it { + is_expected.to include("gift_option_amount" => match_array( + [ + { + "amount" => {"cents" => 500, "currency" => nonprofit.currency}, + "recurrence" => {"interval" => 1, "type" => "monthly"} + }, + { + "amount" => {"cents" => 300, "currency" => nonprofit.currency}, + "recurrence" => nil + } + + ] + )) + } + + it { + is_expected.to include("url" => + base_url(nonprofit.id, campaign.id, campaign_gift_option.id)) + } + end end diff --git a/spec/views/api/campaigns/show.json.jbuilder_spec.rb b/spec/views/api/campaigns/show.json.jbuilder_spec.rb index 65934bd375..1ef537fd60 100644 --- a/spec/views/api/campaigns/show.json.jbuilder_spec.rb +++ b/spec/views/api/campaigns/show.json.jbuilder_spec.rb @@ -2,38 +2,38 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/campaigns/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:campaign, campaign) - render - JSON.parse(rendered) - end - - let(:campaign) { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } - let(:id) { json['id'] } - let(:nonprofit) { campaign.nonprofit } - - it { - is_expected.to include('object' => 'campaign') - } - - it { - is_expected.to include('id' => campaign.id) - } - - it { - is_expected.to include('name' => campaign.name) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}})) - } +require "rails_helper" + +RSpec.describe "/api/campaigns/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:campaign, campaign) + render + JSON.parse(rendered) + end + + let(:campaign) { create(:fv_poverty_fighting_campaign_with_nonprofit_and_profile) } + let(:id) { json["id"] } + let(:nonprofit) { campaign.nonprofit } + + it { + is_expected.to include("object" => "campaign") + } + + it { + is_expected.to include("id" => campaign.id) + } + + it { + is_expected.to include("name" => campaign.name) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/campaigns/#{campaign.id}})) + } end diff --git a/spec/views/api/custom_field_definitions/index.json.jbuilder_spec.rb b/spec/views/api/custom_field_definitions/index.json.jbuilder_spec.rb index 4cc5445d50..e24e605217 100644 --- a/spec/views/api/custom_field_definitions/index.json.jbuilder_spec.rb +++ b/spec/views/api/custom_field_definitions/index.json.jbuilder_spec.rb @@ -2,71 +2,71 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/custom_field_definitions/index.json.jbuilder' do - subject(:json) do - assign(:custom_field_definitions, Kaminari.paginate_array([custom_field_definition]).page) - render - JSON.parse(rendered) - end +RSpec.describe "/api/custom_field_definitions/index.json.jbuilder" do + subject(:json) do + assign(:custom_field_definitions, Kaminari.paginate_array([custom_field_definition]).page) + render + JSON.parse(rendered) + end - let(:custom_field_definition) { create(:custom_field_definition_with_nonprofit) } - let(:nonprofit) { custom_field_definition.nonprofit } + let(:custom_field_definition) { create(:custom_field_definition_with_nonprofit) } + let(:nonprofit) { custom_field_definition.nonprofit } - it { expect(json['data'].count).to eq 1 } + it { expect(json["data"].count).to eq 1 } - describe 'details of the first item' do - subject(:first) do - json['data'].first - end + describe "details of the first item" do + subject(:first) do + json["data"].first + end - it { - is_expected.to include('object' => 'custom_field_definition') - } + it { + is_expected.to include("object" => "custom_field_definition") + } - it { - is_expected.to include('id' => custom_field_definition.id) - } + it { + is_expected.to include("id" => custom_field_definition.id) + } - it { - is_expected.to include('name' => 'Def Name') - } + it { + is_expected.to include("name" => "Def Name") + } - it { - is_expected.to include('nonprofit' => nonprofit.id) - } + it { + is_expected.to include("nonprofit" => nonprofit.id) + } - it { - is_expected.to include('deleted' => false) - } + it { + is_expected.to include("deleted" => false) + } - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} - )) - } - end + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} + )) + } + end - describe 'paging' do - subject(:json) do - custom_field_definition - 6.times do |i| - create(:custom_field_definition_with_nonprofit, - nonprofit: nonprofit, - name: i) - end - assign(:custom_field_definitions, nonprofit.custom_field_definitions.order('id DESC').page.per(5)) - render - JSON.parse(rendered) - end + describe "paging" do + subject(:json) do + custom_field_definition + 6.times do |i| + create(:custom_field_definition_with_nonprofit, + nonprofit: nonprofit, + name: i) + end + assign(:custom_field_definitions, nonprofit.custom_field_definitions.order("id DESC").page.per(5)) + render + JSON.parse(rendered) + end - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/custom_field_definitions/show.json.jbuilder_spec.rb b/spec/views/api/custom_field_definitions/show.json.jbuilder_spec.rb index e8c5c3dbfb..1a814bc79c 100644 --- a/spec/views/api/custom_field_definitions/show.json.jbuilder_spec.rb +++ b/spec/views/api/custom_field_definitions/show.json.jbuilder_spec.rb @@ -2,43 +2,43 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/custom_field_definitions/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:custom_field_definition, custom_field_definition) - render - JSON.parse(rendered) - end - - let(:custom_field_definition) { create(:custom_field_definition_with_nonprofit) } - let(:nonprofit) { custom_field_definition.nonprofit } - - it { - is_expected.to include('object' => 'custom_field_definition') - } - - it { - is_expected.to include('id' => custom_field_definition.id) - } - - it { - is_expected.to include('name' => 'Def Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} - )) - } +require "rails_helper" + +RSpec.describe "/api/custom_field_definitions/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:custom_field_definition, custom_field_definition) + render + JSON.parse(rendered) + end + + let(:custom_field_definition) { create(:custom_field_definition_with_nonprofit) } + let(:nonprofit) { custom_field_definition.nonprofit } + + it { + is_expected.to include("object" => "custom_field_definition") + } + + it { + is_expected.to include("id" => custom_field_definition.id) + } + + it { + is_expected.to include("name" => "Def Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/custom_field_definitions/#{custom_field_definition.id}} + )) + } end diff --git a/spec/views/api/events/show.json.jbuilder_spec.rb b/spec/views/api/events/show.json.jbuilder_spec.rb index 5d6b9f15e4..76e8d3fc18 100644 --- a/spec/views/api/events/show.json.jbuilder_spec.rb +++ b/spec/views/api/events/show.json.jbuilder_spec.rb @@ -2,38 +2,38 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/events/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:event, event) - render - JSON.parse(rendered) - end - - let(:event) { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } - let(:id) { json['id'] } - let(:nonprofit) { event.nonprofit } - - it { - is_expected.to include('object' => 'event') - } - - it { - is_expected.to include('id' => event.id) - } - - it { - is_expected.to include('name' => event.name) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/events/#{event.id}})) - } +require "rails_helper" + +RSpec.describe "/api/events/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:event, event) + render + JSON.parse(rendered) + end + + let(:event) { create(:fv_poverty_fighting_event_with_nonprofit_and_profile) } + let(:id) { json["id"] } + let(:nonprofit) { event.nonprofit } + + it { + is_expected.to include("object" => "event") + } + + it { + is_expected.to include("id" => event.id) + } + + it { + is_expected.to include("name" => event.name) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/events/#{event.id}})) + } end diff --git a/spec/views/api/nonprofits/show.json.jbuilder_spec.rb b/spec/views/api/nonprofits/show.json.jbuilder_spec.rb index dcab474698..9b03c75e32 100644 --- a/spec/views/api/nonprofits/show.json.jbuilder_spec.rb +++ b/spec/views/api/nonprofits/show.json.jbuilder_spec.rb @@ -2,27 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/nonprofits/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:nonprofit, nonprofit) - render - JSON.parse(rendered) - end +RSpec.describe "/api/nonprofits/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:nonprofit, nonprofit) + render + JSON.parse(rendered) + end - let(:nonprofit) { create(:fv_poverty) } + let(:nonprofit) { create(:fv_poverty) } - it { - is_expected.to include('id' => nonprofit.id) - } + it { + is_expected.to include("id" => nonprofit.id) + } - it { - is_expected.to include('name' => nonprofit.name) - } + it { + is_expected.to include("name" => nonprofit.name) + } - it { - is_expected.to include('object' => 'nonprofit') - } + it { + is_expected.to include("object" => "nonprofit") + } end diff --git a/spec/views/api/payments/show.json.jbuilder_spec.rb b/spec/views/api/payments/show.json.jbuilder_spec.rb index be1a67131e..52b3d58210 100644 --- a/spec/views/api/payments/show.json.jbuilder_spec.rb +++ b/spec/views/api/payments/show.json.jbuilder_spec.rb @@ -2,45 +2,45 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe 'api/payments/show.json.jbuilder' do - def base_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" - end - - def subtransaction_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" - end - - def base_url(nonprofit_id, transaction_id) - "http://test.host#{base_path(nonprofit_id, transaction_id)}" - end - - def subtransaction_url(nonprofit_id, transaction_id) - "http://test.host#{subtransaction_path(nonprofit_id, transaction_id)}" - end - - def payment_path(nonprofit_id, transaction_id, payment_id) - "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" - end - - def payment_url(nonprofit_id, transaction_id, payment_id) - "http://test.host#{payment_path(nonprofit_id, transaction_id, payment_id)}" - end - - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:payment, payment) - render - JSON.parse(rendered) - end - - let(:transaction) { create(:transaction_for_donation) } - let(:subtransaction) { transaction.subtransaction } - let(:payment) { subtransaction.payments.first } - let(:supporter) { payment.supporter } - let(:nonprofit) { payment.nonprofit } - - include_context 'with json results for first payment on transaction_for_donation' +require "rails_helper" + +RSpec.describe "api/payments/show.json.jbuilder" do + def base_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" + end + + def subtransaction_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" + end + + def base_url(nonprofit_id, transaction_id) + "http://test.host#{base_path(nonprofit_id, transaction_id)}" + end + + def subtransaction_url(nonprofit_id, transaction_id) + "http://test.host#{subtransaction_path(nonprofit_id, transaction_id)}" + end + + def payment_path(nonprofit_id, transaction_id, payment_id) + "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" + end + + def payment_url(nonprofit_id, transaction_id, payment_id) + "http://test.host#{payment_path(nonprofit_id, transaction_id, payment_id)}" + end + + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:payment, payment) + render + JSON.parse(rendered) + end + + let(:transaction) { create(:transaction_for_donation) } + let(:subtransaction) { transaction.subtransaction } + let(:payment) { subtransaction.payments.first } + let(:supporter) { payment.supporter } + let(:nonprofit) { payment.nonprofit } + + include_context "with json results for first payment on transaction_for_donation" end diff --git a/spec/views/api/supporter_addresses/index.json.jbuilder_spec.rb b/spec/views/api/supporter_addresses/index.json.jbuilder_spec.rb index 2c7593db9f..5f4ac86a48 100644 --- a/spec/views/api/supporter_addresses/index.json.jbuilder_spec.rb +++ b/spec/views/api/supporter_addresses/index.json.jbuilder_spec.rb @@ -2,87 +2,87 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/supporter_addresses/index.json.jbuilder' do - subject(:json) do - assign( - :supporter_addresses, - supporter_with_fv_poverty - .nonprofit - .supporters - .where(id: supporter_with_fv_poverty.id).order('id DESC').page - ) - render - JSON.parse(rendered) - end - - let(:supporter_with_fv_poverty) { create(:supporter_with_fv_poverty) } - - it { - expect(json['data'].count).to eq 1 - } - - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => true) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 25) } - it { is_expected.to include('total_count' => 1) } - - describe 'details of the first item' do - subject(:first) do - json['data'][0] - end - - let(:supporter) { supporter_with_fv_poverty } - let(:supporter_address) { supporter } - let(:nonprofit) { supporter.nonprofit } - - it { - is_expected.to include('object' => 'supporter_address') - } - - it { - is_expected.to include('id' => supporter_address.id) - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('address' => supporter_address.address) - } - - it { - is_expected.to include('city' => supporter_address.city) - } - - it { - is_expected.to include('state_code' => supporter_address.state_code) - } - - it { - is_expected.to include('country' => supporter_address.country) - } - - it { - is_expected.to include('zip_code' => supporter_address.zip_code) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength - )) - } - end +require "rails_helper" + +RSpec.describe "/api/supporter_addresses/index.json.jbuilder" do + subject(:json) do + assign( + :supporter_addresses, + supporter_with_fv_poverty + .nonprofit + .supporters + .where(id: supporter_with_fv_poverty.id).order("id DESC").page + ) + render + JSON.parse(rendered) + end + + let(:supporter_with_fv_poverty) { create(:supporter_with_fv_poverty) } + + it { + expect(json["data"].count).to eq 1 + } + + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => true) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 25) } + it { is_expected.to include("total_count" => 1) } + + describe "details of the first item" do + subject(:first) do + json["data"][0] + end + + let(:supporter) { supporter_with_fv_poverty } + let(:supporter_address) { supporter } + let(:nonprofit) { supporter.nonprofit } + + it { + is_expected.to include("object" => "supporter_address") + } + + it { + is_expected.to include("id" => supporter_address.id) + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("address" => supporter_address.address) + } + + it { + is_expected.to include("city" => supporter_address.city) + } + + it { + is_expected.to include("state_code" => supporter_address.state_code) + } + + it { + is_expected.to include("country" => supporter_address.country) + } + + it { + is_expected.to include("zip_code" => supporter_address.zip_code) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength + )) + } + end end diff --git a/spec/views/api/supporter_addresses/show.json.jbuilder_spec.rb b/spec/views/api/supporter_addresses/show.json.jbuilder_spec.rb index 41e871761e..32cd460a00 100644 --- a/spec/views/api/supporter_addresses/show.json.jbuilder_spec.rb +++ b/spec/views/api/supporter_addresses/show.json.jbuilder_spec.rb @@ -2,66 +2,66 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/supporter_addresses/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:supporter_address, supporter_address) - render - JSON.parse(rendered) - end +RSpec.describe "/api/supporter_addresses/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:supporter_address, supporter_address) + render + JSON.parse(rendered) + end - let(:supporter) { create(:supporter_with_fv_poverty) } - let(:id) { json['id'] } - let(:nonprofit) { supporter.nonprofit } + let(:supporter) { create(:supporter_with_fv_poverty) } + let(:id) { json["id"] } + let(:nonprofit) { supporter.nonprofit } - let(:supporter_address) { supporter } + let(:supporter_address) { supporter } - it { - is_expected.to include('object' => 'supporter_address') - } + it { + is_expected.to include("object" => "supporter_address") + } - it { - is_expected.to include('id' => supporter_address.id) - } + it { + is_expected.to include("id" => supporter_address.id) + } - it { - is_expected.to include('nonprofit' => nonprofit.id) - } + it { + is_expected.to include("nonprofit" => nonprofit.id) + } - it { - is_expected.to include('deleted' => false) - } + it { + is_expected.to include("deleted" => false) + } - it { - is_expected.to include('supporter' => supporter.id) - } + it { + is_expected.to include("supporter" => supporter.id) + } - it { - is_expected.to include('address' => supporter_address.address) - } + it { + is_expected.to include("address" => supporter_address.address) + } - it { - is_expected.to include('city' => supporter_address.city) - } + it { + is_expected.to include("city" => supporter_address.city) + } - it { - is_expected.to include('state_code' => supporter_address.state_code) - } + it { + is_expected.to include("state_code" => supporter_address.state_code) + } - it { - is_expected.to include('country' => supporter_address.country) - } + it { + is_expected.to include("country" => supporter_address.country) + } - it { - is_expected.to include('zip_code' => supporter_address.zip_code) - } + it { + is_expected.to include("zip_code" => supporter_address.zip_code) + } - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength - )) - } + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_addresses/#{supporter_address.id}} # rubocop:disable Layout/LineLength + )) + } end diff --git a/spec/views/api/supporter_notes/index.json.jbuilder_spec.rb b/spec/views/api/supporter_notes/index.json.jbuilder_spec.rb index b5bfd269fd..b02a73badd 100644 --- a/spec/views/api/supporter_notes/index.json.jbuilder_spec.rb +++ b/spec/views/api/supporter_notes/index.json.jbuilder_spec.rb @@ -2,84 +2,84 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/supporter_notes/index.json.jbuilder' do - subject(:json) do - assign(:supporter_notes, supporter_note_with_fv_poverty_with_user.supporter.supporter_notes.order('id DESC').page) - render - JSON.parse(rendered) - end - - let(:supporter_note_with_fv_poverty_with_user) { create(:supporter_note_with_fv_poverty_with_user) } - - it { expect(['data'].count).to eq 1 } - - describe 'details of the first item' do - subject(:first) do - json['data'].first - end - - let(:supporter_note) { supporter_note_with_fv_poverty_with_user } - - let(:supporter) { supporter_note.supporter } - let(:nonprofit) { supporter.nonprofit } - let(:user) { supporter_note.user } - - it { - is_expected.to include('object' => 'supporter_note') - } - - it { - is_expected.to include('id' => supporter_note.id) - } - - it { - is_expected.to include('content' => 'Some content in our note') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('user' => user.id) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} # rubocop:disable Layout/LineLength - )) - } - end - - describe 'paging' do - subject(:json) do - 6.times do |i| - create(:supporter_note_with_fv_poverty_with_user, - supporter: supporter_note_with_fv_poverty_with_user.supporter, - content: "content for #{i}") - end - assign(:supporter_notes, - supporter_note_with_fv_poverty_with_user.supporter.supporter_notes.order('id DESC').page.per(5)) - render - JSON.parse(rendered) - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end +require "rails_helper" + +RSpec.describe "/api/supporter_notes/index.json.jbuilder" do + subject(:json) do + assign(:supporter_notes, supporter_note_with_fv_poverty_with_user.supporter.supporter_notes.order("id DESC").page) + render + JSON.parse(rendered) + end + + let(:supporter_note_with_fv_poverty_with_user) { create(:supporter_note_with_fv_poverty_with_user) } + + it { expect(["data"].size).to eq 1 } + + describe "details of the first item" do + subject(:first) do + json["data"].first + end + + let(:supporter_note) { supporter_note_with_fv_poverty_with_user } + + let(:supporter) { supporter_note.supporter } + let(:nonprofit) { supporter.nonprofit } + let(:user) { supporter_note.user } + + it { + is_expected.to include("object" => "supporter_note") + } + + it { + is_expected.to include("id" => supporter_note.id) + } + + it { + is_expected.to include("content" => "Some content in our note") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("user" => user.id) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} # rubocop:disable Layout/LineLength + )) + } + end + + describe "paging" do + subject(:json) do + 6.times do |i| + create(:supporter_note_with_fv_poverty_with_user, + supporter: supporter_note_with_fv_poverty_with_user.supporter, + content: "content for #{i}") + end + assign(:supporter_notes, + supporter_note_with_fv_poverty_with_user.supporter.supporter_notes.order("id DESC").page.per(5)) + render + JSON.parse(rendered) + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/supporter_notes/show.json.jbuilder_spec.rb b/spec/views/api/supporter_notes/show.json.jbuilder_spec.rb index 2a53e79257..a717730378 100644 --- a/spec/views/api/supporter_notes/show.json.jbuilder_spec.rb +++ b/spec/views/api/supporter_notes/show.json.jbuilder_spec.rb @@ -2,54 +2,54 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/supporter_notes/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:supporter_note, supporter_note) - render - JSON.parse(rendered) - end - - let(:supporter) { supporter_note.supporter } - let(:nonprofit) { supporter.nonprofit } - let(:user) { supporter_note.user } - - let(:supporter_note) { create(:supporter_note_with_fv_poverty_with_user) } - - it { - is_expected.to include('object' => 'supporter_note') - } - - it { - is_expected.to include('id' => supporter_note.id) - } - - it { - is_expected.to include('content' => 'Some content in our note') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('supporter' => supporter.id) - } - - it { - is_expected.to include('user' => user.id) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} - )) - } +require "rails_helper" + +RSpec.describe "/api/supporter_notes/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:supporter_note, supporter_note) + render + JSON.parse(rendered) + end + + let(:supporter) { supporter_note.supporter } + let(:nonprofit) { supporter.nonprofit } + let(:user) { supporter_note.user } + + let(:supporter_note) { create(:supporter_note_with_fv_poverty_with_user) } + + it { + is_expected.to include("object" => "supporter_note") + } + + it { + is_expected.to include("id" => supporter_note.id) + } + + it { + is_expected.to include("content" => "Some content in our note") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("supporter" => supporter.id) + } + + it { + is_expected.to include("user" => user.id) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}/supporter_notes/#{supporter_note.id}} + )) + } end diff --git a/spec/views/api/supporters/index.json.jbuilder_spec.rb b/spec/views/api/supporters/index.json.jbuilder_spec.rb index 2c1e557102..697ebb9644 100644 --- a/spec/views/api/supporters/index.json.jbuilder_spec.rb +++ b/spec/views/api/supporters/index.json.jbuilder_spec.rb @@ -2,92 +2,92 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/supporters/index.json.jbuilder' do - subject(:json) do - assign(:supporters, supporter_with_fv_poverty.nonprofit.supporters.order('id DESC').page) - render - JSON.parse(rendered) - end - - let(:supporter_with_fv_poverty) { create(:supporter_with_fv_poverty) } - - it { expect(json['data'].count).to eq 1 } - - describe 'details of the first item' do - subject(:first) do - json['data'].first - end - - let(:supporter) { supporter_with_fv_poverty } - let(:nonprofit) { supporter.nonprofit } - - let(:id) { first['id'] } - - it { - is_expected.to include('object' => 'supporter') - } - - it { - is_expected.to include('id' => supporter.id) - } - - it { - is_expected.to include('name' => 'Fake Supporter Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('anonymous' => false) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('merged_into' => nil) - } - - it { - is_expected.to include('organization' => nil) - } - - it { - is_expected.to include('phone' => nil) - } - - it { - is_expected.to include('supporter_addresses' => [id]) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) - } - end - - describe 'paging' do - subject(:json) do - supporter_with_fv_poverty - 6.times do |i| - create(:supporter_with_fv_poverty, nonprofit: supporter_with_fv_poverty.nonprofit, name: i, - email: "email#{i}@email#{i}.com") - end - assign(:supporters, supporter_with_fv_poverty.nonprofit.supporters.order('id DESC').page.per(5)) - render - JSON.parse(rendered) - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end +require "rails_helper" + +RSpec.describe "/api/supporters/index.json.jbuilder" do + subject(:json) do + assign(:supporters, supporter_with_fv_poverty.nonprofit.supporters.order("id DESC").page) + render + JSON.parse(rendered) + end + + let(:supporter_with_fv_poverty) { create(:supporter_with_fv_poverty) } + + it { expect(json["data"].count).to eq 1 } + + describe "details of the first item" do + subject(:first) do + json["data"].first + end + + let(:supporter) { supporter_with_fv_poverty } + let(:nonprofit) { supporter.nonprofit } + + let(:id) { first["id"] } + + it { + is_expected.to include("object" => "supporter") + } + + it { + is_expected.to include("id" => supporter.id) + } + + it { + is_expected.to include("name" => "Fake Supporter Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("anonymous" => false) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("merged_into" => nil) + } + + it { + is_expected.to include("organization" => nil) + } + + it { + is_expected.to include("phone" => nil) + } + + it { + is_expected.to include("supporter_addresses" => [id]) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) + } + end + + describe "paging" do + subject(:json) do + supporter_with_fv_poverty + 6.times do |i| + create(:supporter_with_fv_poverty, nonprofit: supporter_with_fv_poverty.nonprofit, name: i, + email: "email#{i}@email#{i}.com") + end + assign(:supporters, supporter_with_fv_poverty.nonprofit.supporters.order("id DESC").page.per(5)) + render + JSON.parse(rendered) + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/supporters/show.json.jbuilder_spec.rb b/spec/views/api/supporters/show.json.jbuilder_spec.rb index 5f494db939..935217992b 100644 --- a/spec/views/api/supporters/show.json.jbuilder_spec.rb +++ b/spec/views/api/supporters/show.json.jbuilder_spec.rb @@ -2,62 +2,62 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/supporters/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:supporter, supporter) - render - JSON.parse(rendered) - end - - let(:supporter) { create(:supporter_with_fv_poverty) } - let(:id) { json['id'] } - let(:nonprofit) { supporter.nonprofit } - - it { - is_expected.to include('object' => 'supporter') - } - - it { - is_expected.to include('id' => supporter.id) - } - - it { - is_expected.to include('name' => 'Fake Supporter Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('anonymous' => false) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('merged_into' => nil) - } - - it { - is_expected.to include('organization' => nil) - } - - it { - is_expected.to include('phone' => nil) - } - - it { - is_expected.to include('supporter_addresses' => [id]) - } - - it { - is_expected.to include('url' => - a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) - } +require "rails_helper" + +RSpec.describe "/api/supporters/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:supporter, supporter) + render + JSON.parse(rendered) + end + + let(:supporter) { create(:supporter_with_fv_poverty) } + let(:id) { json["id"] } + let(:nonprofit) { supporter.nonprofit } + + it { + is_expected.to include("object" => "supporter") + } + + it { + is_expected.to include("id" => supporter.id) + } + + it { + is_expected.to include("name" => "Fake Supporter Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("anonymous" => false) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("merged_into" => nil) + } + + it { + is_expected.to include("organization" => nil) + } + + it { + is_expected.to include("phone" => nil) + } + + it { + is_expected.to include("supporter_addresses" => [id]) + } + + it { + is_expected.to include("url" => + a_string_matching(%r{http://test\.host/api/nonprofits/#{nonprofit.id}/supporters/#{supporter.id}})) + } end diff --git a/spec/views/api/tag_definitions/index.json.jbuilder_spec.rb b/spec/views/api/tag_definitions/index.json.jbuilder_spec.rb index 94d929a27b..6f43a54402 100644 --- a/spec/views/api/tag_definitions/index.json.jbuilder_spec.rb +++ b/spec/views/api/tag_definitions/index.json.jbuilder_spec.rb @@ -2,71 +2,71 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/tag_definitions/index.json.jbuilder' do - subject(:json) do - assign(:tag_definitions, Kaminari.paginate_array([tag_definition]).page) - render - JSON.parse(rendered) - end +RSpec.describe "/api/tag_definitions/index.json.jbuilder" do + subject(:json) do + assign(:tag_definitions, Kaminari.paginate_array([tag_definition]).page) + render + JSON.parse(rendered) + end - let(:tag_definition) { create(:tag_definition_with_nonprofit) } - let(:nonprofit) { tag_definition.nonprofit } + let(:tag_definition) { create(:tag_definition_with_nonprofit) } + let(:nonprofit) { tag_definition.nonprofit } - it { expect(json['data'].count).to eq 1 } + it { expect(json["data"].count).to eq 1 } - describe 'details of the first item' do - subject(:first) do - json['data'].first - end + describe "details of the first item" do + subject(:first) do + json["data"].first + end - it { - is_expected.to include('object' => 'tag_definition') - } + it { + is_expected.to include("object" => "tag_definition") + } - it { - is_expected.to include('id' => tag_definition.id) - } + it { + is_expected.to include("id" => tag_definition.id) + } - it { - is_expected.to include('name' => 'Tag Name') - } + it { + is_expected.to include("name" => "Tag Name") + } - it { - is_expected.to include('nonprofit' => nonprofit.id) - } + it { + is_expected.to include("nonprofit" => nonprofit.id) + } - it { - is_expected.to include('deleted' => false) - } + it { + is_expected.to include("deleted" => false) + } - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} - )) - } - end + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} + )) + } + end - describe 'paging' do - subject(:json) do - tag_definition - 6.times do |i| - create(:tag_definition_with_nonprofit, - nonprofit: nonprofit, - name: i) - end - assign(:tag_definitions, nonprofit.tag_definitions.order('id DESC').page.per(5)) - render - JSON.parse(rendered) - end + describe "paging" do + subject(:json) do + tag_definition + 6.times do |i| + create(:tag_definition_with_nonprofit, + nonprofit: nonprofit, + name: i) + end + assign(:tag_definitions, nonprofit.tag_definitions.order("id DESC").page.per(5)) + render + JSON.parse(rendered) + end - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/tag_definitions/show.json.jbuilder_spec.rb b/spec/views/api/tag_definitions/show.json.jbuilder_spec.rb index 01fcd8960e..43b8ee3f96 100644 --- a/spec/views/api/tag_definitions/show.json.jbuilder_spec.rb +++ b/spec/views/api/tag_definitions/show.json.jbuilder_spec.rb @@ -2,43 +2,43 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/tag_definitions/show.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:tag_definition, tag_definition) - render - JSON.parse(rendered) - end - - let(:tag_definition) { create(:tag_definition_with_nonprofit) } - let(:nonprofit) { tag_definition.nonprofit } - - it { - is_expected.to include('object' => 'tag_definition') - } - - it { - is_expected.to include('id' => tag_definition.id) - } - - it { - is_expected.to include('name' => 'Tag Name') - } - - it { - is_expected.to include('nonprofit' => nonprofit.id) - } - - it { - is_expected.to include('deleted' => false) - } - - it { - is_expected.to include('url' => - a_string_matching( - %r{http://test\.host/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} - )) - } +require "rails_helper" + +RSpec.describe "/api/tag_definitions/show.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:tag_definition, tag_definition) + render + JSON.parse(rendered) + end + + let(:tag_definition) { create(:tag_definition_with_nonprofit) } + let(:nonprofit) { tag_definition.nonprofit } + + it { + is_expected.to include("object" => "tag_definition") + } + + it { + is_expected.to include("id" => tag_definition.id) + } + + it { + is_expected.to include("name" => "Tag Name") + } + + it { + is_expected.to include("nonprofit" => nonprofit.id) + } + + it { + is_expected.to include("deleted" => false) + } + + it { + is_expected.to include("url" => + a_string_matching( + %r{http://test\.host/api/nonprofits/#{nonprofit.id}/tag_definitions/#{tag_definition.id}} + )) + } end diff --git a/spec/views/api/ticket_levels/index.json.jbuilder_spec.rb b/spec/views/api/ticket_levels/index.json.jbuilder_spec.rb index 2ff6192fac..bf9f5d8d61 100644 --- a/spec/views/api/ticket_levels/index.json.jbuilder_spec.rb +++ b/spec/views/api/ticket_levels/index.json.jbuilder_spec.rb @@ -2,64 +2,64 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/ticket_levels/index.json.jbuilder' do - subject(:json) do - assign(:ticket_levels, Kaminari.paginate_array([ - ticket_level_with_event_non_admin__order_3__not_deleted - ]).page) - render - JSON.parse(rendered) - end +RSpec.describe "/api/ticket_levels/index.json.jbuilder" do + subject(:json) do + assign(:ticket_levels, Kaminari.paginate_array([ + ticket_level_with_event_non_admin__order_3__not_deleted + ]).page) + render + JSON.parse(rendered) + end - def base_path(nonprofit_id, event_id, ticket_level_id) - "/api/nonprofits/#{nonprofit_id}/events/#{event_id}/ticket_levels/#{ticket_level_id}" - end + def base_path(nonprofit_id, event_id, ticket_level_id) + "/api/nonprofits/#{nonprofit_id}/events/#{event_id}/ticket_levels/#{ticket_level_id}" + end - def base_url(nonprofit_id, event_id, ticket_level_id) - "http://test.host#{base_path(nonprofit_id, event_id, ticket_level_id)}" - end + def base_url(nonprofit_id, event_id, ticket_level_id) + "http://test.host#{base_path(nonprofit_id, event_id, ticket_level_id)}" + end - let(:ticket_level_with_event_non_admin__order_3__not_deleted) do - create(:ticket_level_with_event_non_admin__order_3__not_deleted) - end + let(:ticket_level_with_event_non_admin__order_3__not_deleted) do + create(:ticket_level_with_event_non_admin__order_3__not_deleted) + end - it { expect(json['data'].count).to eq 1 } + it { expect(json["data"].count).to eq 1 } - describe 'details of the :ticket_level_with_event_non_admin__order_3__not_deleted' do - subject do - json['data'][0] - end + describe "details of the :ticket_level_with_event_non_admin__order_3__not_deleted" do + subject do + json["data"][0] + end - let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } - let(:event) { ticket_level.event } - let(:nonprofit) { ticket_level.nonprofit } + let(:ticket_level) { ticket_level_with_event_non_admin__order_3__not_deleted } + let(:event) { ticket_level.event } + let(:nonprofit) { ticket_level.nonprofit } - include_context 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' - end + include_context "json results for ticket_level_with_event_non_admin__order_3__not_deleted" + end - describe 'paging' do - subject(:json) do - ticket_level_with_event_non_admin__order_3__not_deleted - 6.times do |i| - create( - :ticket_level_with_event_non_admin__order_3__not_deleted, - event: ticket_level_with_event_non_admin__order_3__not_deleted.event, - name: i - ) - end - assign(:ticket_levels, - ticket_level_with_event_non_admin__order_3__not_deleted.event.ticket_levels.order('id DESC').page.per(5)) - render - JSON.parse(rendered) - end + describe "paging" do + subject(:json) do + ticket_level_with_event_non_admin__order_3__not_deleted + 6.times do |i| + create( + :ticket_level_with_event_non_admin__order_3__not_deleted, + event: ticket_level_with_event_non_admin__order_3__not_deleted.event, + name: i + ) + end + assign(:ticket_levels, + ticket_level_with_event_non_admin__order_3__not_deleted.event.ticket_levels.order("id DESC").page.per(5)) + render + JSON.parse(rendered) + end - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/ticket_levels/show.json.jbuilder_spec.rb b/spec/views/api/ticket_levels/show.json.jbuilder_spec.rb index 82a4d07e2e..55fa4be47d 100644 --- a/spec/views/api/ticket_levels/show.json.jbuilder_spec.rb +++ b/spec/views/api/ticket_levels/show.json.jbuilder_spec.rb @@ -2,28 +2,28 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/ticket_levels/show.json.jbuilder' do - def base_path(nonprofit_id, event_id, ticket_level_id) - "/api/nonprofits/#{nonprofit_id}/events/#{event_id}/ticket_levels/#{ticket_level_id}" - end +RSpec.describe "/api/ticket_levels/show.json.jbuilder" do + def base_path(nonprofit_id, event_id, ticket_level_id) + "/api/nonprofits/#{nonprofit_id}/events/#{event_id}/ticket_levels/#{ticket_level_id}" + end - def base_url(nonprofit_id, event_id, ticket_level_id) - "http://test.host#{base_path(nonprofit_id, event_id, ticket_level_id)}" - end + def base_url(nonprofit_id, event_id, ticket_level_id) + "http://test.host#{base_path(nonprofit_id, event_id, ticket_level_id)}" + end - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:ticket_level, ticket_level) - render - JSON.parse(rendered) - end + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:ticket_level, ticket_level) + render + JSON.parse(rendered) + end - let(:event) { ticket_level.event } - let(:nonprofit) { ticket_level.nonprofit } + let(:event) { ticket_level.event } + let(:nonprofit) { ticket_level.nonprofit } - let(:ticket_level) { create(:ticket_level_with_event_non_admin__order_3__not_deleted) } + let(:ticket_level) { create(:ticket_level_with_event_non_admin__order_3__not_deleted) } - include_context 'json results for ticket_level_with_event_non_admin__order_3__not_deleted' + include_context "json results for ticket_level_with_event_non_admin__order_3__not_deleted" end diff --git a/spec/views/api/transactions/index.json.jbuilder_spec.rb b/spec/views/api/transactions/index.json.jbuilder_spec.rb index ae4ac803ed..328d46ecfd 100644 --- a/spec/views/api/transactions/index.json.jbuilder_spec.rb +++ b/spec/views/api/transactions/index.json.jbuilder_spec.rb @@ -2,57 +2,57 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe '/api/transactions/index.json.jbuilder' do - def base_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" - end - - def base_url(nonprofit_id, transaction_id) - "http://test.host#{base_path(nonprofit_id, transaction_id)}" - end - - subject(:json) do - assign(:transactions, Kaminari.paginate_array([transaction]).page) - render - JSON.parse(rendered) - end - - let(:transaction) { create(:transaction_for_donation) } - let(:supporter) { transaction.supporter } - let(:nonprofit) { transaction.nonprofit } - - it { expect(json['data'].count).to eq 1 } - - describe 'details of the first item' do - subject(:first) do - json['data'].first - end - - include_context 'with json results for transaction_for_donation' - end - - describe 'paging' do - subject(:json) do - transaction - 6.times do |_i| - create( - :transaction, - nonprofit: transaction.nonprofit, - supporter: transaction.supporter - ) - end - assign(:transactions, nonprofit.transactions.order('created DESC').page.per(5)) - render - JSON.parse(rendered) - end - - it { is_expected.to include('data' => have_attributes(count: 5)) } - it { is_expected.to include('first_page' => true) } - it { is_expected.to include('last_page' => false) } - it { is_expected.to include('current_page' => 1) } - it { is_expected.to include('requested_size' => 5) } - it { is_expected.to include('total_count' => 7) } - end +require "rails_helper" + +RSpec.describe "/api/transactions/index.json.jbuilder" do + def base_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" + end + + def base_url(nonprofit_id, transaction_id) + "http://test.host#{base_path(nonprofit_id, transaction_id)}" + end + + subject(:json) do + assign(:transactions, Kaminari.paginate_array([transaction]).page) + render + JSON.parse(rendered) + end + + let(:transaction) { create(:transaction_for_donation) } + let(:supporter) { transaction.supporter } + let(:nonprofit) { transaction.nonprofit } + + it { expect(json["data"].count).to eq 1 } + + describe "details of the first item" do + subject(:first) do + json["data"].first + end + + include_context "with json results for transaction_for_donation" + end + + describe "paging" do + subject(:json) do + transaction + 6.times do |_i| + create( + :transaction, + nonprofit: transaction.nonprofit, + supporter: transaction.supporter + ) + end + assign(:transactions, nonprofit.transactions.order("created DESC").page.per(5)) + render + JSON.parse(rendered) + end + + it { is_expected.to include("data" => have_attributes(count: 5)) } + it { is_expected.to include("first_page" => true) } + it { is_expected.to include("last_page" => false) } + it { is_expected.to include("current_page" => 1) } + it { is_expected.to include("requested_size" => 5) } + it { is_expected.to include("total_count" => 7) } + end end diff --git a/spec/views/api/transactions/show.json.jbuilder_spec.rb b/spec/views/api/transactions/show.json.jbuilder_spec.rb index cf428a4d2c..502a658059 100644 --- a/spec/views/api/transactions/show.json.jbuilder_spec.rb +++ b/spec/views/api/transactions/show.json.jbuilder_spec.rb @@ -2,27 +2,27 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/transactions/show.json.jbuilder' do - def base_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" - end +RSpec.describe "/api/transactions/show.json.jbuilder" do + def base_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" + end - def base_url(nonprofit_id, transaction_id) - "http://test.host#{base_path(nonprofit_id, transaction_id)}" - end - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:transaction, transaction) - render - JSON.parse(rendered) - end + def base_url(nonprofit_id, transaction_id) + "http://test.host#{base_path(nonprofit_id, transaction_id)}" + end + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:transaction, transaction) + render + JSON.parse(rendered) + end - let(:transaction) { create(:transaction_for_donation) } - let(:supporter) { transaction.supporter } - let(:id) { json['id'] } - let(:nonprofit) { transaction.nonprofit } + let(:transaction) { create(:transaction_for_donation) } + let(:supporter) { transaction.supporter } + let(:id) { json["id"] } + let(:nonprofit) { transaction.nonprofit } - include_context 'with json results for transaction_for_donation' + include_context "with json results for transaction_for_donation" end diff --git a/spec/views/api/transactions/subtransaction.json.jbuilder_spec.rb b/spec/views/api/transactions/subtransaction.json.jbuilder_spec.rb index 6d1c5724c6..a51ec0b185 100644 --- a/spec/views/api/transactions/subtransaction.json.jbuilder_spec.rb +++ b/spec/views/api/transactions/subtransaction.json.jbuilder_spec.rb @@ -2,45 +2,45 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' - -RSpec.describe 'api/transactions/subtransaction' do - def base_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" - end - - def subtransaction_path(nonprofit_id, transaction_id) - "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" - end - - def base_url(nonprofit_id, transaction_id) - "http://test.host#{base_path(nonprofit_id, transaction_id)}" - end - - def subtransaction_url(nonprofit_id, transaction_id) - "http://test.host#{subtransaction_path(nonprofit_id, transaction_id)}" - end - - def payment_path(nonprofit_id, transaction_id, payment_id) - "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" - end - - def payment_url(nonprofit_id, transaction_id, payment_id) - "http://test.host#{payment_path(nonprofit_id, transaction_id, payment_id)}" - end - - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:subtransaction, subtransaction) - render - JSON.parse(rendered) - end - - let(:transaction) { create(:transaction_for_donation) } - let(:subtransaction) { transaction.subtransaction } - let(:supporter) { subtransaction.supporter } - let(:id) { json['id'] } - let(:nonprofit) { subtransaction.nonprofit } - - include_context 'with json results for subtransaction on transaction_for_donation' +require "rails_helper" + +RSpec.describe "api/transactions/subtransaction" do + def base_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}" + end + + def subtransaction_path(nonprofit_id, transaction_id) + "/api/nonprofits/#{nonprofit_id}/transactions/#{transaction_id}/subtransaction" + end + + def base_url(nonprofit_id, transaction_id) + "http://test.host#{base_path(nonprofit_id, transaction_id)}" + end + + def subtransaction_url(nonprofit_id, transaction_id) + "http://test.host#{subtransaction_path(nonprofit_id, transaction_id)}" + end + + def payment_path(nonprofit_id, transaction_id, payment_id) + "#{subtransaction_path(nonprofit_id, transaction_id)}/payments/#{payment_id}" + end + + def payment_url(nonprofit_id, transaction_id, payment_id) + "http://test.host#{payment_path(nonprofit_id, transaction_id, payment_id)}" + end + + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:subtransaction, subtransaction) + render + JSON.parse(rendered) + end + + let(:transaction) { create(:transaction_for_donation) } + let(:subtransaction) { transaction.subtransaction } + let(:supporter) { subtransaction.supporter } + let(:id) { json["id"] } + let(:nonprofit) { subtransaction.nonprofit } + + include_context "with json results for subtransaction on transaction_for_donation" end diff --git a/spec/views/api/users/current.json.jbuilder_spec.rb b/spec/views/api/users/current.json.jbuilder_spec.rb index e5858a11f0..b6b48b9525 100644 --- a/spec/views/api/users/current.json.jbuilder_spec.rb +++ b/spec/views/api/users/current.json.jbuilder_spec.rb @@ -2,21 +2,21 @@ # License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE -require 'rails_helper' +require "rails_helper" -RSpec.describe '/api/users/current.json.jbuilder' do - subject(:json) do - view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) - assign(:user, create(:user)) - render - JSON.parse(rendered) - end +RSpec.describe "/api/users/current.json.jbuilder" do + subject(:json) do + view.lookup_context.prefixes = view.lookup_context.prefixes.drop(2) + assign(:user, create(:user)) + render + JSON.parse(rendered) + end - it { - is_expected.to include('id' => kind_of(Numeric)) - } + it { + is_expected.to include("id" => kind_of(Numeric)) + } - it { - is_expected.to include('object' => 'user') - } + it { + is_expected.to include("object" => "user") + } end diff --git a/turbo_test.rb b/turbo_test.rb index 80131d3d08..d3599886fc 100644 --- a/turbo_test.rb +++ b/turbo_test.rb @@ -4,12 +4,12 @@ # Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE # based on code at: https://github.com/ioquatix/turbo_test/issues/6 -ENV['RAILS_ENV'] = 'test' +ENV["RAILS_ENV"] = "test" worker do |index| - index += 1 - ENV['TEST_ENV_NUMBER'] = index == 1 ? '' : index.to_s - ENV['RAILS_ENV'] = 'test' - system('bin/rails', 'db:environment:set', 'RAILS_ENV=test') - system('bin/rails', 'db:drop', 'db:create', 'db:schema:load') + index += 1 + ENV["TEST_ENV_NUMBER"] = (index == 1) ? "" : index.to_s + ENV["RAILS_ENV"] = "test" + system("bin/rails", "db:environment:set", "RAILS_ENV=test") + system("bin/rails", "db:drop", "db:create", "db:schema:load") end