Ran for 2 minutes, finished .
# frozen_string_literal: true
class Maintenance::CleanDuplicateCompanyGuidTreenodesTask < MaintenanceTasks::Task
def collection
TreeNode.where.not(company_guid: [nil, ''])
.group(:company_guid)
.having('count(*) > 1')
.pluck(:company_guid)
end
def process(company_guid)
with_first_keeper(company_guid) { |keeper| process_with_keeper(company_guid, keeper) }
end
def merge_duplicate_into_keeper(keeper:, duplicate:)
duplicate.mbo_profiles.reload.find_each do |mbo|
transfer_mbo_to_keeper(mbo: mbo, keeper: keeper)
end
reassign_legacy_custom_fields_to_keeper(duplicate, keeper)
end
private
def with_first_keeper(company_guid)
keeper = TreeNode.where(company_guid: company_guid).order(:created_at).first
yield keeper if keeper
end
def process_with_keeper(company_guid, keeper)
duplicate_ids = Maintenance::MergeDuplicateTreenodesService.call(
company_guid: company_guid, keeper: keeper, merger: self
)
return if duplicate_ids.empty?
ensure_single_primary_mbo_profile(keeper)
log_merge(company_guid: company_guid, keeper: keeper, duplicate_ids: duplicate_ids)
delete_duplicate_ids(duplicate_ids)
end
# :reek:FeatureEnvy
def transfer_mbo_to_keeper(mbo:, keeper:)
existing = keeper.mbo_profiles.find_by(
mbo_id: mbo.mbo_id,
country_id: mbo.country_id,
mid_back_office: mbo.mid_back_office
)
if existing
merge_custom_fields_into(source_mbo: mbo, target_mbo: existing)
mbo.destroy!
else
# Move the join record to point to the keeper instead of the duplicate
join = mbo.tree_node_to_mbo_profiles.where.not(tree_node_id: keeper.id).first
if join
join.update!(tree_node_id: keeper.id, primary: false)
else
keeper.tree_node_to_mbo_profiles.create!(mbo_profile: mbo, primary: false)
end
end
end
def merge_custom_fields_into(source_mbo:, target_mbo:)
source_mbo.custom_fields.find_each do |custom_field|
CustomFieldToMboProfile.find_or_create_by!(
custom_field: custom_field,
mbo_profile: target_mbo
)
end
end
def reassign_legacy_custom_fields_to_keeper(duplicate, keeper)
return unless CustomField.connection.column_exists?(:custom_fields, :tree_node_id)
duplicate.legacy_custom_fields.find_each do |custom_field|
custom_field.assign_legacy_tree_node_id(keeper)
end
end
def ensure_single_primary_mbo_profile(keeper)
primary_joins = keeper.tree_node_to_mbo_profiles.reload.where(primary: true).order(:created_at)
all_joins = keeper.tree_node_to_mbo_profiles.order(:created_at)
if primary_joins.empty? && all_joins.any?
all_joins.first.update!(primary: true)
elsif primary_joins.many?
primary_joins.offset(1).find_each { |join| join.update!(primary: false) }
end
end
def delete_duplicate_ids(duplicate_ids)
TreeNode.where(id: duplicate_ids).find_each do |tree_node|
tree_node.reload
tree_node.destroy!
end
end
def log_merge(company_guid:, keeper:, duplicate_ids:)
merged_ids = TreeNode.where(id: duplicate_ids).pluck(:id, :name).map { |id, name| "#{id}(#{name})" }.join(', ')
Rails.logger.info(
"[CleanDuplicateCompanyGuidTreenodesTask] company_guid=#{company_guid} " \
"kept treenode=#{keeper.id}(#{keeper.name}) deleted_duplicates=[#{merged_ids}]"
)
end
end
Processed 224 out of 224 items (100%).
Ran for 2 minutes, finished .
-1