class DonationsImport < Import include Imports::Rollback include Imports::Validations include ArtfullyOseHelper def kind "donations" end def process(parsed_row) row_valid?(parsed_row) person = create_person(parsed_row) create_contribution(parsed_row, person) end def rollback rollback_orders rollback_people rollback_campaigns rollback_appeals end def before_import # Delayed::Worker.logger.add(Logger::INFO, "--------------- before campaigns_data ---------") @campaigns_hash = {} #{campaign_name => {start_date => xxx_date, end_date => xxx_date, goal => xxx_amount, id=xxx}} parsed_rows.each do |parsed_row, index| unless parsed_row.campaign.blank? campaign = parsed_row.campaign occurred_at = parsed_row.donation_date.blank? ? time_zone_parser.now : time_zone_parser.parse(parsed_row.donation_date) amount = parsed_row.amount if @campaigns_hash.has_key?(campaign) @campaigns_hash[campaign][:start_date] = [occurred_at, @campaigns_hash[campaign][:start_date]].min @campaigns_hash[campaign][:end_date] = [occurred_at, @campaigns_hash[campaign][:end_date]].max @campaigns_hash[campaign][:goal] = @campaigns_hash[campaign][:goal] + amount else @campaigns_hash[campaign] = {:start_date => occurred_at, :end_date => occurred_at, :goal => amount} end end end end def validate_amounts(parsed_row) if !parsed_row.unparsed_nongift_amount.blank? && parsed_row.nongift_amount > parsed_row.amount raise Import::RowError, "Non-deductible amount (#{parsed_row.unparsed_nongift_amount}) cannot be more than the total doantion amount (#{parsed_row.unparsed_amount})': #{parsed_row.row}" end if !parsed_row.unparsed_deductible_amount.blank? && parsed_row.deductible_amount > parsed_row.amount raise Import::RowError, "Deductible amount (#{parsed_row.unparsed_deductible_amount}) cannot be more than the total doantion amount (#{parsed_row.unparsed_amount})': #{parsed_row.row}" end if !parsed_row.unparsed_deductible_amount.blank? && !parsed_row.unparsed_nongift_amount.blank? && (parsed_row.deductible_amount + parsed_row.nongift_amount != parsed_row.amount) raise Import::RowError, "Deductible amount (#{parsed_row.unparsed_deductible_amount}) + Non-Deductible Amount (#{parsed_row.unparsed_nongift_amount}) does not equal Amount of in this row: #{parsed_row.row}" end end def row_valid?(parsed_row) raise Import::RowError, "No Amount included in this row: #{parsed_row.row}" if parsed_row.unparsed_amount.blank? raise Import::RowError, "Please include a first name, last name, email, or company name in this row: #{parsed_row.row}" unless attach_person(parsed_row).naming_details_available? raise Import::RowError, "Please include a payment method in this row: #{parsed_row.row}" if parsed_row.payment_method.blank? raise Import::RowError, "Donation type must be 'Monetary' or 'In-Kind': #{parsed_row.row}" unless GiveAction.subtypes.include? (parsed_row.donation_type) raise Import::RowError, "No Date included in this row: #{parsed_row.row}" unless parsed_row.donation_date valid_date? parsed_row.donation_date [:unparsed_amount, :unparsed_nongift_amount, :unparsed_deductible_amount].each do |amt| valid_amount? parsed_row.send(amt) unless parsed_row.send(amt).blank? end validate_amounts(parsed_row) true end def create_campaign(parsed_row, params) campaign_name = parsed_row.campaign if campaign_name.present? camp = self.organization.campaigns.where(:name => campaign_name).first_or_create do |campaign| campaign.import = self campaign.starts_at = @campaigns_hash[campaign_name] && @campaigns_hash[campaign_name][:start_date] ? @campaigns_hash[campaign_name][:start_date] : time_zone_parser.now campaign.ends_at = @campaigns_hash[campaign_name] && @campaigns_hash[campaign_name][:end_date] ? @campaigns_hash[campaign_name][:end_date] : time_zone_parser.now campaign.ends_at = nil if campaign.ends_at.to_s == campaign.starts_at.to_s campaign.goal = @campaigns_hash[campaign_name] && @campaigns_hash[campaign_name][:goal] ? @campaigns_hash[campaign_name][:goal] / 100 : 1000 campaign.status = 'active' end params[:campaign_id] = camp.id camp end end def create_appeal(parsed_row, campaign, params) if parsed_row.appeal.present? && !campaign.nil? a = campaign.appeals.where({:name => parsed_row.appeal, :organization_id => self.organization.id}).first_or_create do |appeal| appeal.import = self appeal.starts_at = campaign.starts_at appeal.channel = 'email' appeal.status = 'active' end params[:appeal_id] = a.id end end def create_match_eligible(parsed_row, params) matcher = parsed_row.match_eligible_matcher eligible_amount = parsed_row.match_eligible_amount if matcher.present? && matcher.include?("@") && eligible_amount > 0 # todo validate email matcher_person = Person.first_or_create({:email => matcher, :organization => self.organization}) do |p| p.import = self end params[:match_eligible] = 'true' params[:matcher] = matcher_person.id params[:eligible_amount] = eligible_amount params[:ratio] = parsed_row.match_eligible_ratio.to_f if parsed_row.match_eligible_ratio.to_f > 0 params[:commitment_date] = time_zone_parser.now.to_s end end def create_soft_credit(parsed_row, params) soft_credit_email = parsed_row.soft_credit_email soft_credit_first_name = parsed_row.soft_credit_first_name soft_credit_last_name = parsed_row.soft_credit_last_name soft_credit_amount = parsed_row.soft_credit_amount if soft_credit_email.present? && soft_credit_email.include?("@") && soft_credit_amount > 0 sc_person = Person.first_or_create({:email => soft_credit_email, :organization => self.organization}) do |p| p.import = self p.first_name = soft_credit_first_name p.last_name = soft_credit_last_name end params[:soft_credit] = {-Time.now.to_i => {:person_id => sc_person.id, :amount => soft_credit_amount}} end end def create_contribution(parsed_row, person) Rails.logger.info("Processing Import [#{id}] DONATION_IMPORT: Creating contribution") params = {} params[:creator_id] = self.user.id params[:person_id] = person.id amount = parsed_row.amount deductible_amount = parsed_row.unparsed_deductible_amount.blank? ? amount - parsed_row.nongift_amount : parsed_row.deductible_amount nongift_amount = parsed_row.unparsed_nongift_amount.blank? ? amount - deductible_amount : parsed_row.nongift_amount occurred_at = parsed_row.donation_date.blank? ? time_zone_parser.now : time_zone_parser.parse(parsed_row.donation_date) params[:subtype] = parsed_row.donation_type params[:amount] = deductible_amount + nongift_amount params[:nongift_amount] = nongift_amount params[:payment_method] = parsed_row.payment_method params[:organization_id] = self.organization.id params[:occurred_at] = occurred_at.to_s params[:details] = "Imported by #{user.email} on #{I18n.l self.created_at_local_to_organization, :format => :date}" params[:creator_id] = user.id params[:notes] = parsed_row.notes params[:ack_sent_date] = parsed_row.ack_sent_date params[:fiscal_year] = parsed_row.fiscal_year campaign = create_campaign(parsed_row, params) create_appeal(parsed_row, campaign, params) create_match_eligible(parsed_row, params) create_soft_credit(parsed_row, params) contribution = Contribution.new(params) contribution.save(ImportedOrder, self.id) contribution end end