Class: SubscriberList

Inherits:
ApplicationRecord show all
Includes:
Models::Auditable
Defined in:
app/models/subscriber_list.rb

Overview

== Schema Information

Table name: subscriber_lists
Database name: primary

id :integer not null, primary key
add_all_emails :boolean
customer_search_params :jsonb
list_type :string
name :string
created_at :datetime not null
updated_at :datetime not null
creator_id :integer
updater_id :integer

Constant Summary collapse

LIST_TYPES =
%w[email_static email_dynamic customer].freeze

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary collapse

Has many collapse

Has and belongs to many collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Models::Auditable

#all_skipped_columns, #audit_reference_data, #creator, #should_not_save_version, #stamp_record, #updater

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#customer_search_paramsObject (readonly)



33
# File 'app/models/subscriber_list.rb', line 33

validates :customer_search_params, presence: true, if: :email_dynamic?

#imported_subscribers_csvObject

Returns the value of attribute imported_subscribers_csv.



39
40
41
# File 'app/models/subscriber_list.rb', line 39

def imported_subscribers_csv
  @imported_subscribers_csv
end

#list_typeObject (readonly)



32
# File 'app/models/subscriber_list.rb', line 32

validates :name, :list_type, presence: true

#nameObject (readonly)



32
# File 'app/models/subscriber_list.rb', line 32

validates :name, :list_type, presence: true

Class Method Details

.customersActiveRecord::Relation<SubscriberList>

A relation of SubscriberLists that are customers. Active Record Scope

Returns:

See Also:



30
# File 'app/models/subscriber_list.rb', line 30

scope :customers, -> { where(list_type: 'customer') }

.ensure_unique_name(name) ⇒ Object



41
42
43
44
45
46
# File 'app/models/subscriber_list.rb', line 41

def self.ensure_unique_name(name)
  unique_name = name.dup
  existing_list = where(name: unique_name).exists?
  unique_name << " #{Time.current.to_fs(:compact)}" if existing_list # we need to make the name unique
  unique_name
end

Instance Method Details

#campaignsActiveRecord::Relation<Campaign>

Returns:

See Also:



28
# File 'app/models/subscriber_list.rb', line 28

has_and_belongs_to_many :campaigns

#customer?Boolean

Returns:

  • (Boolean)


52
53
54
# File 'app/models/subscriber_list.rb', line 52

def customer?
  list_type == 'customer'
end

#email?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'app/models/subscriber_list.rb', line 48

def email?
  %w[email_static email_dynamic].include?(list_type)
end

#email_dynamic?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'app/models/subscriber_list.rb', line 56

def email_dynamic?
  list_type == 'email_dynamic'
end

#generate_subscribersObject



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'app/models/subscriber_list.rb', line 147

def generate_subscribers
  return true if list_type.in?(%w[email_static customer])

  results = perform_search_query
  email_addresses = []
  if add_all_emails.to_b
    customer_ids = results.where.not(state: %w[closed bankrupt]).reorder('').pluck(:id)
    email_addresses = ContactPoint.emails.under_customer_ids(customer_ids).distinct.pluck(:detail)
  else
    results.each do |search_result|
      if (email = search_result.customer_main_email || search_result.customer_first_contact_email)
        email_addresses << email
      end
    end
  end

  email_addresses.uniq! # remove any duplicates

  timestamp = Time.current

  logger.info "[generate_subscribers] Subscriber list generation candidates: #{subscribers.size}"

  # Who's already subscribed, who's not
  already_subscribed = subscribers.pluck(:email_address) & email_addresses
  logger.info "[generate_subscribers] * already subscribed: #{already_subscribed.size}"

  # inactivate those not already_subscribed
  not_on_our_list = subscribers.where.not(email_address: already_subscribed)
  logger.info "[generate_subscribers] * Inactivating those not on our candidate list: #{not_on_our_list.size}"
  not_on_our_list.update_all(active: false, updated_at: timestamp)

  # Those already subscribed gets activated in case they where not active
  if already_subscribed.present?
    on_our_list_inactive = subscribers.where(email_address: already_subscribed).where.not(active: true)
    logger.info "[generate_subscribers] * Activating those from our candidate list which were inactive: #{on_our_list_inactive.size}"
    on_our_list_inactive.update_all(active: true, updated_at: timestamp)

    existing_active_unsubscribed = subscribers.where(active: true).joins(:email_preference).merge(EmailPreference.completely_unsubscribed)
    logger.info "[generate_subscribers] * De-activating #{existing_active_unsubscribed.size} subscribers who have completely unsubscribed"
    existing_active_unsubscribed.update_all(active: false, updated_at: timestamp)
  end

  # From our list who remains to create
  not_subscribed = email_addresses - already_subscribed

  # But we will trim it down first and remove everyone who is completele unsubscribed to emails
  completely_unsubscribed_emails = EmailPreference.completely_unsubscribed.where(email: not_subscribed).pluck(:email)
  logger.info "Out of #{not_subscribed.size} subscribers to add, removing #{completely_unsubscribed_emails.size} which are completely unsubcribed"

  not_subscribed -= completely_unsubscribed_emails

  if not_subscribed.present?
    logger.info "[generate_subscribers] * Need to now create #{not_subscribed.size} new subscribers"
    good_emails = not_subscribed.select { |email| email =~ ContactPoint::EMAIL_REGEXP } # filter out any bad email addresses, else we'll get a PG::SyntaxError
    new_subscribers = []
    good_emails.each do |email|
      new_subscribers << { subscriber_list_id: id,
                           email_address: email,
                           active: true }
    end
    require 'activerecord-import/base'
    require 'activerecord-import/active_record/adapters/postgresql_adapter'
    result = Subscriber.import new_subscribers, validate: false
    logger.info "[generate_subscribers] created #{result.num_inserts} subscribers"
  end
  logger.info '[generate_subscribers] * All done with generate_subscribers'

  true
end

#import_subscribers_from_csvObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/models/subscriber_list.rb', line 60

def import_subscribers_from_csv
  return unless imported_subscribers_csv.present?

  emails = []
  CSV.foreach(imported_subscribers_csv.path) do |row|
    emails << row[0] if row[0].present?
  end
  if add_all_emails == true
    emails.each do |email|
      parties = Party.joins(:contact_points).merge(ContactPoint.emails.where(detail: email))
      parties.each do |p|
        if p.is_a?(Contact) && p.customer.present?
          emails += p.customer.all_emails
        elsif p.is_a?(Customer)
          emails += p.all_emails
        end
      end
    end
  end
  emails.uniq.each do |email|
    subscribers << Subscriber.new(email_address: email) unless subscribers.any? { |s| s.email_address == email }
  end
end

#name_and_typeObject



111
112
113
# File 'app/models/subscriber_list.rb', line 111

def name_and_type
  "#{name} [#{list_type}]"
end

#perform_search_queryObject



141
142
143
144
145
# File 'app/models/subscriber_list.rb', line 141

def perform_search_query
  assert_valid_customer_search_params!
  cs = CustomerSearch.create(query_params: customer_search_params)
  cs.perform(nil, nil, nil, false, nil, true, true)
end

#perform_search_query_countObject



135
136
137
138
139
# File 'app/models/subscriber_list.rb', line 135

def perform_search_query_count
  assert_valid_customer_search_params!
  cs = CustomerSearch.new(query_params: customer_search_params, selected_columns: [:id])
  cs.fast_count
end

#subscriber_countObject



115
116
117
118
119
120
121
# File 'app/models/subscriber_list.rb', line 115

def subscriber_count
  if email_dynamic? && subscribers.empty?
    perform_search_query_count
  else
    subscribers.active.size
  end
end

#subscriber_counts_groupedObject



123
124
125
126
127
128
129
130
131
132
133
# File 'app/models/subscriber_list.rb', line 123

def subscriber_counts_grouped
  if email_dynamic? && subscribers.empty?
    count = perform_search_query_count
    { 'active' => count }
  else
    {
      'active' => subscribers.active.count,
      'inactive' => subscribers.inactive.count
    }
  end
end

#subscribersActiveRecord::Relation<Subscriber>

Returns:

See Also:



27
# File 'app/models/subscriber_list.rb', line 27

has_many :subscribers, dependent: :destroy, inverse_of: :subscriber_list