Skip to content
19 changes: 13 additions & 6 deletions app/controllers/diy/diy_email_address_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,19 @@ def after_update_success
contact = current_diy_intake.campaign_contact
return unless contact.present?

CampaignEmail.create(
campaign_contact_id: contact.id,
message_name: "diy_followup_survey",
to_email: contact.email_address,
scheduled_send_at: Time.current + 1.day
)
existing_send_count = CampaignEmail.where(
campaign_contact_id: contact.id,
message_name: "diy_followup_survey"
).count

return if existing_send_count >= 2

CampaignEmail.create!(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check for exisitng message and see if scheduled_send_at has already passed before trying to send one

campaign_contact_id: contact.id,
message_name: "diy_followup_survey",
to_email: contact.email_address,
scheduled_send_at: Time.current + 1.day
)
end
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/campaign_email.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# Indexes
#
# index_campaign_emails_on_campaign_contact_id (campaign_contact_id)
# index_campaign_emails_on_contact_id_and_message_name (campaign_contact_id,message_name) UNIQUE
# index_campaign_emails_on_contact_id_and_message_name (campaign_contact_id,message_name)
# index_campaign_emails_on_mailgun_message_id (mailgun_message_id) UNIQUE
#
# Foreign Keys
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class RemoveUniqueIndexFromCampaignEmails < ActiveRecord::Migration[7.1]
disable_ddl_transaction!

def up
remove_index :campaign_emails, name: "index_campaign_emails_on_contact_id_and_message_name"

add_index :campaign_emails,
[:campaign_contact_id, :message_name],
name: "index_campaign_emails_on_contact_id_and_message_name",
algorithm: :concurrently
end

def down
remove_index :campaign_emails, name: "index_campaign_emails_on_contact_id_and_message_name"

add_index :campaign_emails,
[:campaign_contact_id, :message_name],
name: "index_campaign_emails_on_contact_id_and_message_name",
unique: true,
algorithm: :concurrently
end
end
4 changes: 2 additions & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2026_03_03_001000) do
ActiveRecord::Schema[7.1].define(version: 2026_03_20_232943) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
Expand Down Expand Up @@ -615,7 +615,7 @@
t.text "subject"
t.string "to_email"
t.datetime "updated_at", null: false
t.index ["campaign_contact_id", "message_name"], name: "index_campaign_emails_on_contact_id_and_message_name", unique: true
t.index ["campaign_contact_id", "message_name"], name: "index_campaign_emails_on_contact_id_and_message_name"
t.index ["campaign_contact_id"], name: "index_campaign_emails_on_campaign_contact_id"
t.index ["mailgun_message_id"], name: "index_campaign_emails_on_mailgun_message_id", unique: true
end
Expand Down
63 changes: 50 additions & 13 deletions spec/controllers/diy/diy_email_address_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,36 +141,73 @@

before do
allow(Flipper).to receive(:enabled?).and_call_original
allow(CampaignEmail).to receive(:create)
allow(Flipper).to receive(:enabled?).with(:send_diy_survey).and_return(true)
end

context "when flipper flag 'send_diy_survey' is off" do
it "doesn't create the send survey email" do
before do
allow(Flipper).to receive(:enabled?).with(:send_diy_survey).and_return(false)
end

post :update, params: params, session: { diy_intake_id: diy_intake.id }

expect(CampaignEmail).not_to have_received(:create)
it "does not create the send survey email" do
expect do
post :update, params: params, session: { diy_intake_id: diy_intake.id }
end.not_to change(CampaignEmail, :count)
end
end

context "with flipper flag 'send_diy_survey' enabled and contact present" do
it "creates a campaign contact" do
expect {
expect do
post :update, params: params, session: { diy_intake_id: diy_intake.id }
}.to change(CampaignContact, :count).by(1)
end.to change(CampaignContact, :count).by(1)
end

it "creates a campaign email for the diy survey" do
it "creates the first campaign email for the diy survey" do
expect do
post :update, params: params, session: { diy_intake_id: diy_intake.id }
end.to change(CampaignEmail, :count).by(1)

campaign_email = CampaignEmail.order(:created_at).last

expect(campaign_email.campaign_contact_id).to eq(diy_intake.reload.campaign_contact.id)
expect(campaign_email.message_name).to eq("diy_followup_survey")
expect(campaign_email.to_email).to eq("iloveplant@example.test")
expect(campaign_email.scheduled_send_at).to be_within(1.minute).of(Time.current + 1.day)
end

it "creates a second campaign email for the same contact and message" do
post :update, params: params, session: { diy_intake_id: diy_intake.id }

expect(CampaignEmail).to have_received(:create).with(
campaign_contact_id: diy_intake.campaign_contact.id,
message_name: "diy_followup_survey",
to_email: diy_intake.email_address,
scheduled_send_at: be_within(1.minute).of(Time.current + 1.day)
expect do
post :update, params: params, session: { diy_intake_id: diy_intake.id }
end.to change(CampaignEmail, :count).by(1)

contact = diy_intake.reload.campaign_contact
campaign_emails = CampaignEmail.where(
campaign_contact_id: contact.id,
message_name: "diy_followup_survey"
)

expect(campaign_emails.count).to eq(2)
end

it "does not create a third campaign email for the same contact and message" do
2.times do
post :update, params: params, session: { diy_intake_id: diy_intake.id }
end

expect do
post :update, params: params, session: { diy_intake_id: diy_intake.id }
end.not_to change(CampaignEmail, :count)

contact = diy_intake.reload.campaign_contact
campaign_emails = CampaignEmail.where(
campaign_contact_id: contact.id,
message_name: "diy_followup_survey"
)

expect(campaign_emails.count).to eq(2)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/factories/campaign_emails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# Indexes
#
# index_campaign_emails_on_campaign_contact_id (campaign_contact_id)
# index_campaign_emails_on_contact_id_and_message_name (campaign_contact_id,message_name) UNIQUE
# index_campaign_emails_on_contact_id_and_message_name (campaign_contact_id,message_name)
# index_campaign_emails_on_mailgun_message_id (mailgun_message_id) UNIQUE
#
# Foreign Keys
Expand Down
2 changes: 1 addition & 1 deletion spec/models/campaign_email_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# Indexes
#
# index_campaign_emails_on_campaign_contact_id (campaign_contact_id)
# index_campaign_emails_on_contact_id_and_message_name (campaign_contact_id,message_name) UNIQUE
# index_campaign_emails_on_contact_id_and_message_name (campaign_contact_id,message_name)
# index_campaign_emails_on_mailgun_message_id (mailgun_message_id) UNIQUE
#
# Foreign Keys
Expand Down
Loading