Class: OnlineMigrations::DataMigrations::BackfillQuoteBuilderOnlineOppsToIq

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

Overview

Retroactively re-tags the legacy "QB-flow opp accidentally written as
'Online'" rows to the canonical 'IQ'. These came in via the second
of the two quote-builder opp-creation paths
(RoomConfiguration.update_or_create_from_rhc_args, the share_key /
auto-save flow) which, prior to PR #756, hardcoded
opportunity_reception_type: 'Online' — even though the rooms it
created beneath the opp were correctly tagged with QB-flow reception
types ('IQ', 'QuoteBuilder', 'DesignTool2', or 'Upload').

Match criteria

An 'Online' opp is reclassified to 'IQ' when EITHER of the
following signals fires:

(a) Room signal — the opp has at least one room_configurations
row whose reception_type is in QB_ROOM_RECEPTION_TYPES. This
captures the bulk of the data: any opp whose attached rooms were
created by the QB flow.

(b) Name signal — the opp's name starts with 'Quote Builder'.
The QB flow's default name (OpportunityConstants::IQ_PROJECT_NAME)
is 'Quote Builder'; subsequent same-customer opps get
'Quote Builder #N' from Opportunity.get_unique_name. Catches
orphan QB opps whose rooms were since deleted.

Opps matching neither signal stay 'Online' — they're legitimate
web-lead-form rows that genuinely came from the generic online lead
capture, not from quote-builder.

Audit (as of 2026-05-11)

both signals: 5,703
name only (no rooms left): 296
room only (custom or auto name): 2,977
total to migrate: 8,976
genuine 'Online' leads (left): 1,620

See Also:

Constant Summary collapse

BATCH_SIZE =

Batch size — opportunities is a large table; keep transactions small.

1_000
QB_ROOM_RECEPTION_TYPES =

room_configurations.reception_type values that originate from the
quote-builder flow. Includes the legacy 'QuoteBuilder' literal in
case this migration is interleaved with BackfillQuoteBuilderToIq
— both 'IQ' and 'QuoteBuilder' mean the same flow.

%w[IQ QuoteBuilder DesignTool2 Upload].freeze
QB_NAME_PREFIX =

Name prefix written by the QB flow (the literal OpportunityConstants::IQ_PROJECT_NAME
and its #N-suffixed variants from Opportunity.get_unique_name).

'Quote Builder'

Instance Method Summary collapse

Instance Method Details

#collectionActiveRecord::Batches::BatchEnumerator

Batches of opp IDs that match either signal.

Returns:

  • (ActiveRecord::Batches::BatchEnumerator)


67
68
69
# File 'lib/online_migrations/data_migrations/backfill_quote_builder_online_opps_to_iq.rb', line 67

def collection
  candidate_scope.in_batches(of: BATCH_SIZE)
end

#countInteger

Total un-migrated rows. Drives the online_migrations progress bar.

Returns:

  • (Integer)


89
90
91
# File 'lib/online_migrations/data_migrations/backfill_quote_builder_online_opps_to_iq.rb', line 89

def count
  candidate_scope.count
end

#process(opps) ⇒ void

This method returns an undefined value.

Rewrites one batch from 'Online' to 'IQ'. Re-applies the full
candidate_scope classifier at write time so the update only
touches rows still matching both the 'Online' reception type
AND a QB signal — keeps the write idempotent (already-migrated
rows are no-ops, no updated_at churn) and defensive against
callers passing IDs that aren't real candidates.

Parameters:



81
82
83
84
# File 'lib/online_migrations/data_migrations/backfill_quote_builder_online_opps_to_iq.rb', line 81

def process(opps)
  candidate_scope.where(id: opps.ids)
                 .update_all(opportunity_reception_type: 'IQ', updated_at: Time.current)
end