defmodule Plausible.Workers.ScheduleEmailReports do use Plausible.Repo use Oban.Worker, queue: :schedule_email_reports alias Plausible.Workers.SendEmailReport require Logger @impl Oban.Worker @doc """ Email reports should be sent on Monday at 9am according to the timezone of a site. """ def perform(_job) do schedule_weekly_emails() schedule_monthly_emails() end defp schedule_weekly_emails() do weekly_jobs = from( j in Oban.Job, where: j.worker == "Plausible.Workers.SendEmailReport" and fragment("(? ->> 'interval')", j.args) == "weekly" ) sites = Repo.all( from s in Plausible.Site, inner_join: t in assoc(s, :team), join: wr in Plausible.Site.WeeklyReport, on: wr.site_id == s.id, left_join: job in subquery(weekly_jobs), on: fragment("(? -> 'site_id')::int", job.args) == s.id and job.state not in ["completed", "discarded"], where: is_nil(job), where: not t.locked, preload: [weekly_report: wr] ) for site <- sites do SendEmailReport.new(%{site_id: site.id, interval: "weekly"}, scheduled_at: monday_9am(site.timezone) ) |> Oban.insert!() end :ok end def monday_9am(timezone) do DateTime.now!(timezone) |> DateTime.shift(week: 1) |> Plausible.Times.beginning_of_week() |> DateTime.shift(hour: 9) end defp schedule_monthly_emails() do monthly_jobs = from( j in Oban.Job, where: j.worker == "Plausible.Workers.SendEmailReport" and fragment("(? ->> 'interval')", j.args) == "monthly" ) sites = Repo.all( from s in Plausible.Site, inner_join: t in assoc(s, :team), join: mr in Plausible.Site.MonthlyReport, on: mr.site_id == s.id, left_join: job in subquery(monthly_jobs), on: fragment("(? -> 'site_id')::int", job.args) == s.id and job.state not in ["completed", "discarded"], where: is_nil(job), where: not t.locked, preload: [monthly_report: mr] ) for site <- sites do SendEmailReport.new(%{site_id: site.id, interval: "monthly"}, scheduled_at: first_of_month_9am(site.timezone) ) |> Oban.insert!() end :ok end def first_of_month_9am(timezone) do DateTime.now!(timezone) |> DateTime.shift(month: 1) |> Plausible.Times.beginning_of_month() |> DateTime.shift(hour: 9) end end