Add CiviCRM importer

This commit is contained in:
Hugo Peixoto 2022-09-28 00:18:36 +01:00
parent 9dfdf3675b
commit e22f6e0a00

View File

@ -11,4 +11,116 @@ namespace :saucy do
task notify: :environment do
Notification.send_scheduled_for_today
end
desc "Import data from CiviCRM XML files"
task import: :environment do
require 'nokogiri'
require 'date'
Notification.delete_all
Contribution.delete_all
Member.delete_all
def sql_resultset_to_hashes(resultset_filename)
Nokogiri::XML(File.read(resultset_filename))
.xpath('resultset/row')
.map do |row|
row
.xpath('field')
.map { |field| [field["name"], field.children.size > 0 ? field.text : nil] }
.to_h
end
end
def ensure_one(list)
raise if list.size > 1
list[0]
end
addresses = sql_resultset_to_hashes('civicrm-dump/address.xml').select { |a| a["is_primary"] == "1" }
contacts = sql_resultset_to_hashes('civicrm-dump/contact.xml')
contributions = sql_resultset_to_hashes('civicrm-dump/contribution.xml')
emails = sql_resultset_to_hashes('civicrm-dump/email.xml').select { |a| a["is_primary"] == "1" }
memberships = sql_resultset_to_hashes('civicrm-dump/membership.xml').select { |m| Date.parse(m['end_date']).year >= 2020 }
payment_instruments = sql_resultset_to_hashes('civicrm-dump/payment_instrument.xml')
statuses = sql_resultset_to_hashes('civicrm-dump/status.xml')
types = sql_resultset_to_hashes('civicrm-dump/type.xml')
members = contacts.map do |contact|
contact.merge(
"membership" => memberships.select { |m| m['contact_id'] == contact['id'] }.then { |ms| ensure_one(ms) },
"address" => addresses.select { |a| a['contact_id'] == contact['id'] }.then { |ms| ensure_one(ms) },
"email" => emails.select { |a| a['contact_id'] == contact['id'] }.then { |ms| ensure_one(ms) },
"contributions" => contributions.select { |c| c['contact_id'] == contact['id'] },
)
end
members = members.select { |m| !m['membership'].nil? }
raise "we have duplicates" unless members.map { |m| m['display_name'] }.count == members.map { |m| m['display_name'] }.uniq.count
members.each do |member|
address = member['address']
address = if address
postal_code = [
address['postal_code'],
address['postal_code_suffix']
].reject(&:nil?).reject(&:empty?).join('-')
[
address['street_address'],
address['supplemental_address_1'],
address['supplemental_address_2'],
address['supplemental_address_3'],
"#{postal_code} #{address['city']}",
].reject(&:nil?).reject(&:empty?).join("\n")
else
nil
end
category = case member['membership']['membership_type_id']
when "1" then 'student'
when "2" then 'normal'
when "3" then 'retired'
when "4" then 'unemployed'
else raise "derp membership type"
end
m = Member.new(
number: member['membership']['id'],
email: member['email']['email'],
display_name: member['display_name'],
identification_number: member['legal_identifier'],
status: "", # must be reset
category: category, # membership type id
address: address,
joined_on: member['membership']['join_date'],
expires_on: member['membership']['end_date'],
#t.string "regular_ifthenpay_link"
#t.string "reduced_ifthenpay_link"
excluded: false,
wants_mailing_list: true,
prefers_postal: false,
)
m.save!
m.reset_status!
member['contributions'].each do |contribution|
c = Contribution.new(
member: m,
eurocents: contribution['total_amount'],
payment_on: contribution['receive_date'] || m.joined_on,
payment_method: payment_instruments.find { |i| i["value"] == contribution['payment_instrument_id'] }["name"],
payment_reference: "",
)
c.save!
end
end
end
end