diff --git a/lib/mix/tasks/store_rates.ex b/lib/mix/tasks/store_rates.ex index a217d72..253af32 100644 --- a/lib/mix/tasks/store_rates.ex +++ b/lib/mix/tasks/store_rates.ex @@ -6,8 +6,7 @@ defmodule Mix.Tasks.StoreRates do alias PrisonRideshare.Repo alias PrisonRideshareWeb.{GasPrice, Ride} alias PrisonRideshare.CalculateRatesFromGasPrice - - alias Timex.Duration + alias PrisonRideshare.Email import Ecto.Query @@ -28,17 +27,30 @@ defmodule Mix.Tasks.StoreRates do gas_prices = Repo.all(GasPrice, order_by: :inserted_at) Enum.each(rides, fn ride -> - window_before_ride_start = Timex.subtract(ride.start, Duration.from_days(1)) - - window_after_ride_start = Timex.add(ride.start, Duration.from_days(1)) + # Choose the nearest gas price by proximity to start time closest_gas_price = - Enum.find(gas_prices, fn gas_price -> - Timex.after?(gas_price.inserted_at, window_before_ride_start) && - Timex.before?(gas_price.inserted_at, window_after_ride_start) - end) + case gas_prices do + [] -> + nil + + _ -> + Enum.min_by(gas_prices, fn gp -> + abs(Timex.diff(gp.inserted_at, ride.start, :seconds)) + end) + end if closest_gas_price do + # send a warning if the assigned gas price is 5 days or more from the ride start + diff_seconds = + Timex.diff(closest_gas_price.inserted_at, ride.start, :seconds) + |> abs() + + if diff_seconds >= 5 * 24 * 60 * 60 do + Email.store_rates_gap_warning_report(ride, closest_gas_price) + |> PrisonRideshare.Mailer.deliver_now() + end + rate = if ride.institution.far, do: CalculateRatesFromGasPrice.far_rate(closest_gas_price), diff --git a/lib/prison_rideshare_web/email.ex b/lib/prison_rideshare_web/email.ex index d4a5345..6304788 100644 --- a/lib/prison_rideshare_web/email.ex +++ b/lib/prison_rideshare_web/email.ex @@ -69,6 +69,34 @@ defmodule PrisonRideshare.Email do ) end + def store_rates_gap_warning_report(ride, gas_price) do + diff_seconds = + Timex.diff(gas_price.inserted_at, ride.start, :seconds) + |> abs() + + gap_days = div(diff_seconds, 86_400) + + body = + [ + "Gas price assignment gap warning: the gas price assigned to a ride is #{gap_days} days apart from the ride start, is archival broken?", + "", + "Ride ID: #{ride.id}", + "Visitor: #{ride.name}", + "Ride start: #{ride.start}", + "Assigned gas price timestamp: #{gas_price.inserted_at}", + "Gap: #{gap_days} days" + ] + |> Enum.join("\n") + + new_email( + to: ["barnone.coordinator+gap+warning@gmail.com", "bot@barnonewpg.org"], + from: {"Bar None Bot", "bot@barnonewpg.org"}, + subject: "Gas price assignment gap warning", + html_body: body, + text_body: body + ) + end + defp format_gas_price_failure_reason(:missing_value), do: "missing pageFunctionResult" defp format_gas_price_failure_reason(:invalid_number), do: "invalid number format" defp format_gas_price_failure_reason(:invalid_format), do: "invalid response format" diff --git a/test/mix/tasks/store_rates_test.exs b/test/mix/tasks/store_rates_test.exs index a66ac31..435b3b9 100644 --- a/test/mix/tasks/store_rates_test.exs +++ b/test/mix/tasks/store_rates_test.exs @@ -1,6 +1,7 @@ defmodule Mix.Tasks.StoreRatesTest do use ExUnit.Case use PrisonRideshareWeb.ConnCase + use Bamboo.Test alias PrisonRideshare.Repo @@ -22,7 +23,7 @@ defmodule Mix.Tasks.StoreRatesTest do inserted_at: NaiveDateTime.from_erl!({{2018, 6, 24}, {16, 37, 0}}) }) - other_price = + ancient_price = Repo.insert!(%GasPrice{ price: 5, inserted_at: NaiveDateTime.from_erl!({{2017, 1, 1}, {0, 0, 0}}) @@ -40,6 +41,16 @@ defmodule Mix.Tasks.StoreRatesTest do far: true }) + _ancient_ride = + Repo.insert!(%Ride{ + start: NaiveDateTime.from_erl!({{2017, 2, 2}, {11, 0, 0}}), + institution: close_institution, + end: NaiveDateTime.from_erl!({{2017, 2, 2}, {12, 0, 0}}), + address: "address", + contact: "contact", + name: "name" + }) + _old_ride = Repo.insert!(%Ride{ start: NaiveDateTime.from_erl!({{2018, 5, 23}, {11, 0, 0}}), @@ -95,7 +106,7 @@ defmodule Mix.Tasks.StoreRatesTest do Repo.insert!(%Ride{ start: NaiveDateTime.from_erl!({{2018, 6, 28}, {11, 0, 0}}), institution: far_institution, - gas_price: other_price, + gas_price: ancient_price, end: NaiveDateTime.from_erl!({{2018, 6, 28}, {12, 0, 0}}), address: "address", contact: "contact", @@ -116,6 +127,7 @@ defmodule Mix.Tasks.StoreRatesTest do Mix.Tasks.StoreRates.run([]) [ + ancient, old, yesterday, zero_rate_ride, @@ -129,7 +141,10 @@ defmodule Mix.Tasks.StoreRatesTest do |> preload(:gas_price) |> Repo.all() - refute old.gas_price + assert ancient.gas_price.id == ancient_price.id + + assert old.gas_price.id == yesterday_price.id + assert old.rate == ~M[23] assert yesterday.gas_price.id == yesterday_price.id assert yesterday.rate == ~M[23] @@ -140,14 +155,24 @@ defmodule Mix.Tasks.StoreRatesTest do assert today.gas_price.id == today_price.id assert today.rate == ~M[20] - refute tomorrow.gas_price + assert tomorrow.gas_price.id == today_price.id + assert tomorrow.rate == ~M[20] - assert already_set_gas_price.gas_price.id == other_price.id + assert already_set_gas_price.gas_price.id == ancient_price.id refute already_set_rate.gas_price - [yesterday_version, _zero_version, _today_version] = Repo.all(PaperTrail.Version) - assert yesterday_version.event == "update" - assert yesterday_version.origin == "StoreRates" - assert yesterday_version.item_id == yesterday.id + ancient_version = hd(Repo.all(PaperTrail.Version)) + + assert ancient_version.event == "update" + assert ancient_version.origin == "StoreRates" + assert ancient_version.item_id == ancient.id + + assert_delivered_email( + PrisonRideshare.Email.store_rates_gap_warning_report(ancient, ancient_price) + ) + + assert_delivered_email( + PrisonRideshare.Email.store_rates_gap_warning_report(old, yesterday_price) + ) end end