Class: OnlineMigrations::DataMigrations::BackfillOpportunityParents

Inherits:
OnlineMigrations::DataMigration
  • Object
show all
Defined in:
lib/online_migrations/data_migrations/backfill_opportunity_parents.rb

Overview

Backfills Opportunity#parent_id on historical CRM opportunities that
are plausibly follow-ups to an earlier website-originated opportunity
for the same customer and project. The runtime equivalent lives on
the model as Opportunity#auto_link_to_web_parent (a before_create
callback); this migration applies the same rule retroactively to the
~110 pairs identified in the analysis attached to PR #750.

Match criteria

  • Same customer_id
  • Web opp's reception type ∈ IQ
  • Web opp not in a terminal state (won / lost / abandoned / cancelled
    / untracked) — matches Opportunity#open_opportunities
  • Web opp created within LOOKBACK_DAYS days BEFORE the CRM opp
  • Same installation_postal_code if both are set; otherwise a no-zip
    web opp is the fallback. A different zip means a different project.

See Also:

Constant Summary collapse

BATCH_SIZE =

Batch size.

500
WEB_RECEPTION_TYPES =

Web reception types whose opps are eligible to be linked as parents.

%w[Online IQ].freeze
LOOKBACK_DAYS =

Lookback window — a CRM opp is only considered a follow-up if the
web opp was created within this many days BEFORE the CRM opp.

180
TERMINAL_STATES =

States the web opp must NOT have reached for a CRM follow-up to be
considered a continuation of the same project. Mirrors the exclusion
list used by Opportunity#open_opportunities so the runtime auto-link
and the historical backfill apply the same rule.

%w[won lost abandoned cancelled untracked].freeze

Instance Method Summary collapse

Instance Method Details

#collectionActiveRecord::Batches::BatchEnumerator

CRM opportunities still eligible for parent backfill, batched.

Returns:

  • (ActiveRecord::Batches::BatchEnumerator)


44
45
46
47
48
49
50
# File 'lib/online_migrations/data_migrations/backfill_opportunity_parents.rb', line 44

def collection
  Opportunity.where(opportunity_reception_type: "CRM",
                    parent_id: nil,
                    merged_into_id: nil)
             .where.not(customer_id: nil)
             .in_batches(of: BATCH_SIZE)
end

#countInteger

Total CRM opportunities still eligible for backfill. Used by
online_migrations to render the progress bar.

Returns:

  • (Integer)


76
77
78
79
80
81
82
# File 'lib/online_migrations/data_migrations/backfill_opportunity_parents.rb', line 76

def count
  Opportunity.where(opportunity_reception_type: "CRM",
                    parent_id: nil,
                    merged_into_id: nil)
             .where.not(customer_id: nil)
             .count
end

#process(crm_opps) ⇒ void

This method returns an undefined value.

Links each CRM opp in the batch to its candidate parent when the
row is still unlinked. The conditional update_all avoids
clobbering a row whose parent_id or merged_into_id was set by
the live before_create hook while this batch was in flight, and
also bypasses Auditable / callbacks — the correct semantic for a
backfill.

Parameters:



62
63
64
65
66
67
68
69
70
# File 'lib/online_migrations/data_migrations/backfill_opportunity_parents.rb', line 62

def process(crm_opps)
  crm_opps.each do |crm_opp|
    parent = candidate_parent_for(crm_opp)
    next unless parent

    Opportunity.where(id: crm_opp.id, parent_id: nil, merged_into_id: nil)
               .update_all(parent_id: parent.id, updated_at: Time.current)
  end
end