From e22f6e0a00dc493866d6697f103a934b2d541dda Mon Sep 17 00:00:00 2001 From: Hugo Peixoto Date: Wed, 28 Sep 2022 00:18:36 +0100 Subject: [PATCH] Add CiviCRM importer --- lib/tasks/saucy.rake | 112 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/lib/tasks/saucy.rake b/lib/tasks/saucy.rake index 4d4e184..2c734a5 100644 --- a/lib/tasks/saucy.rake +++ b/lib/tasks/saucy.rake @@ -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