6772312ea7
The primary license of the project is changing to: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later with some specific files to be licensed under the one of two licenses: CC0-1.0 LGPL-3.0-or-later This commit is one of the many steps to relicense the entire codebase. Documentation granting permission for this relicensing (from all past contributors who hold copyrights) is on file with Software Freedom Conservancy, Inc.
163 lines
5.7 KiB
Ruby
163 lines
5.7 KiB
Ruby
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
|
require 'query/query_recurring_donations'
|
|
require 'insert/insert_supporter_notes'
|
|
require 'format/date'
|
|
require 'format/currency'
|
|
|
|
module UpdateRecurringDonations
|
|
|
|
# Update the card id and name for a given recurring donation (provide rd['donation_id'])
|
|
def self.update_card_id(rd, token)
|
|
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}
|
|
})
|
|
|
|
source_token = QuerySourceToken.get_and_increment_source_token(token, nil)
|
|
tokenizable = source_token.tokenizable
|
|
|
|
|
|
entities = RetrieveActiveRecordItems.retrieve_from_keys(rd, RecurringDonation => :id )
|
|
|
|
validate_entities(entities[:id], tokenizable)
|
|
|
|
Qx.transaction do
|
|
rec_don = entities[:id]
|
|
donation = rec_don.donation
|
|
#TODO This is stupid but the two are used together inconsistently. We should scrap one or the other.
|
|
donation.card = tokenizable
|
|
rec_don.card_id = tokenizable
|
|
|
|
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}])
|
|
end
|
|
return 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).include?(paydate.to_i)
|
|
Psql.execute(Qexpr.new.update(:recurring_donations, paydate: paydate).where("id=$id", id: rd['id']))
|
|
rd['paydate'] = paydate
|
|
return rd
|
|
end
|
|
|
|
# @param [RecurringDonation] rd
|
|
# @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}
|
|
})
|
|
source_token = QuerySourceToken.get_and_increment_source_token(token, nil)
|
|
tokenizable = source_token.tokenizable
|
|
|
|
validate_entities(rd, tokenizable)
|
|
|
|
previous_amount = rd.amount
|
|
donation = rd.donation
|
|
Qx.transaction do
|
|
#TODO This is stupid but the two are used together inconsistently. We should scrap one or the other.
|
|
rd.card = tokenizable
|
|
rd.amount = amount
|
|
rd.n_failures= 0
|
|
donation.card = tokenizable
|
|
donation.amount = amount
|
|
rd.save!
|
|
donation.save!
|
|
end
|
|
EmailJobQueue.queue(JobTypes::NonprofitRecurringDonationChangeAmountJob, rd.id, previous_amount)
|
|
EmailJobQueue.queue(JobTypes::DonorRecurringDonationChangeAmountJob,rd.id, previous_amount)
|
|
rd
|
|
end
|
|
|
|
|
|
def self.update_from_start_dates
|
|
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)
|
|
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)
|
|
)
|
|
rd = QueryRecurringDonations.fetch_for_edit(rd_id)['recurring_donation']
|
|
InsertSupporterNotes.create([{supporter_id: rd['supporter_id'], 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'])}", user_id: 540}])
|
|
if (!dont_notify_nonprofit)
|
|
DonationMailer.delay.nonprofit_recurring_donation_cancellation(rd['donation_id'])
|
|
end
|
|
return rd
|
|
end
|
|
|
|
|
|
def self.update(rd, params)
|
|
params = set_defaults(params)
|
|
if params[:donation]
|
|
rd.donation.update_attributes(params[:donation])
|
|
return rd.donation unless rd.donation.valid?
|
|
params = params.except(:donation)
|
|
end
|
|
|
|
rd.update_attributes(params)
|
|
return rd
|
|
end
|
|
|
|
|
|
def self.set_defaults(params)
|
|
if params[:donation] && params[:donation][:dollars]
|
|
params[:donation][:amount] = Format::Currency.dollars_to_cents(params[:donation][:dollars])
|
|
params[:donation] = params[:donation].except(:dollars)
|
|
params[:amount] = params[:donation][:amount]
|
|
end
|
|
|
|
if params[:end_date_str]
|
|
if params[:end_date_str].blank? || params[:end_date_str] == 'None'
|
|
params[:end_date] = nil
|
|
else
|
|
params[:end_date] = Chronic.parse(params[:end_date_str])
|
|
end
|
|
params = params.except(:end_date_str)
|
|
end
|
|
|
|
return params
|
|
end
|
|
|
|
# @param [RecurringDonation] rd
|
|
# @param [Card] tokenizable
|
|
def self.validate_entities(rd, tokenizable)
|
|
if (rd.cancelled_at)
|
|
raise ParamValidation::ValidationError.new("Recurring Donation #{rd.id} is already cancelled.", key: :id)
|
|
end
|
|
|
|
if (tokenizable.deleted)
|
|
raise ParamValidation::ValidationError.new("Tokenized card #{tokenizable.id} is not valid.", key: :token)
|
|
end
|
|
|
|
if tokenizable.holder != rd.supporter
|
|
raise ParamValidation::ValidationError.new("Supporter #{rd.supporter.id} does not own card #{tokenizable.id}", key: :token)
|
|
end
|
|
end
|
|
|
|
end
|
|
|