lib/openagents/box/usage.ex

main at 58e6347eeb72 · 1 KB

defmodule OpenAgents.Box.Usage do
  @moduledoc "Aggregated accumulated Box lifetime and settled cost."

  import Ecto.Query

  alias OpenAgents.Box.ConversationBox
  alias OpenAgents.Conversations.Conversation
  alias OpenAgents.Repo

  @spec for_conversation(String.t()) :: map()
  def for_conversation(conversation_id) when is_binary(conversation_id) do
    aggregate(from box in ConversationBox, where: box.conversation_id == ^conversation_id)
  end

  @spec for_owner(String.t()) :: map()
  def for_owner(owner_id) when is_binary(owner_id) do
    aggregate(
      from box in ConversationBox,
        join: conversation in Conversation,
        on: conversation.id == box.conversation_id,
        join: visitor in assoc(conversation, :visitor),
        where: visitor.user_id == ^owner_id
    )
  end

  defp aggregate(query) do
    {lifetime_seconds, settled_cost_microusd, boxes} =
      Repo.one(
        from box in query,
          select: {
            coalesce(sum(box.lifetime_seconds), 0),
            coalesce(sum(box.settled_cost_microusd), 0),
            count(box.id)
          }
      )

    %{
      lifetime_seconds: integer_value(lifetime_seconds),
      settled_cost_microusd: integer_value(settled_cost_microusd),
      boxes: boxes
    }
  end

  defp integer_value(%Decimal{} = value), do: Decimal.to_integer(value)
  defp integer_value(value), do: value
end