sf_migrate 1.0.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/export.rb +22 -15
- data/lib/fields.rb +13 -9
- data/lib/import.rb +685 -269
- data/lib/sf_migrate.rb +14 -12
- metadata +48 -7
data/lib/export.rb
CHANGED
@@ -6,18 +6,18 @@ module SalesforceMigration
|
|
6
6
|
#
|
7
7
|
# @param [Hash] options hash representing passed command line options
|
8
8
|
def initialize(options)
|
9
|
-
credentials
|
10
|
-
consumer_key
|
11
|
-
consumer_secret
|
12
|
-
username
|
13
|
-
password
|
14
|
-
@csv_dir
|
15
|
-
@action
|
9
|
+
credentials = YAML.load_file(options[:config_file])
|
10
|
+
consumer_key = credentials['salesforce_consumer_key']
|
11
|
+
consumer_secret = credentials['salesforce_consumer_secret']
|
12
|
+
username = credentials['salesforce_username']
|
13
|
+
password = credentials['salesforce_password']
|
14
|
+
@csv_dir = options[:csv_dir]
|
15
|
+
@action = options[:action]
|
16
|
+
@last_modified_date = options[:last_modified_date]
|
16
17
|
@logger = SalesforceMigration::Runner::create_logger
|
17
18
|
@logger.info("Export action started")
|
18
19
|
@client = Databasedotcom::Client.new :client_id => consumer_key, :client_secret => consumer_secret
|
19
20
|
@client.authenticate :username => username, :password => password
|
20
|
-
|
21
21
|
@logger.info("Authentication to SalesForce successfull")
|
22
22
|
start
|
23
23
|
@logger.info("Export action ended successfully")
|
@@ -25,7 +25,7 @@ module SalesforceMigration
|
|
25
25
|
|
26
26
|
private
|
27
27
|
def start
|
28
|
-
%w(ISOs__c Agent__c Account Payment_Methods__c Banks__c MerchantToAPM__c ccrmbasic__Email__c Email_Association__c).each do |type|
|
28
|
+
%w(ISOs__c Agent__c Account Acquirer__c Contract Payment_Methods__c Banks__c MerchantToAPM__c ccrmbasic__Email__c Email_Association__c User).each do |type|
|
29
29
|
@logger.info "Writing CSV for #{type}"
|
30
30
|
write_to_csv type
|
31
31
|
end
|
@@ -45,7 +45,7 @@ module SalesforceMigration
|
|
45
45
|
records.each do |record|
|
46
46
|
arr = []
|
47
47
|
fields.each do |field|
|
48
|
-
arr << record.send(field)
|
48
|
+
arr << record.send(field).to_s
|
49
49
|
arr.map!(&method(:remove_quotes))
|
50
50
|
end
|
51
51
|
file << arr
|
@@ -75,14 +75,21 @@ module SalesforceMigration
|
|
75
75
|
# @return [Databasedotcom::Collection] the requested records
|
76
76
|
def get_records(type)
|
77
77
|
if @action == 'initial_run'
|
78
|
-
@logger.info "Getting all records from SalesForce for #{type}"
|
78
|
+
@logger.info "Getting all records from SalesForce for #{type} object"
|
79
79
|
records = get_all_sobjects(type)
|
80
80
|
else
|
81
|
-
@logger.info "Getting records for yesterday from SalesForce for #{type}"
|
81
|
+
@logger.info "Getting records for yesterday from SalesForce for #{type} object"
|
82
82
|
records = @client.materialize(type)
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
|
84
|
+
begin
|
85
|
+
datetime = DateTime.parse(@last_modified_date)
|
86
|
+
rescue
|
87
|
+
if defined? @last_modified_date == nil
|
88
|
+
datetime = DateTime.now
|
89
|
+
else
|
90
|
+
raise ArgumentError, "Invalid Date", caller
|
91
|
+
end
|
92
|
+
end
|
86
93
|
records.query("lastmodifieddate >= #{datetime}")
|
87
94
|
end
|
88
95
|
end
|
data/lib/fields.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
module SalesforceMigration
|
2
2
|
class Fields
|
3
3
|
# Salesforce objects and the fields for import
|
4
|
-
ISOS_FIELDS
|
5
|
-
AGENT_FIELDS
|
6
|
-
ACCOUNT_FIELDS
|
7
|
-
PAYMENT_METHODS_FIELDS
|
8
|
-
BANKS_FIELDS
|
9
|
-
MERCHANTTOAPM_FIELDS
|
10
|
-
CCRMBASIC__EMAIL_FIELDS
|
11
|
-
EMAIL_ASSOCIATION_FIELDS= %w{Merchant_Name__c Email__c}
|
12
|
-
|
4
|
+
ISOS_FIELDS = %w{Active__c Address__c Adult_Chargeback_Fee__c Adult_Commission__c Adult_Transaction_Fee__c Agreement_Received__c Background_Check_Complete__c Business_Phone_Number__c Cell_Phone_Number__c Comments__c CreatedBy CreatedById CreatedDate Curren__c CurrencyIsoCode Email_Address__c Fax_Number__c Gambling_Chargeback_Fee__c Gambling_Commission_Fee__c Gambling_Transaction_Fee__c General_Conventional_Chargeback_Fee__c General_Conventional_Commission_Fee__c General_Conventional_Transaction_Fee__c General_Non_Conventional_Chargeback_Fee__c General_Non_Conventional_Commission_Fee__c General_Non_Conventional_Transaction_Fee__c ISO_ID_Assigned__c ISO_ID_Number__c ISO_Owner_Name__c Id IsDeleted KYC_Gathered__c LastActivityDate LastModifiedBy LastModifiedById LastModifiedDate Name New_Hire_Package_Received__c Owner OwnerId Pharmacy_Chargeback_Fee__c Pharmacy_Commission_Fee__c Pharmacy_Transaction_Fee__c Projected_Deals_Count__c Recruiter__c Region__c System_Access_Granted__c Training_Completed__c Welcome_Call_Completed__c Welcome_Package_Sent__c eMerchantPay_ISO_ID__c}
|
5
|
+
AGENT_FIELDS = %w{Id IsDeleted Name LastActivityDate CreatedBy CreatedDate CreatedById LastModifiedDate LastModifiedById LastModifiedBy Owner OwnerId Agent_Billing_Address__c Agent_Cell_Phone__c Agent_Id__c Agent_Phone__c Agent_Skype__c Agreement_Received__c Agreement_Sent__c Background_Check_Complete__c Business_Phone_Number__c Comments__c Commission_Fee__c Email_Address__c eMerchantPay_Agent_ID__c Fee_Comments__c ISO_Company__c New_Hire_Package_Received__c One_Time_Commission_Currency__c Recruiter__c Region__c Split_percentage__c System_Access_Granted__c Title__c Transaction_Fee__c}
|
6
|
+
ACCOUNT_FIELDS = %w{Additional_Url__c Agents__c AnnualRevenue Approval_Citeria__c Approve_1__c Approve_2__c Approve_3__c BillingCity BillingCountry BillingPostalCode BillingState BillingStreet City__c Comment__c CreatedBy CreatedById CreatedDate Credit_Card__c CurrencyIsoCode Current_Volume__c Description Descriptor__c FD_Merchant_Number__c Fax ISO_Name__c Id IsDeleted Industry Info_Capture__c Integration__c Integrator__c Integrator_2__c Iovation__c IPSP__c IPSP_Name2__c IsPartner Jigsaw LastModifiedBy LastModifiedById LastModifiedDate Merchant_Email__c Merchant_Type__c Name NumberOfEmployees Overlying_Company__c Owner OwnerId Phone Projected_Monthly_Volume__c Recruiter__c Risk_Analyst__c Secondary_FD_Merchant_Number__c ShippingCity ShippingCountry ShippingPostalCode ShippingState ShippingStreet Status_Comments__c Status__c Threat_Metrix__c Type__c Url__c VBV_MC3D__c Vacation1__c Website} # OwnerName OwnerPhone OwnerEmail}
|
7
|
+
PAYMENT_METHODS_FIELDS = %w{Accounts__c Business_Contact__c Business_Type_Coments__c Business_type__c Buy_Rates__c Chargeback_Comments__c Chargeback__c Client_Integration__c Countries2__c Countries__c CreatedBy CreatedById CreatedDate CurrencyIsoCode Id IsDeleted Integration__c LastModifiedBy LastModifiedById LastModifiedDate Name Our_Buy_Rates__c Owner OwnerId Proccessing_Currency__c Processing_Currency__c Rebilling_Comments__c Rebilling__c Refund_Comments__c Refund__c Release_Date__c Settlement_Currency__c Settlement_Cycle__c Settlement__c Tech_Contact__c Type__c V_terminal_Comments__c V_terminal__c}
|
8
|
+
BANKS_FIELDS = %w{Account_Number__c BIC_Code__c Merchant_2__c Bank_Address__c Bank_Name__c Contract__c CreatedBy CreatedById CreatedDate CurrencyIsoCode Holder_Address__c IBAN__c Id IsDeleted LastActivityDate LastModifiedBy LastModifiedById LastModifiedDate Name Owner OwnerId Processing_Currency__c Routing_Number__c SWIFT__c Settlement_Currency__c}
|
9
|
+
MERCHANTTOAPM_FIELDS = %w{Merchant__c Payment_Methods__c}
|
10
|
+
CCRMBASIC__EMAIL_FIELDS = %w{Actual_Subject__c Agent__c ccrmbasic__Account__c ccrmbasic__Body__c ccrmbasic__Cc__c ccrmbasic__Direction__c ccrmbasic__From__c ccrmbasic__Internal_Contact__c ccrmbasic__To__c Id IsDeleted Name}
|
11
|
+
EMAIL_ASSOCIATION_FIELDS = %w{Merchant_Name__c Email__c}
|
12
|
+
CONTRACT_FIELDS = %w{Id IsDeleted AccountId CurrencyIsoCode StartDate EndDate BillingStreet BillingCity BillingState BillingPostalCode BillingCountry ContractTerm OwnerId Status StatusCode ContractNumber CreatedDate CreatedById LastModifiedDate LastModifiedById SystemModstamp LastActivityDate Commission_Fee__c Transaction_Fee_Approved__c Transaction_Fee_Declined__c Charge_Back_Fee__c Rolling_Reserve__c Rolling_Reserve_Period__c VBV_Fee__c Wiring_Fee__c PCI_Compliance_Test_Fee__c Billing_Period_Duration_Weekly__c Discover__c Delay_in_Payment_Weeks__c Amex__c Guaranty__c Amount_Number__c Currency__c Treasury_Executive__c Acquirer__c Proccessing_Start_Date__c Proccessing_End_Date__c Acquirer_Approval_Timeframe__c Url__c Date_of_Submission_to_the_Acquirer__c Date_of_Approval__c Refund_Fee__c Registration_Fee__c Integrator_1__c Integrator_2__c Descriptor__c City_Field__c Acquirer_Rejection_Timeframe__c Date_of_Rejection__c Date_of_Issuing_the_MID__c Date_of_Terminal_Setup__c Date_of_Activation__c Deactivation_Date__c Comments__c Threat_Matrix__c Iovation__c Info_Capture__c VBV_MC3D__c PCI_Compliance__c Website_Compliance__c Reason_of_Deactivation__c VISA__c MC__c JCB__c UATP__c Integration_Type__c Payment_Status__c Payment_Suspension_Reason__c IPSP_name__c Visa_MCC_Code__c MC_MCC_Code__c Rejection_Reason__c Type_Of_Agreement__c}
|
13
|
+
ACQUIRER_FIELDS = %w{Id IsDeleted OwnerId Owner Name CurrencyIsoCode CreatedDate CreatedById CreatedBy LastModifiedDate LastModifiedById LastModifiedBy SystemModstamp LastActivityDate Acquirer_Address__c Acquirer_Country__c SPLIT__c Chargeback_Fee__c One_time_Setup_Fee__c Swift_Wire_Transfer_Fee__c Card_Type__c Card_Scheme__c Currency__c Risk_Level__c Transaction__c Fees_Approved__c Fees_Declined__c Fees_other__c Flat_Commision_Fee__c EUR_Interchange__c Non_EUR_Interchange__c }
|
14
|
+
SYSTEM_FIELDS = %w{id acquirer ownerid createddate createdbyid integrator integrator_1 integrator_2 ipsp iso lastactivitydate lastmodifieddate lastmodifiedbyid systemmodstamp recruiter region risk_analyst}
|
15
|
+
SYSTEM_READABLE_FIELDS = %w{id acquirer_id owner_id created_date created_by_id integrator_id integrator_id integrator_2_id ipsp_id iso_id last_activity_date last_modified_date last_modified_by_id system_modstamp recruiter_id region_id risk_analyst_id}
|
16
|
+
USER_FIELDS = %w{Id FirstName LastName Phone Email}
|
13
17
|
end
|
14
18
|
end
|
data/lib/import.rb
CHANGED
@@ -7,7 +7,7 @@ module SalesforceMigration
|
|
7
7
|
# -> transform_agents
|
8
8
|
# -> populate_sugar -> get_sugarcrm_module_type
|
9
9
|
# -> convert_string_to_datetime
|
10
|
-
# ->
|
10
|
+
# -> create_associations -> find_sugarcrm_object
|
11
11
|
# -> create_user
|
12
12
|
class Import
|
13
13
|
|
@@ -23,11 +23,11 @@ module SalesforceMigration
|
|
23
23
|
SugarCRM.connect(url, username, password)
|
24
24
|
@action = options[:action]
|
25
25
|
@isos, @agents, @merchants, @bank_accounts, @agent_users, @iso_users, @emails = [], [], [], [], [], [], []
|
26
|
-
@payment_to_merchants, @emails_to_merchants = [], []
|
26
|
+
@payment_to_merchants, @emails_to_merchants, @acquirers, @contracts, @users = [], [], [], [], []
|
27
27
|
@logger = SalesforceMigration::Runner::create_logger
|
28
|
-
@logger.info("Import action started")
|
28
|
+
@logger.info("Import action started!")
|
29
29
|
start
|
30
|
-
@logger.info("Import action
|
30
|
+
@logger.info("Import action completed!")
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
@@ -35,11 +35,14 @@ module SalesforceMigration
|
|
35
35
|
def start
|
36
36
|
import_emails
|
37
37
|
import_payment_methods
|
38
|
+
import_settlement_bank_accounts
|
39
|
+
import_acquirers
|
40
|
+
import_contracts
|
41
|
+
import_users
|
38
42
|
import_isos
|
39
43
|
import_agents
|
40
44
|
import_merchants
|
41
|
-
|
42
|
-
|
45
|
+
|
43
46
|
associate_records_to_groups
|
44
47
|
end
|
45
48
|
|
@@ -47,66 +50,93 @@ module SalesforceMigration
|
|
47
50
|
# get rid of unnecessary information, transforms other fields, so
|
48
51
|
# they can match the one in SugarCRM and calls for the populate_sugar method
|
49
52
|
# which start the actual import. Keep in mind, that the order of the imports is important
|
53
|
+
|
54
|
+
def import_emails
|
55
|
+
records = load_file_for_import 'ccrmbasic__Email__c'
|
56
|
+
transform_emails! records
|
57
|
+
populate_sugar(records, "email")
|
58
|
+
load_email_to_merchant_associations
|
59
|
+
end
|
60
|
+
|
61
|
+
def load_email_to_merchant_associations
|
62
|
+
# Use the Email_Association CSV relation (Merchant.SalesForceId - Payment_Method.SalesForceId)
|
63
|
+
records = load_file_for_import 'Email_Association__c'
|
64
|
+
transform_email_to_merchants! records
|
65
|
+
@emails_to_merchants = records
|
66
|
+
end
|
67
|
+
|
68
|
+
def import_payment_methods
|
69
|
+
records = load_file_for_import 'Payment_Methods__c'
|
70
|
+
transform_payment_methods! records
|
71
|
+
populate_sugar(records, "payment_method")
|
72
|
+
load_payment_methods_to_merchant_associations
|
73
|
+
end
|
74
|
+
|
75
|
+
def load_payment_methods_to_merchant_associations
|
76
|
+
# Use the MerchantToAPM CSV relation (Merchant.SalesForceId - Payment_Method.SalesForceId)
|
77
|
+
records = load_file_for_import 'MerchantToAPM__c'
|
78
|
+
transform_apm_to_merchants! records
|
79
|
+
@payment_to_merchants = records
|
80
|
+
end
|
81
|
+
|
82
|
+
def import_settlement_bank_accounts
|
83
|
+
records = load_file_for_import 'Banks__c'
|
84
|
+
transform_settlement_bank_accounts! records
|
85
|
+
populate_sugar(records, "settlement_bank_account")
|
86
|
+
end
|
87
|
+
|
88
|
+
def import_acquirers
|
89
|
+
records = load_file_for_import 'Acquirer__c'
|
90
|
+
transform_acquirers! records
|
91
|
+
populate_sugar(records, "acquirer")
|
92
|
+
end
|
93
|
+
|
94
|
+
def import_contracts
|
95
|
+
records = load_file_for_import 'Contract'
|
96
|
+
transform_contracts! records
|
97
|
+
populate_sugar(records, "contract")
|
98
|
+
end
|
99
|
+
|
100
|
+
def import_users
|
101
|
+
records = load_file_for_import 'User'
|
102
|
+
transform_users! records
|
103
|
+
populate_sugar(records, "user")
|
104
|
+
end
|
105
|
+
|
50
106
|
def import_isos
|
51
107
|
records = load_file_for_import 'ISOs__c'
|
52
|
-
|
108
|
+
transform_isos! records
|
53
109
|
populate_sugar(records, "iso")
|
54
110
|
end
|
55
111
|
|
56
112
|
def import_agents
|
57
113
|
records = load_file_for_import 'Agent__c'
|
58
|
-
|
114
|
+
transform_agents! records
|
59
115
|
populate_sugar(records, "agent")
|
60
116
|
end
|
61
117
|
|
62
118
|
def import_merchants
|
63
119
|
records = load_file_for_import 'Account'
|
64
|
-
|
120
|
+
transform_merchants! records
|
65
121
|
populate_sugar(records, "merchant")
|
66
122
|
end
|
67
123
|
|
68
|
-
def import_settlement_bank_accounts
|
69
|
-
records = load_file_for_import 'Banks__c'
|
70
|
-
records = transform_settlement_bank_accounts(records)
|
71
|
-
populate_sugar(records, "settlement_bank_account")
|
72
|
-
end
|
73
|
-
|
74
|
-
def import_payment_methods
|
75
|
-
records = load_file_for_import 'Payment_Methods__c'
|
76
|
-
junction_records = load_file_for_import 'MerchantToAPM__c'
|
77
|
-
# We don`t need db table to save the many-to-many associations between Merchant and Payment Method,
|
78
|
-
# so we just store them in an array and use it later on
|
79
|
-
junction_records.each do |jrecord|
|
80
|
-
@payment_to_merchants << jrecord
|
81
|
-
end
|
82
|
-
populate_sugar(records, "payment_method")
|
83
|
-
end
|
84
|
-
|
85
|
-
def import_emails
|
86
|
-
records = load_file_for_import 'ccrmbasic__Email__c'
|
87
|
-
records = transform_emails(records)
|
88
|
-
junction_records = load_file_for_import 'Email_Association__c'
|
89
|
-
# We don`t need db table to save the many-to-many associations between Merchant and Payment Method,
|
90
|
-
# so we just store them in an array and use it later on
|
91
|
-
junction_records.each do |jrecord|
|
92
|
-
@emails_to_merchants << jrecord
|
93
|
-
end
|
94
|
-
populate_sugar(records, "email")
|
95
|
-
end
|
96
|
-
|
97
124
|
# Load CSV for import
|
98
125
|
#
|
99
126
|
# @param [String] module_name name of the module
|
100
127
|
#
|
101
128
|
# @return [Array] parsed CSV file
|
102
129
|
def load_file_for_import(module_name)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
130
|
+
|
131
|
+
case @action
|
132
|
+
when "initial_run"
|
133
|
+
filename = "#{@csv_dir}/initial/#{module_name}_export.csv"
|
134
|
+
when "update"
|
135
|
+
today = lambda { Date.today.to_s }
|
136
|
+
dir = "#{@csv_dir}/update/#{today.call}"
|
137
|
+
filename = "#{dir}/#{module_name}_export.csv"
|
109
138
|
end
|
139
|
+
|
110
140
|
@logger.error("Could not create or find a csv filename for module #{module_name}") unless defined? filename
|
111
141
|
@logger.info("Loading CSV file #{filename} for import")
|
112
142
|
csv_file = ::CSV.read(filename, :encoding => 'utf-8')
|
@@ -137,23 +167,165 @@ module SalesforceMigration
|
|
137
167
|
header.end_with?("__c") ? header.slice(0..-4).downcase : header.downcase
|
138
168
|
end
|
139
169
|
|
140
|
-
# Add sf_ prefix to all
|
170
|
+
# Add sf_ prefix to all SalesForce-related fields and rename them (if applicable)
|
141
171
|
#
|
142
|
-
# @param [Array<SugarCRM::Namespace::Object>] records records to be prefixed
|
172
|
+
# @param [Array<SugarCRM::Namespace::Object>] records - records to be prefixed
|
143
173
|
#
|
144
|
-
# @return [Array<SugarCRM::Namespace::Object>]
|
174
|
+
# @return [Array<SugarCRM::Namespace::Object>] records
|
145
175
|
def prefix_sf_attribute_names(records)
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
176
|
+
field_names_default = SalesforceMigration::Fields::SYSTEM_FIELDS
|
177
|
+
field_names_readable = SalesforceMigration::Fields::SYSTEM_READABLE_FIELDS
|
178
|
+
|
179
|
+
records.each do |record|
|
180
|
+
field_names_default.each_with_index do |field, index|
|
181
|
+
if record.key?(field)
|
182
|
+
record["sf_#{field_names_readable[index].downcase}"] = record[field]
|
183
|
+
record.delete(field)
|
184
|
+
end
|
151
185
|
end
|
186
|
+
# Set the "deleted" flag according to SugarCRM's default fields
|
187
|
+
record['deleted'] = record['isdeleted'] unless record['isdeleted'].nil?
|
152
188
|
end
|
153
189
|
records
|
154
190
|
end
|
155
191
|
|
156
|
-
|
192
|
+
|
193
|
+
def transform_emails!(records)
|
194
|
+
@logger.info("Transforming Email fields")
|
195
|
+
records.each do |record|
|
196
|
+
record['sf_agent_id'] = record['agent']
|
197
|
+
record['sf_merchant_id'] = record['ccrmbasic__account']
|
198
|
+
record['direction'] = record['ccrmbasic__direction']
|
199
|
+
record['sender'] = record['ccrmbasic__from']
|
200
|
+
record['internal_contact'] = record['ccrmbasic__internal_contact']
|
201
|
+
record['receiver'] = record['ccrmbasic__to']
|
202
|
+
record['cc'] = record['ccrmbasic__cc']
|
203
|
+
record['name'] = record['actual_subject'] unless record['actual_subject'].blank?
|
204
|
+
record['body'] = convert_characters(record['ccrmbasic__body']) unless record['ccrmbasic__body'].nil?
|
205
|
+
|
206
|
+
record.delete 'agent'
|
207
|
+
record.delete 'ccrmbasic__to'
|
208
|
+
record.delete 'ccrmbasic__cc'
|
209
|
+
record.delete 'actual_subject'
|
210
|
+
record.delete 'ccrmbasic__body'
|
211
|
+
record.delete 'ccrmbasic__from'
|
212
|
+
record.delete 'ccrmbasic__account'
|
213
|
+
record.delete 'ccrmbasic__direction'
|
214
|
+
record.delete 'ccrmbasic__internal_contact'
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def transform_payment_methods!(records)
|
219
|
+
@logger.info("Transforming Payment Method's fields")
|
220
|
+
records.each do |record|
|
221
|
+
record['business_type_comments'] = record['business_type_coments']
|
222
|
+
|
223
|
+
record.delete 'business_type_coments'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
def transform_settlement_bank_accounts!(records)
|
229
|
+
@logger.info("Transforming Settlement Bank Account fields")
|
230
|
+
records.each do |record|
|
231
|
+
record['sf_contract_id'] = record['contract']
|
232
|
+
record['sf_merchant_id'] = record['merchant_2']
|
233
|
+
|
234
|
+
record.delete 'merchant_2'
|
235
|
+
record.delete 'contract'
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def transform_acquirers!(records)
|
240
|
+
@logger.info("Transforming Acquirer fields")
|
241
|
+
records.each do |record|
|
242
|
+
record['currency_iso_code'] = record['currencyisocode']
|
243
|
+
record['fees_transaction'] = record['transaction']
|
244
|
+
|
245
|
+
record.delete 'currencyisocode'
|
246
|
+
record.delete 'transaction'
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def transform_contracts!(records)
|
251
|
+
@logger.info("Transforming Contract fields")
|
252
|
+
records.each do |record|
|
253
|
+
record['name'] = record['contractnumber']
|
254
|
+
record['sf_account_id'] = record['accountid']
|
255
|
+
record['currency_iso_code'] = record['currencyisocode']
|
256
|
+
record['start_date'] = record['startdate']
|
257
|
+
record['end_date'] = record['enddate']
|
258
|
+
record['billing_street'] = record['billingstreet']
|
259
|
+
record['billing_city'] = record['billingcity']
|
260
|
+
record['billing_state'] = record['billingstate']
|
261
|
+
record['billing_postal_code'] = record['billingpostalcode']
|
262
|
+
record['billing_country'] = record['billingcountry']
|
263
|
+
record['contract_term'] = record['contractterm']
|
264
|
+
record['status_code'] = record['statuscode']
|
265
|
+
record['contract_number'] = record['contractnumber']
|
266
|
+
record['guarantee'] = record['guaranty']
|
267
|
+
record['guaranteed_amount'] = record['amount_number']
|
268
|
+
record['treasury_executive_sf_id'] = record['treasury_executive']
|
269
|
+
record['processing_start_date'] = record['proccessing_start_date']
|
270
|
+
record['processing_end_date'] = record['proccessing_end_date']
|
271
|
+
record['date_of_submission_to_acqirer'] = record['date_of_submission_to_the_acquirer']
|
272
|
+
record['chargeback_fee'] = record['charge_back_fee']
|
273
|
+
record['billing_period_duration'] = record['billing_period_duration_weekly']
|
274
|
+
record['payment_delay'] = record['delay_in_payment_weeks']
|
275
|
+
record['integrator1_sf_id'] = record['integrator_1']
|
276
|
+
record['integrator2_sf_id'] = record['integrator_2']
|
277
|
+
record['date_of_issuing_mid'] = record['date_of_issuing_the_mid']
|
278
|
+
record['date_of_deactivation'] = record['deactivation_date']
|
279
|
+
record['threatmetrix'] = record['threat_matrix']
|
280
|
+
record['deactivation_reason'] = record['reason_of_deactivation']
|
281
|
+
record['mastercard'] = record['mc']
|
282
|
+
record['ipsp_name_sf_id'] = record['ipsp_name']
|
283
|
+
record['mastercard_mcc_code'] = record['mc_mcc_code']
|
284
|
+
|
285
|
+
record.delete 'contractnumber'
|
286
|
+
record.delete 'accountid'
|
287
|
+
record.delete 'currencyisocode'
|
288
|
+
record.delete 'startdate'
|
289
|
+
record.delete 'enddate'
|
290
|
+
record.delete 'billingstreet'
|
291
|
+
record.delete 'billingcity'
|
292
|
+
record.delete 'billingstate'
|
293
|
+
record.delete 'billingpostalcode'
|
294
|
+
record.delete 'billingcountry'
|
295
|
+
record.delete 'contractterm'
|
296
|
+
record.delete 'statuscode'
|
297
|
+
record.delete 'guaranty'
|
298
|
+
record.delete 'amount_number'
|
299
|
+
record.delete 'treasury_executive'
|
300
|
+
record.delete 'proccessing_start_date'
|
301
|
+
record.delete 'proccessing_end_date'
|
302
|
+
record.delete 'date_of_submission_to_the_acquirer'
|
303
|
+
record.delete 'charge_back_fee'
|
304
|
+
record.delete 'billing_period_duration_weekly'
|
305
|
+
record.delete 'delay_in_payment_weeks'
|
306
|
+
record.delete 'integrator_1'
|
307
|
+
record.delete 'integrator_2'
|
308
|
+
record.delete 'date_of_issuing_the_mid'
|
309
|
+
record.delete 'deactivation_date'
|
310
|
+
record.delete 'threat_matrix'
|
311
|
+
record.delete 'reason_of_deactivation'
|
312
|
+
record.delete 'mc'
|
313
|
+
record.delete 'ipsp_name'
|
314
|
+
record.delete 'mc_mcc_code'
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def transform_users!(records)
|
319
|
+
@logger.info("Transforming User fields")
|
320
|
+
records.each do |record|
|
321
|
+
record['name'] = "#{record['firstname']} #{record['lastname']}"
|
322
|
+
|
323
|
+
record.delete 'firstname'
|
324
|
+
record.delete 'lastname'
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def transform_isos!(records)
|
157
329
|
@logger.info("Transforming ISO fields")
|
158
330
|
records.each do |record|
|
159
331
|
record['general_c_chargeback_fee'] = record['general_conventional_chargeback_fee']
|
@@ -162,6 +334,7 @@ module SalesforceMigration
|
|
162
334
|
record['general_nc_chargeback_fee'] = record['general_non_conventional_chargeback_fee']
|
163
335
|
record['general_nc_commission_fee'] = record['general_non_conventional_commission_fee']
|
164
336
|
record['general_nc_transaction_fee'] = record['general_non_conventional_transaction_fee']
|
337
|
+
|
165
338
|
record.delete 'general_conventional_chargeback_fee'
|
166
339
|
record.delete 'general_conventional_commission_fee'
|
167
340
|
record.delete 'general_conventional_transaction_fee'
|
@@ -169,80 +342,152 @@ module SalesforceMigration
|
|
169
342
|
record.delete 'general_non_conventional_commission_fee'
|
170
343
|
record.delete 'general_non_conventional_transaction_fee'
|
171
344
|
end
|
172
|
-
records
|
173
345
|
end
|
174
346
|
|
175
|
-
def transform_agents(records)
|
176
|
-
@logger.info("Transforming fields")
|
347
|
+
def transform_agents!(records)
|
348
|
+
@logger.info("Transforming Agent fields")
|
177
349
|
records.each do |record|
|
178
|
-
record['
|
350
|
+
record['sf_iso_id'] = record['iso_company']
|
351
|
+
|
179
352
|
record.delete 'iso_company'
|
180
353
|
end
|
181
|
-
records
|
182
354
|
end
|
183
355
|
|
184
|
-
def transform_merchants(records)
|
356
|
+
def transform_merchants!(records)
|
185
357
|
@logger.info("Transforming Merchant fields")
|
186
358
|
records.each do |record|
|
187
|
-
record['
|
188
|
-
record['
|
189
|
-
record['
|
359
|
+
record['sf_agent_id'] = record['agents']
|
360
|
+
record['ipsp_name'] = record['ipsp_name2']
|
361
|
+
record['url'] = record['url'].to_s.gsub(/<[^>]*>|^[\n\r]*/, '')
|
362
|
+
record['additional_url'] = record['additional_url'].to_s.gsub(/(<[^>]*>|^[\n\r]*)/, '')
|
363
|
+
|
190
364
|
record.delete 'agents'
|
191
|
-
record.delete 'sf_lastactivitydate'
|
192
|
-
record.delete 'sf_lastmodifieddate'
|
193
365
|
record.delete 'sf_region'
|
366
|
+
record.delete 'ipsp_name2'
|
194
367
|
end
|
195
|
-
records
|
196
368
|
end
|
197
369
|
|
198
|
-
def
|
199
|
-
@logger.info("Transforming
|
370
|
+
def transform_email_to_merchants!(records)
|
371
|
+
@logger.info("Transforming Emails to Merchant fields");
|
200
372
|
records.each do |record|
|
201
|
-
record['
|
202
|
-
record['
|
203
|
-
|
204
|
-
record.delete '
|
205
|
-
record.delete '
|
206
|
-
record.delete 'contract'
|
207
|
-
record.delete 'sf_recruiter'
|
208
|
-
record.delete 'sf_region'
|
373
|
+
record['sf_id'] = record['email']
|
374
|
+
record['sf_merchant_id'] = record['merchant_name']
|
375
|
+
|
376
|
+
record.delete 'email'
|
377
|
+
record.delete 'merchant_name'
|
209
378
|
end
|
210
|
-
records
|
211
379
|
end
|
212
|
-
|
213
|
-
def
|
214
|
-
@logger.info("Transforming
|
380
|
+
|
381
|
+
def transform_apm_to_merchants!(records)
|
382
|
+
@logger.info("Transforming APM to Merchant fields");
|
215
383
|
records.each do |record|
|
216
|
-
record['
|
217
|
-
record['
|
218
|
-
|
219
|
-
|
220
|
-
record.delete '
|
221
|
-
record.delete 'ccrmbasic__cc'
|
222
|
-
record.delete 'ccrmbasic__body'
|
384
|
+
record['sf_id'] = record['payment_methods']
|
385
|
+
record['sf_merchant_id'] = record['merchant']
|
386
|
+
|
387
|
+
record.delete 'payment_methods'
|
388
|
+
record.delete 'merchant'
|
223
389
|
end
|
224
|
-
records
|
225
390
|
end
|
226
391
|
|
227
|
-
#
|
392
|
+
# Correct/Sanitize field types in a record (Boolean, Date/DateTime, nil)
|
393
|
+
#
|
394
|
+
# @param [SugarCRM::Namespace::Object] record - the record we want to process
|
395
|
+
#
|
396
|
+
# @return [SugarCRM::Namespace::Object] record
|
397
|
+
def correct_field_types!(record)
|
398
|
+
strip_empty_arrays!(record)
|
399
|
+
|
400
|
+
replace_invalid_ids!(record)
|
401
|
+
|
402
|
+
convert_string_to_boolean!(record)
|
403
|
+
|
404
|
+
convert_string_to_datetime!(record)
|
405
|
+
|
406
|
+
strip_nil_to_empty_string!(record)
|
407
|
+
end
|
408
|
+
|
409
|
+
|
410
|
+
# Convert all fields with date/modstamp in their names to DateTime objects
|
228
411
|
#
|
229
|
-
# @param [SugarCRM::Namespace::Object] record the record
|
412
|
+
# @param [SugarCRM::Namespace::Object] record - the record, where we look for date/stamp values and make them DB-Compatible
|
230
413
|
#
|
231
|
-
# @return [SugarCRM::Namespace::Object]
|
232
|
-
def convert_string_to_datetime(record)
|
233
|
-
record
|
234
|
-
|
235
|
-
|
236
|
-
|
414
|
+
# @return [SugarCRM::Namespace::Object] record
|
415
|
+
def convert_string_to_datetime!(record)
|
416
|
+
record.each do |field_name, field_value|
|
417
|
+
if field_name =~ /(.*)date(.*)|modstamp/
|
418
|
+
record[field_name] = DateTime.parse(field_value).to_s(:db) rescue nil
|
419
|
+
end
|
420
|
+
end
|
237
421
|
end
|
238
|
-
|
422
|
+
|
423
|
+
# Convert all string fields to Boolean objects
|
424
|
+
#
|
425
|
+
# @param [SugarCRM::Namespace::Object] record - the record, where we look for boolean variables in string format
|
426
|
+
#
|
427
|
+
# @return [SugarCRM::Namespace::Object] record
|
428
|
+
def convert_string_to_boolean!(record)
|
429
|
+
record.each do |field_name, field_value|
|
430
|
+
case field_value
|
431
|
+
when /\Atrue\Z/i;
|
432
|
+
record[field_name] = true
|
433
|
+
when /\Afalse\Z/i;
|
434
|
+
record[field_name] = false
|
435
|
+
when /\Anil\Z/i, /\ANULL\Z/;
|
436
|
+
record[field_name] = nil
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
# Replace all empty arrays with empty strings
|
442
|
+
#
|
443
|
+
# @param [SugarCRM::Namespace::Object] record - the record, where we look for empty arrays
|
444
|
+
#
|
445
|
+
# @return [SugarCRM::Namespace::Object] record
|
446
|
+
def strip_empty_arrays!(record)
|
447
|
+
record.each do |field_name, field_value|
|
448
|
+
if field_value == "[]"
|
449
|
+
record[field_name] = ""
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
# nil (null) Values are not properly handled by SugarCRM, thus convert them to empty strings
|
455
|
+
#
|
456
|
+
# @param [SugarCRM::Namespace::Object] record - the record, where we look for empty arrays
|
457
|
+
#
|
458
|
+
# @return [SugarCRM::Namespace::Object] record
|
459
|
+
def strip_nil_to_empty_string!(record)
|
460
|
+
record.each do |field_name, field_value|
|
461
|
+
record[field_name] = "" if record[field_name].nil?
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
# Sometimes a record, may have an invalid id or a new owner, but the change might not be reflected in SalesForce thus we need to change it manually
|
466
|
+
#
|
467
|
+
# @param [SugarCRM::Namespace::Object] record - the record, where we look for empty arrays
|
468
|
+
#
|
469
|
+
# @return [SugarCRM::Namespace::Object] record
|
470
|
+
def replace_invalid_ids!(record)
|
471
|
+
valid_ids = %w{005300000057piVAAQ}
|
472
|
+
invalid_ids = %w{0053000000567TbAAI}
|
473
|
+
|
474
|
+
record.each do |field_name, field_value|
|
475
|
+
invalid_ids.each_with_index { |invalid_id, index| record[field_name] = valid_ids[index] if compare_salesforce_ids(record[field_value], invalid_id) }
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
# SQL escape string
|
480
|
+
#
|
481
|
+
# @param String string
|
482
|
+
#
|
483
|
+
# @return String string
|
239
484
|
def convert_characters(string)
|
240
485
|
string.gsub!(/\'/, ''')
|
241
486
|
string.gsub!(/'/, '')
|
242
487
|
string.gsub!(/"/, '')
|
243
488
|
string.gsub!(/\"/, '"')
|
244
489
|
string
|
245
|
-
|
490
|
+
end
|
246
491
|
|
247
492
|
# Populate SugarCRM with records
|
248
493
|
# If it's initial run, it will create all records from the CSV file
|
@@ -252,40 +497,46 @@ module SalesforceMigration
|
|
252
497
|
# @param [String] type type of the object
|
253
498
|
def populate_sugar(records, type)
|
254
499
|
module_type = get_sugarcrm_module_type(type)
|
500
|
+
|
255
501
|
case @action
|
256
|
-
|
257
|
-
|
502
|
+
when 'initial_run'
|
503
|
+
@logger.info("Creating new records for #{type} type")
|
504
|
+
records.each do |record|
|
505
|
+
create_sugar_record(module_type, record, type)
|
506
|
+
end
|
507
|
+
when 'update'
|
258
508
|
records.each do |record|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
record
|
509
|
+
correct_field_types! record
|
510
|
+
|
511
|
+
existing_record = find_sugarcrm_object(type, 'sf_id', record['sf_id'])
|
512
|
+
|
513
|
+
if existing_record
|
514
|
+
if existing_record.is_a?(Array)
|
515
|
+
@logger.error("More than one record for #{type} #{record['name']} - SalesForce Id (#{record['sf_id']}")
|
516
|
+
existing_record = existing_record.first
|
517
|
+
end
|
518
|
+
|
519
|
+
@logger.info("Updating record for #{type} #{record['name']}")
|
520
|
+
existing_record.update_attributes!(record)
|
521
|
+
else
|
522
|
+
@logger.info("Creating new record for #{type} #{record['name']}")
|
523
|
+
create_sugar_record(module_type, record, type)
|
271
524
|
end
|
272
|
-
@logger.info("Updating record for #{type} #{record['name']}")
|
273
|
-
existing_record.update_attributes!(record)
|
274
|
-
else
|
275
|
-
@logger.info("Creating new record for #{type} #{record['name']}")
|
276
|
-
create_sugar_record(module_type, record, type)
|
277
525
|
end
|
278
|
-
end
|
279
526
|
end
|
280
527
|
end
|
281
528
|
|
282
529
|
# Create the actual records and users in SugarCRM. Populates the var_pool
|
530
|
+
#
|
531
|
+
# @param module_type
|
532
|
+
# @param record [SugarCRM::Namespace::Object]
|
533
|
+
# @param type
|
283
534
|
def create_sugar_record(module_type, record, type)
|
284
|
-
|
535
|
+
correct_field_types!(record)
|
285
536
|
|
286
537
|
obj = module_type.new(record)
|
287
538
|
obj.save!
|
288
|
-
obj =
|
539
|
+
obj = create_associations(obj, type) unless %(email payment_method).include? type
|
289
540
|
create_security_group_iso obj if type == 'iso'
|
290
541
|
|
291
542
|
create_user(obj, type) if %(iso agent).include? type
|
@@ -295,21 +546,28 @@ module SalesforceMigration
|
|
295
546
|
# Populates variables with SugarCRM objects.
|
296
547
|
# We use them later on, when associating objects with Security Groups
|
297
548
|
# Actually we don`t use @bank_accounts & @emails for now, but it`s probably a good idea to store the objects
|
298
|
-
#
|
299
|
-
# @param [
|
549
|
+
#
|
550
|
+
# @param [SugarCRM::Namespace::Object] obj - object for which a user will be created
|
551
|
+
# @param [String] type - type of the object
|
300
552
|
def populate_var_pool(obj, type)
|
301
553
|
case type
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
554
|
+
when 'email'
|
555
|
+
@emails << obj
|
556
|
+
when 'settlement_bank_account'
|
557
|
+
@bank_accounts << obj
|
558
|
+
when 'acquirer'
|
559
|
+
@acquirers << obj
|
560
|
+
when 'contract'
|
561
|
+
@contracts << obj
|
562
|
+
when 'user'
|
563
|
+
@users << obj
|
564
|
+
when 'iso'
|
565
|
+
@isos << obj
|
566
|
+
when 'agent'
|
567
|
+
@agents << obj
|
568
|
+
when 'merchant'
|
569
|
+
@merchants << obj
|
570
|
+
end
|
313
571
|
end
|
314
572
|
|
315
573
|
# Create association for agent, merchant, settlement bank Account, Email, Payment Method
|
@@ -317,119 +575,243 @@ module SalesforceMigration
|
|
317
575
|
# If it is merchant, it will find the Agent, Payment Method, User and create the associations
|
318
576
|
# If it is Settlement Bank Account it will find the Merchant and create the associations
|
319
577
|
# @param [SugarCRM::Namespace::Object] obj the object for which an association will be created
|
320
|
-
# @param [String] type type of the object
|
578
|
+
# @param [String] type - type of the object
|
321
579
|
#
|
322
|
-
# @return [SugarCRM::Namespace::Object] the object
|
323
|
-
def
|
324
|
-
|
580
|
+
# @return [SugarCRM::Namespace::Object] - the object
|
581
|
+
def create_associations(obj, type)
|
582
|
+
# You need to save! the object before passing it, as it won't create associations
|
583
|
+
@logger.info("Creating associations for #{type} #{obj.name}")
|
584
|
+
|
325
585
|
case type
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
agent = find_sugarcrm_object('agent', 'sf_id', obj.sf_agent)
|
344
|
-
if agent
|
345
|
-
obj.associate! agent
|
346
|
-
obj.assigned_user_id = agent.assigned_user_id
|
347
|
-
end
|
348
|
-
|
349
|
-
when "settlement_bank_account"
|
350
|
-
merchant = find_sugarcrm_object('merchant', 'sf_id', obj.sf_merchant)
|
351
|
-
obj.associate! merchant if merchant
|
586
|
+
when "agent"
|
587
|
+
associate_with!('iso', @isos, 'sf_id', obj)
|
588
|
+
|
589
|
+
associate_with!('email', @emails, 'sf_agent_id', obj)
|
590
|
+
when "merchant"
|
591
|
+
associate_with!('agent', @agents, 'sf_id', obj)
|
592
|
+
|
593
|
+
associate_with!('contract', @contracts, 'sf_account_id', obj)
|
594
|
+
|
595
|
+
associate_with!('email', @emails_to_merchants, 'sf_merchant_id', obj)
|
596
|
+
|
597
|
+
associate_with!('payment_method', @payment_to_merchants, 'sf_merchant_id', obj)
|
598
|
+
|
599
|
+
associate_with!('settlement_bank_account', @bank_accounts, 'sf_merchant_id', obj)
|
600
|
+
|
601
|
+
assign_user_as_owner_to_record(obj, obj)
|
352
602
|
end
|
353
603
|
obj
|
354
604
|
end
|
355
605
|
|
356
|
-
#
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
#user.email1 = obj.email_address || "mail@example.com"
|
369
|
-
user.email1 = 'stefan@emerchantpay.com'
|
370
|
-
user.status = 'Inactive'
|
371
|
-
user.system_generated_password = false
|
372
|
-
user.save!
|
373
|
-
obj.assigned_user_id = user.id
|
374
|
-
obj.save!
|
375
|
-
|
376
|
-
populate_user_pool(user, type)
|
377
|
-
end
|
378
|
-
|
379
|
-
# Populates Users as SugarCRM objects.
|
380
|
-
# We use them later on, when associating objects with Security Groups
|
381
|
-
# @param [SugarCRM::Namespace::Object] Already created user object
|
382
|
-
# @param [String] type type of the object
|
383
|
-
def populate_user_pool(user, type)
|
384
|
-
case type
|
385
|
-
when 'iso'
|
386
|
-
@iso_users << user
|
387
|
-
when 'agent'
|
388
|
-
@agent_users << user
|
606
|
+
# Associate an object with selected ids
|
607
|
+
def associate_module_by_ids!(obj, type, list_of_ids, assign_to_user = false, reverse_association = false)
|
608
|
+
if list_of_ids.is_a?(Array)
|
609
|
+
list_of_ids.each do |record_id|
|
610
|
+
sugar_object = find_sugarcrm_object(type, 'sf_id', record_id)
|
611
|
+
if reverse_association
|
612
|
+
sugar_object.associate! obj if sugar_object
|
613
|
+
else
|
614
|
+
obj.associate! sugar_object if sugar_object
|
615
|
+
end
|
616
|
+
assign_user_as_owner_to_record(object, sugar_object) if assign_to_user
|
617
|
+
end
|
389
618
|
end
|
390
619
|
end
|
391
620
|
|
392
621
|
# Find records(payment methods, emails) in the junction object arrays, given the merchant_id
|
393
622
|
# Both payment methods and emails have a many-to-many relationship with the merchant in Salesforce
|
394
|
-
|
395
|
-
|
396
|
-
|
623
|
+
|
624
|
+
def associate_with!(type, relation_data, relation_field, object)
|
625
|
+
return unless type and relation_data and relation_field and object
|
626
|
+
|
627
|
+
case type
|
628
|
+
when "iso"
|
629
|
+
related_to_id = object.sf_iso_id
|
630
|
+
when "agent"
|
631
|
+
related_to_id = object.sf_agent_id
|
632
|
+
else
|
633
|
+
related_to_id = object.sf_id
|
634
|
+
end
|
635
|
+
|
636
|
+
relation_data = (@action == "update") ? type : relation_data
|
637
|
+
|
638
|
+
found_records = find_related_records(relation_data, relation_field, related_to_id)
|
639
|
+
|
640
|
+
return if found_records.blank?
|
641
|
+
|
642
|
+
if %(contract email settlement_bank_account).include? type
|
643
|
+
associate_module_by_ids!(obj, type, found_records, true, false)
|
644
|
+
else
|
645
|
+
associate_module_by_ids!(obj, type, found_records, false, false)
|
397
646
|
end
|
398
|
-
false
|
399
647
|
end
|
400
|
-
|
401
|
-
def
|
402
|
-
|
403
|
-
|
648
|
+
|
649
|
+
def find_related_records(relation_data, relation_field, related_to_id)
|
650
|
+
return unless relation_data and relation_field and related_to_id
|
651
|
+
|
652
|
+
search_results = []
|
653
|
+
|
654
|
+
case @action
|
655
|
+
when "initial_run"
|
656
|
+
relation_data.each do |record|
|
657
|
+
# Check if we are dealing with file-relations (stored as Array)
|
658
|
+
# OR if we're using SugarCRM records (store as Object)
|
659
|
+
|
660
|
+
record_id = (relation_data.first.is_a?(Hash)) ? record['sf_id'] : record.sf_id
|
661
|
+
relate_id = (relation_data.first.is_a?(Hash)) ? record[relation_field] : record.send(relation_field.to_sym)
|
662
|
+
|
663
|
+
search_results << record_id if compare_salesforce_ids(relate_id, related_to_id)
|
664
|
+
end
|
665
|
+
when "update"
|
666
|
+
# Check if we are dealing with file-relations (stored as Array)
|
667
|
+
if relation_data.first.is_a?(Hash)
|
668
|
+
relation_data.each { |record| search_results << record['sf_id'] if compare_salesforce_ids(record[relation_field], related_to_id) }
|
669
|
+
# OR extract the objects from SugarCRM
|
670
|
+
else
|
671
|
+
records = find_sugarcrm_object(relation_data, relation_field, related_to_id)
|
672
|
+
|
673
|
+
if records.is_a?(Array)
|
674
|
+
records.each { |record| search_results << record.sf_id }
|
675
|
+
else
|
676
|
+
search_results << records.sf_id
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
return search_results
|
682
|
+
end
|
683
|
+
|
684
|
+
# Assign user to an object, by providing a source and target objects
|
685
|
+
#
|
686
|
+
# @param [Object] id_object - An object holding the User Id
|
687
|
+
# @param [Object] target_object - The object we want to associate to this user
|
688
|
+
#
|
689
|
+
def assign_user_as_owner_to_record(id_object, object_to_assign)
|
690
|
+
return unless id_object and object_to_assign
|
691
|
+
|
692
|
+
salesforce_id = (id_object.sf_agent_id.blank?) ? id_object.sf_id : id_object.sf_agent_id
|
693
|
+
|
694
|
+
user = find_sugarcrm_object('users', 'salesforce_id', salesforce_id)
|
695
|
+
|
696
|
+
return if user.blank?
|
697
|
+
|
698
|
+
# Warn the user that we might've stumbbled upon some duplication or non-empty database (SalesForce Ids shoud be unique)
|
699
|
+
if user.is_a?(Array)
|
700
|
+
@logger.error("We found a SalesForce Id with two created SugarCRM users.")
|
701
|
+
user = user.first
|
404
702
|
end
|
703
|
+
|
704
|
+
@logger.info("Assigning #{user.last_name} as owner to #{object_to_assign.name}")
|
705
|
+
|
706
|
+
object_to_assign.assigned_user_id = user.id
|
707
|
+
object_to_assign.save!
|
708
|
+
end
|
709
|
+
|
710
|
+
# Compare SalesForce Ids - SalesForce have two type of ids - 15 digit case-sensitive and 18-digit case-insensitive
|
711
|
+
#
|
712
|
+
# @param [String] salesforce_id - salesforce id to compare to
|
713
|
+
# @param [String] target_id - id
|
714
|
+
#
|
715
|
+
# @return [Boolean] true on match, every other case - false
|
716
|
+
def compare_salesforce_ids(salesforce_id, target_id)
|
717
|
+
return false unless salesforce_id and target_id
|
718
|
+
|
719
|
+
case salesforce_id.length
|
720
|
+
when 15
|
721
|
+
if target_id.length == 18
|
722
|
+
target_id = target_id[0..-4]
|
723
|
+
end
|
724
|
+
if salesforce_id == target_id
|
725
|
+
return true
|
726
|
+
end
|
727
|
+
when 18
|
728
|
+
if target_id.length == 15
|
729
|
+
salesforce_id = salesforce_id[0..-4]
|
730
|
+
end
|
731
|
+
if salesforce_id.casecmp(target_id) == 0
|
732
|
+
return true
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
405
736
|
false
|
406
737
|
end
|
407
738
|
|
408
|
-
#Creates the Security Group object in SugarCRM
|
739
|
+
# Creates the Security Group object in SugarCRM
|
740
|
+
#
|
409
741
|
# @param [SugarCRM::Namespace::EmpIso] Iso object
|
410
742
|
def create_security_group_iso(iso)
|
411
743
|
@logger.info("Creating SecurityGroup #{iso.name}")
|
412
|
-
|
413
|
-
|
744
|
+
security_group = SugarCRM::SecurityGroup.new(:name => iso.name) unless find_sugarcrm_object('security_group','name', iso.name)
|
745
|
+
security_group.save!
|
414
746
|
end
|
415
747
|
|
416
|
-
# Assign all records,
|
748
|
+
# Assign all records, to their ISO's SecurityGroup
|
417
749
|
def associate_records_to_groups
|
418
750
|
put_isos_into_iso_group
|
419
751
|
put_agents_into_iso_group
|
420
752
|
put_merchants_into_iso_group
|
421
753
|
end
|
422
754
|
|
755
|
+
# Create user associated with SugarCRM object
|
756
|
+
# Default email: mail@example.com, default password: 123456
|
757
|
+
#
|
758
|
+
# @param [SugarCRM::Namespace::Object] obj object for which a user will be created
|
759
|
+
# @param [String] type type of the object
|
760
|
+
def create_user(obj, type)
|
761
|
+
@logger.info("Creating user for #{type} #{obj.name}")
|
762
|
+
if (defined?(obj.emerchantpay_iso_id) && (obj.emerchantpay_iso_id.blank? || obj.email_address.blank?)) ||
|
763
|
+
(defined?(obj.emerchantpay_agent_id) && (obj.emerchantpay_agent_id.blank? || obj.email_address.blank?))
|
764
|
+
@logger.error("Record |#{obj.name}| with type |#{type}| have empty fields (which are required), thus its skipped!")
|
765
|
+
else
|
766
|
+
user = SugarCRM::User.new
|
767
|
+
user.user_name = (type == 'agent') ? obj.emerchantpay_agent_id : obj.emerchantpay_iso_id
|
768
|
+
user.last_name = obj.name
|
769
|
+
user.emp_type = type
|
770
|
+
user.email1 = obj.email_address || ""
|
771
|
+
user.status = 'Inactive'
|
772
|
+
user.salesforce_id = obj.sf_id
|
773
|
+
user.system_generated_password = false
|
774
|
+
user.save!
|
775
|
+
obj.assigned_user_id = user.id
|
776
|
+
obj.save!
|
777
|
+
|
778
|
+
populate_user_pool(user, type)
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
# Populates Users as SugarCRM objects.
|
783
|
+
# We use them later on, when associating objects with Security Groups
|
784
|
+
# @param [SugarCRM::Namespace::Object] Already created user object
|
785
|
+
# @param [String] type type of the object
|
786
|
+
def populate_user_pool(user, type)
|
787
|
+
case type
|
788
|
+
when 'iso'
|
789
|
+
@iso_users << user
|
790
|
+
when 'agent'
|
791
|
+
@agent_users << user
|
792
|
+
end
|
793
|
+
end
|
794
|
+
|
423
795
|
def put_isos_into_iso_group
|
424
796
|
if @isos
|
425
797
|
@logger.info("Puting ISOs into ISO groups")
|
426
798
|
role = SugarCRM::ACLRole.find_by_name("isos")
|
427
799
|
@isos.each do |iso|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
800
|
+
security_group = find_sugarcrm_object('security_group','name', iso.name)
|
801
|
+
|
802
|
+
if security_group
|
803
|
+
user = SugarCRM::User.find_by_last_name(iso.name)
|
804
|
+
iso.associate! security_group
|
805
|
+
role.associate! security_group
|
806
|
+
|
807
|
+
if user.nil?
|
808
|
+
@logger.error("ISO (#{iso.name}) doesn't have a user record")
|
809
|
+
else
|
810
|
+
user.associate! security_group
|
811
|
+
end
|
812
|
+
else
|
813
|
+
@logger.error("Couldn't find a SecurityGroup for ISO - #{iso.name}")
|
814
|
+
end
|
433
815
|
end
|
434
816
|
end
|
435
817
|
end
|
@@ -438,15 +820,24 @@ module SalesforceMigration
|
|
438
820
|
if @agents
|
439
821
|
@logger.info("Putting agent records, agent users and agent role into ISO groups")
|
440
822
|
@agents.each do |agent|
|
441
|
-
|
823
|
+
security_group = find_sugarcrm_object('security_group','name', agent.emp_iso.first.name) unless agent.emp_iso.empty?
|
442
824
|
role = SugarCRM::ACLRole.find_by_name('agents')
|
443
|
-
if
|
825
|
+
if security_group
|
444
826
|
user = SugarCRM::User.find_by_last_name(agent.name)
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
827
|
+
|
828
|
+
if user.nil?
|
829
|
+
@logger.error("Agent (#{agent.emp_iso.first.name}) doesn't have a user record")
|
830
|
+
else
|
831
|
+
user.associate! security_group
|
832
|
+
end
|
833
|
+
|
834
|
+
@logger.info("Puting Agent #{agent.name} in Security Group #{security_group.name}")
|
835
|
+
agent.associate! security_group
|
836
|
+
role.associate! security_group
|
837
|
+
put_email_objects_into_iso_group(security_group, 'agent', agent)
|
838
|
+
else
|
839
|
+
@logger.error("Couldn't find a ISO SecurityGroup for Agent - #{agent.emp_iso.first.name}")
|
840
|
+
end
|
450
841
|
end
|
451
842
|
end
|
452
843
|
end
|
@@ -459,81 +850,94 @@ module SalesforceMigration
|
|
459
850
|
if @merchants
|
460
851
|
@logger.info("Puting merchants into ISO groups")
|
461
852
|
@merchants.each do |merchant|
|
462
|
-
unless (merchant.emp_agent.
|
463
|
-
|
464
|
-
@logger.info("Puting merchant #{merchant.name} into ISO group")
|
465
|
-
|
466
|
-
if sg
|
467
|
-
merchant.associate! sg
|
468
|
-
put_email_objects_into_iso_group(sg, merchant.sf_id)
|
469
|
-
put_payment_methods_objects_into_iso_group(sg, merchant.sf_id)
|
470
|
-
end
|
853
|
+
unless (merchant.emp_agent.blank? || merchant.emp_agent.first.emp_iso.blank?)
|
854
|
+
security_group = find_sugarcrm_object('security_group','name', merchant.emp_agent.first.emp_iso.first.name)
|
471
855
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
856
|
+
if security_group
|
857
|
+
@logger.info("Puting merchant #{merchant.name} into ISO group")
|
858
|
+
merchant.associate! security_group
|
859
|
+
put_bank_accounts_into_iso_group(security_group, merchant)
|
860
|
+
put_email_objects_into_iso_group(security_group, 'merchant', merchant)
|
861
|
+
put_payment_methods_objects_into_iso_group(security_group, merchant)
|
862
|
+
else
|
863
|
+
@logger.error("Couldn't find a ISO SecurityGroup for Merchant - #{merchant.name}")
|
476
864
|
end
|
477
865
|
end
|
478
866
|
end
|
479
867
|
end
|
480
868
|
end
|
481
869
|
|
482
|
-
def put_bank_accounts_into_iso_group(
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
870
|
+
def put_bank_accounts_into_iso_group(security_group, merchant)
|
871
|
+
return unless security_group and merchant
|
872
|
+
|
873
|
+
@logger.info("Puting Bank Account for #{merchant.name} into ISO group")
|
874
|
+
|
875
|
+
case @action
|
876
|
+
when "initial_run"
|
877
|
+
bank_accounts_for_merchant_id = find_related_records(@bank_accounts, 'sf_merchant_id', merchant.sf_id)
|
878
|
+
when "update"
|
879
|
+
bank_accounts_for_merchant_id = find_related_records('settlement_bank_account', 'sf_merchant_id', merchant.sf_id)
|
489
880
|
end
|
881
|
+
|
882
|
+
return if bank_accounts_for_merchant_id.blank?
|
883
|
+
|
884
|
+
associate_module_by_ids!(security_group, 'settlement_bank_account', bank_accounts_for_merchant_id, false, true)
|
490
885
|
end
|
491
886
|
|
492
|
-
def put_email_objects_into_iso_group(
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
887
|
+
def put_email_objects_into_iso_group(security_group, type, obj)
|
888
|
+
return unless security_group and type and obj
|
889
|
+
|
890
|
+
@logger.info("Puting Emails for #{obj.name} into ISO group")
|
891
|
+
|
892
|
+
case type
|
893
|
+
when "agent"
|
894
|
+
case @action
|
895
|
+
when "initial_run"
|
896
|
+
email_ids_for_object = find_related_records(@emails, 'sf_agent_id', obj.sf_id)
|
897
|
+
when "update"
|
898
|
+
email_ids_for_object = find_related_records('email', 'sf_agent_id', obj.sf_id)
|
899
|
+
end
|
900
|
+
when "merchant"
|
901
|
+
case @action
|
902
|
+
when "initial_run"
|
903
|
+
email_ids_for_object = find_related_records(@emails_to_merchants, 'sf_merchant_id', obj.sf_id)
|
904
|
+
when "update"
|
905
|
+
email_ids_for_object = find_related_records('email', 'sf_merchant_id', obj.sf_id)
|
504
906
|
end
|
505
|
-
end
|
506
907
|
end
|
908
|
+
|
909
|
+
return if email_ids_for_object.blank?
|
910
|
+
|
911
|
+
associate_module_by_ids!(security_group, 'email', email_ids_for_object, false, true)
|
507
912
|
end
|
508
913
|
|
509
|
-
def put_payment_methods_objects_into_iso_group(
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
else
|
520
|
-
payment_method.associate! sg
|
521
|
-
end
|
522
|
-
end
|
523
|
-
end
|
914
|
+
def put_payment_methods_objects_into_iso_group(security_group, merchant)
|
915
|
+
return unless security_group and merchant
|
916
|
+
|
917
|
+
@logger.info("Puting Payment Methods for #{merchant.name} into ISO group")
|
918
|
+
|
919
|
+
payment_methods = find_related_records(@payment_to_merchants, 'sf_merchant_id', merchant.sf_id)
|
920
|
+
|
921
|
+
return if payment_methods.blank?
|
922
|
+
|
923
|
+
associate_module_by_ids!(security_group, 'payment_method', payment_methods, false, true)
|
524
924
|
end
|
525
925
|
|
526
926
|
# Returns the SugarCRM module namespace
|
527
927
|
# @param [String] type type of the module object
|
528
928
|
def get_sugarcrm_module_type(type)
|
529
929
|
modules = {
|
530
|
-
"
|
930
|
+
"acquirer" => SugarCRM::EmpAcquirer,
|
531
931
|
"agent" => SugarCRM::EmpAgent,
|
932
|
+
"contract" => SugarCRM::EmpContract,
|
933
|
+
"email" => SugarCRM::EmpEmail,
|
934
|
+
"iso" => SugarCRM::EmpIso,
|
532
935
|
"merchant" => SugarCRM::EmpMerchant,
|
533
936
|
"payment_method" => SugarCRM::EmpPaymentmethod,
|
534
937
|
"settlement_bank_account" => SugarCRM::EmpSettlementBankAccount,
|
938
|
+
"user" => SugarCRM::EmpUser,
|
535
939
|
"security_group" => SugarCRM::SecurityGroup,
|
536
|
-
"
|
940
|
+
"users" => SugarCRM::User,
|
537
941
|
}
|
538
942
|
modules[type]
|
539
943
|
end
|
@@ -549,5 +953,17 @@ module SalesforceMigration
|
|
549
953
|
SugarCRM.connection.get_entry_list(module_type, "#{module_type.downcase}.#{attribute} = '#{search_string}'")
|
550
954
|
end
|
551
955
|
|
956
|
+
# Populates the var_pool with Sugar Objects.
|
957
|
+
# Reason being, is that if you abort the current process (error or some other reason)
|
958
|
+
# You won't be able to continue from the same place and be able to correctly associate the objects
|
959
|
+
# To prevent this, we can just load back every object for every type and continue uninterrupted
|
960
|
+
#
|
961
|
+
# @param [String] id - SalesForce id of the object, that we want to retrieve
|
962
|
+
# @param [String] type - type of the object, that we want to retrieve (module type)
|
963
|
+
def populate_var_poll_from_sugar(id, type)
|
964
|
+
obj = find_sugarcrm_object(type, 'sf_id', id)
|
965
|
+
populate_var_pool(obj, type) if obj
|
966
|
+
end
|
967
|
+
|
552
968
|
end
|
553
969
|
end
|