diff --git a/lib/workers/notify_annual_renewal.ex b/lib/workers/notify_annual_renewal.ex index 7c89e23a1..d5a66fbe8 100644 --- a/lib/workers/notify_annual_renewal.ex +++ b/lib/workers/notify_annual_renewal.ex @@ -9,19 +9,30 @@ defmodule Plausible.Workers.NotifyAnnualRenewal do Sends a notification at most 7 days and at least 1 day before the renewal of an annual subscription """ def perform(_job) do + current_subscriptions = from( + s in Plausible.Billing.Subscription, + group_by: s.user_id, + select: %{ + user_id: s.user_id, + inserted_at: max(s.inserted_at) + } + ) + users = Repo.all( from u in Plausible.Auth.User, - join: s in Plausible.Billing.Subscription, - on: s.user_id == u.id, - left_join: sent in "sent_renewal_notifications", - on: s.user_id == sent.user_id, - where: s.paddle_plan_id in @yearly_plans, - where: - s.next_bill_date > fragment("now()::date") and - s.next_bill_date <= fragment("now()::date + INTERVAL '7 days'"), - where: is_nil(sent.id) or sent.timestamp < fragment("now() - INTERVAL '1 month'"), - preload: [subscription: s] + join: cs in subquery(current_subscriptions), + on: cs.user_id == u.id, + join: s in Plausible.Billing.Subscription, + on: s.inserted_at == cs.inserted_at, + left_join: sent in "sent_renewal_notifications", + on: s.user_id == sent.user_id, + where: s.paddle_plan_id in @yearly_plans, + where: + s.next_bill_date > fragment("now()::date") and + s.next_bill_date <= fragment("now()::date + INTERVAL '7 days'"), + where: is_nil(sent.id) or sent.timestamp < fragment("now() - INTERVAL '1 month'"), + preload: [subscription: s] ) for user <- users do diff --git a/test/workers/notify_annual_renewal_test.exs b/test/workers/notify_annual_renewal_test.exs index 3c0b0fedc..847ffec54 100644 --- a/test/workers/notify_annual_renewal_test.exs +++ b/test/workers/notify_annual_renewal_test.exs @@ -39,6 +39,26 @@ defmodule Plausible.Workers.NotifyAnnualRenewalTest do assert_no_emails_delivered() end + test "ignores user with old yearly subscription that's been superseded by a newer one", %{user: user} do + insert(:subscription, + inserted_at: Timex.shift(Timex.now(), days: -1), + user: user, + paddle_plan_id: @yearly_plan, + next_bill_date: Timex.shift(Timex.today(), days: 5) + ) + + insert(:subscription, + inserted_at: Timex.now(), + user: user, + paddle_plan_id: @yearly_plan, + next_bill_date: Timex.shift(Timex.today(), days: 30) + ) + + NotifyAnnualRenewal.perform(nil) + + assert_no_emails_delivered() + end + test "sends renewal notification to user whose subscription is due for renewal in 7 days", %{ user: user } do