defmodule Glific.Seeds.SeedsStats do
@moduledoc """
One shot migration of data to seed the stats table
"""
alias Glific.{Repo, Stats, Stats.Stat}
@doc """
Run the migration to populate the stats table for all active organizations
"""
@spec seed_stats(list()) :: nil
def seed_stats(org_id_list) do
from_day = Timex.parse!("2021-03-01T00:00:00+00:00", "{ISO:Extended}")
from_week = Timex.parse!("2021-01-04T00:00:00+00:00", "{ISO:Extended}")
from_month = Timex.parse!("2020-06-01T00:00:00+00:00", "{ISO:Extended}")
to =
DateTime.utc_now()
|> Timex.beginning_of_day()
rows =
%{}
|> seed_daily(org_id_list, from_day, to)
|> seed_weekly(org_id_list, from_week, to)
|> seed_monthly(org_id_list, from_month, to)
|> Stats.reject_empty()
Repo.insert_all(Stat, rows)
nil
end
@doc false
@spec seed_monthly(map(), list(), DateTime.t(), DateTime.t()) :: map()
defp seed_monthly(stats, org_id_list, from, to) do
start = Timex.end_of_month(from)
# we only compute till the end of the previous month
finish = next_month(to, -1)
do_seed_monthly(stats, org_id_list, start, finish)
end
@spec do_seed_monthly(map(), list(), DateTime.t(), DateTime.t()) :: map()
defp do_seed_monthly(stats, org_id_list, current, finish) do
if DateTime.compare(current, finish) == :gt do
stats
else
stats
|> Stats.get_monthly_stats(org_id_list, time: current, summary: false)
|> do_seed_monthly(org_id_list, next_month(current), finish)
end
end
@spec next_month(DateTime.t(), integer) :: DateTime.t()
defp next_month(time, offset \\ 1),
do:
time
|> Timex.shift(months: offset)
|> Timex.end_of_month()
@doc false
@spec seed_daily(map(), list(), DateTime.t(), DateTime.t()) :: map()
defp seed_daily(stats, org_id_list, from, to) do
start = Timex.end_of_day(from)
do_seed_daily(stats, org_id_list, start, to)
end
@spec do_seed_daily(map(), list(), DateTime.t(), DateTime.t()) :: map()
defp do_seed_daily(stats, org_id_list, current, finish) do
if DateTime.compare(current, finish) == :gt do
stats
else
stats
|> Stats.get_daily_stats(org_id_list, time: current)
|> do_seed_daily(org_id_list, Timex.shift(current, days: 1), finish)
end
end
@doc false
@spec seed_weekly(map(), list(), DateTime.t(), DateTime.t()) :: map()
defp seed_weekly(stats, org_id_list, from, to) do
start = Timex.end_of_week(from)
# go back to the previous week
finish = Timex.end_of_week(Timex.shift(to, days: -7))
do_seed_weekly(stats, org_id_list, start, finish)
end
@spec do_seed_weekly(map(), list(), DateTime.t(), DateTime.t()) :: map()
defp do_seed_weekly(stats, org_id_list, current, finish) do
if DateTime.compare(current, finish) == :gt do
stats
else
stats
|> Stats.get_weekly_stats(org_id_list, time: current, summary: false)
|> do_seed_weekly(org_id_list, Timex.shift(current, days: 7), finish)
end
end
end