mirror of
https://github.com/plausible/analytics.git
synced 2024-10-26 10:22:34 +03:00
Revenue tracking: Add currency field to goal creation (#2948)
* Add revenue goal option to goal creation This commit adds a currency field to the goals form. Goals that have a currency set are now revenue goals, and are cached with sites to later be used during ingestion. Co-authored-by: Robert Joonas <robertjoonas16@gmail.com> * Enable feature flag in tests --------- Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
This commit is contained in:
parent
3a07487c05
commit
10d9e3b083
@ -54,4 +54,8 @@ config :plausible,
|
||||
|
||||
config :plausible, Plausible.Ingestion.Counters, enabled: true
|
||||
|
||||
config :ex_cldr,
|
||||
default_locale: "en",
|
||||
default_backend: Plausible.Cldr
|
||||
|
||||
import_config "#{config_env()}.exs"
|
||||
|
@ -320,6 +320,9 @@ config :plausible, Plausible.ImportDeletionRepo,
|
||||
transport_opts: ch_transport_opts,
|
||||
pool_size: 1
|
||||
|
||||
config :ex_money,
|
||||
open_exchange_rates_app_id: get_var_from_path_or_env(config_dir, "OPEN_EXCHANGE_RATES_APP_ID")
|
||||
|
||||
case mailer_adapter do
|
||||
"Bamboo.PostmarkAdapter" ->
|
||||
config :plausible, Plausible.Mailer,
|
||||
|
@ -29,4 +29,6 @@ config :plausible,
|
||||
http_impl: Plausible.HTTPClient.Mock,
|
||||
sites_by_domain_cache_enabled: false
|
||||
|
||||
config :ex_money, api_module: Plausible.ExchangeRateMock
|
||||
|
||||
config :plausible, Plausible.Ingestion.Counters, enabled: false
|
||||
|
5
lib/plausible/cldr.ex
Normal file
5
lib/plausible/cldr.ex
Normal file
@ -0,0 +1,5 @@
|
||||
defmodule Plausible.Cldr do
|
||||
@moduledoc false
|
||||
|
||||
use Cldr, locales: ["en"], providers: [Cldr.Number]
|
||||
end
|
@ -24,20 +24,40 @@ defmodule Plausible.Goal do
|
||||
field :event_name, :string
|
||||
field :page_path, :string
|
||||
|
||||
field :currency, Ecto.Enum, values: Money.Currency.known_current_currencies()
|
||||
|
||||
belongs_to :site, Plausible.Site
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
def revenue?(%__MODULE__{currency: currency}) do
|
||||
!!currency
|
||||
end
|
||||
|
||||
def valid_currencies do
|
||||
Ecto.Enum.dump_values(__MODULE__, :currency)
|
||||
end
|
||||
|
||||
def currency_options do
|
||||
options =
|
||||
for code <- valid_currencies() do
|
||||
{"#{code} - #{Cldr.Currency.display_name!(code)}", code}
|
||||
end
|
||||
|
||||
[{"", nil}] ++ options
|
||||
end
|
||||
|
||||
def changeset(goal, attrs \\ %{}) do
|
||||
goal
|
||||
|> cast(attrs, [:site_id, :event_name, :page_path])
|
||||
|> cast(attrs, [:site_id, :event_name, :page_path, :currency])
|
||||
|> validate_required([:site_id])
|
||||
|> cast_assoc(:site)
|
||||
|> validate_event_name_and_page_path()
|
||||
|> update_change(:event_name, &String.trim/1)
|
||||
|> update_change(:page_path, &String.trim/1)
|
||||
|> validate_length(:event_name, max: 120)
|
||||
|> maybe_drop_currency()
|
||||
end
|
||||
|
||||
defp validate_event_name_and_page_path(changeset) do
|
||||
@ -59,4 +79,12 @@ defmodule Plausible.Goal do
|
||||
value = get_field(changeset, :event_name)
|
||||
value && String.match?(value, ~r/^.+/)
|
||||
end
|
||||
|
||||
defp maybe_drop_currency(changeset) do
|
||||
if get_field(changeset, :page_path) do
|
||||
delete_change(changeset, :currency)
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -31,6 +31,7 @@ defmodule Plausible.Site do
|
||||
many_to_many :members, User, join_through: Plausible.Site.Membership
|
||||
has_many :memberships, Plausible.Site.Membership
|
||||
has_many :invitations, Plausible.Auth.Invitation
|
||||
has_many :revenue_goals, Plausible.Goal, where: [currency: {:not, nil}]
|
||||
has_one :google_auth, GoogleAuth
|
||||
has_one :weekly_report, Plausible.Site.WeeklyReport
|
||||
has_one :monthly_report, Plausible.Site.MonthlyReport
|
||||
|
@ -51,11 +51,11 @@ defmodule Plausible.Site.Cache do
|
||||
@modes [:all, :updated_recently]
|
||||
|
||||
@cached_schema_fields ~w(
|
||||
id
|
||||
domain
|
||||
domain_changed_from
|
||||
ingest_rate_limit_scale_seconds
|
||||
ingest_rate_limit_threshold
|
||||
id
|
||||
domain
|
||||
domain_changed_from
|
||||
ingest_rate_limit_scale_seconds
|
||||
ingest_rate_limit_threshold
|
||||
)a
|
||||
|
||||
@type t() :: Site.t()
|
||||
@ -92,17 +92,9 @@ defmodule Plausible.Site.Cache do
|
||||
|
||||
@spec refresh_all(Keyword.t()) :: :ok
|
||||
def refresh_all(opts \\ []) do
|
||||
sites_by_domain_query =
|
||||
from s in Site,
|
||||
select: {
|
||||
s.domain,
|
||||
s.domain_changed_from,
|
||||
%{struct(s, ^@cached_schema_fields) | from_cache?: true}
|
||||
}
|
||||
|
||||
refresh(
|
||||
:all,
|
||||
sites_by_domain_query,
|
||||
sites_by_domain_query(),
|
||||
Keyword.put(opts, :delete_stale_items?, true)
|
||||
)
|
||||
end
|
||||
@ -110,14 +102,9 @@ defmodule Plausible.Site.Cache do
|
||||
@spec refresh_updated_recently(Keyword.t()) :: :ok
|
||||
def refresh_updated_recently(opts \\ []) do
|
||||
recently_updated_sites_query =
|
||||
from s in Site,
|
||||
from [s, mg] in sites_by_domain_query(),
|
||||
order_by: [asc: s.updated_at],
|
||||
where: s.updated_at > ago(^15, "minute"),
|
||||
select: {
|
||||
s.domain,
|
||||
s.domain_changed_from,
|
||||
%{struct(s, ^@cached_schema_fields) | from_cache?: true}
|
||||
}
|
||||
where: s.updated_at > ago(^15, "minute") or mg.updated_at > ago(^15, "minute")
|
||||
|
||||
refresh(
|
||||
:updated_recently,
|
||||
@ -126,6 +113,17 @@ defmodule Plausible.Site.Cache do
|
||||
)
|
||||
end
|
||||
|
||||
defp sites_by_domain_query do
|
||||
from s in Site,
|
||||
left_join: mg in assoc(s, :revenue_goals),
|
||||
select: {
|
||||
s.domain,
|
||||
s.domain_changed_from,
|
||||
%{struct(s, ^@cached_schema_fields) | from_cache?: true}
|
||||
},
|
||||
preload: [revenue_goals: mg]
|
||||
end
|
||||
|
||||
@spec merge(new_items :: [Site.t()], opts :: Keyword.t()) :: :ok
|
||||
def merge(new_items, opts \\ [])
|
||||
def merge([], _), do: :ok
|
||||
@ -182,7 +180,16 @@ defmodule Plausible.Site.Cache do
|
||||
nil
|
||||
end
|
||||
else
|
||||
Plausible.Sites.get_by_domain(domain)
|
||||
get_from_source(domain)
|
||||
end
|
||||
end
|
||||
|
||||
defp get_from_source(domain) do
|
||||
query = from s in sites_by_domain_query(), where: s.domain == ^domain
|
||||
|
||||
case Plausible.Repo.one(query) do
|
||||
{_, _, site} -> %Site{site | from_cache?: false}
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -7,9 +7,19 @@
|
||||
</div>
|
||||
<div class="my-6">
|
||||
<div id="event-fields">
|
||||
<%= label f, :event_name, class: "block text-sm font-bold dark:text-gray-100" %>
|
||||
<%= text_input f, :event_name, class: "transition mt-3 bg-gray-100 dark:bg-gray-900 outline-none appearance-none border border-transparent rounded w-full p-2 text-gray-700 dark:text-gray-300 leading-normal focus:outline-none focus:bg-white dark:focus:bg-gray-800 focus:border-gray-300 dark:focus:border-gray-500", placeholder: "Signup" %>
|
||||
<%= error_tag f, :event_name %>
|
||||
<div>
|
||||
<%= label f, :event_name, class: "block text-sm font-bold dark:text-gray-100" %>
|
||||
<%= text_input f, :event_name, class: "transition mt-3 bg-gray-100 dark:bg-gray-900 outline-none appearance-none border border-transparent rounded w-full p-2 text-gray-700 dark:text-gray-300 leading-normal focus:outline-none focus:bg-white dark:focus:bg-gray-800 focus:border-gray-300 dark:focus:border-gray-500", placeholder: "Signup" %>
|
||||
<%= error_tag f, :event_name %>
|
||||
</div>
|
||||
|
||||
<%= if FunWithFlags.enabled?(:revenue_goals, for: @current_user) do %>
|
||||
<div class="mt-3">
|
||||
<%= label f, :currency, "Reporting currency for revenue tracking (optional)", class: "block text-sm font-bold dark:text-gray-100" %>
|
||||
<%= select f, :currency, Plausible.Goal.currency_options(), class: "transition mt-3 bg-gray-100 dark:bg-gray-900 outline-none appearance-none border border-transparent rounded w-full p-2 text-gray-700 dark:text-gray-300 leading-normal focus:outline-none focus:bg-white dark:focus:bg-gray-800 focus:border-gray-300 dark:focus:border-gray-500" %>
|
||||
<%= error_tag f, :currency %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div id="pageview-fields" class="hidden">
|
||||
<%= label f, :page_path, class: "block text-sm font-bold dark:text-gray-100" %>
|
||||
|
3
mix.exs
3
mix.exs
@ -116,7 +116,8 @@ defmodule Plausible.MixProject do
|
||||
{:siphash, "~> 3.2"},
|
||||
{:timex, "~> 3.7"},
|
||||
{:ua_inspector, "~> 3.0"},
|
||||
{:ex_doc, "~> 0.28", only: :dev, runtime: false}
|
||||
{:ex_doc, "~> 0.28", only: :dev, runtime: false},
|
||||
{:ex_money, "~> 5.12"}
|
||||
]
|
||||
end
|
||||
|
||||
|
6
mix.lock
6
mix.lock
@ -13,6 +13,7 @@
|
||||
"ch": {:git, "https://github.com/plausible/ch.git", "f411daa07c6310d3308f81397905df65330aeb64", []},
|
||||
"chatterbox": {:hex, :ts_chatterbox, "0.13.0", "6f059d97bcaa758b8ea6fffe2b3b81362bd06b639d3ea2bb088335511d691ebf", [:rebar3], [{:hpack, "~> 0.2.3", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "b93d19104d86af0b3f2566c4cba2a57d2e06d103728246ba1ac6c3c0ff010aa7"},
|
||||
"chto": {:git, "https://github.com/plausible/chto.git", "6afe76281e617c19df9b7a705c8401f604fe091f", []},
|
||||
"cldr_utils": {:hex, :cldr_utils, "2.22.0", "5df60df2603dfeeffe26e40ab1ee565df34da288a53bb2db0d0dbd243fd646ef", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "ea14e8a6aa89ffd59a5d49baebe7ebf852cc024ac50dc2b3dabcd3786eeed657"},
|
||||
"combination": {:hex, :combination, "0.0.3", "746aedca63d833293ec6e835aa1f34974868829b1486b1e1cb0685f0b2ae1f41", [:mix], [], "hexpm", "72b099f463df42ef7dc6371d250c7070b57b6c5902853f69deb894f79eda18ca"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
|
||||
@ -27,6 +28,7 @@
|
||||
"db_connection": {:hex, :db_connection, "2.5.0", "bb6d4f30d35ded97b29fe80d8bd6f928a1912ca1ff110831edcd238a1973652c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c92d5ba26cd69ead1ff7582dbb860adeedfff39774105a4f1c92cbb654b55aa2"},
|
||||
"decimal": {:hex, :decimal, "2.1.0", "4a607736e18d9a77ea44fa18388bf43bb7f7df70ff2e0d23d4238f9d18a3ad7d", [:mix], [], "hexpm", "6396853b6b4bf8b1ff2c2217121f1fad4a1aff999014a10fba60e6009194f91b"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
|
||||
"digital_token": {:hex, :digital_token, "0.4.0", "2ad6894d4a40be8b2890aad286ecd5745fa473fa5699d80361a8c94428edcd1f", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "a178edf61d1fee5bb3c34e14b0f4ee21809ee87cade8738f87337e59e5e66e26"},
|
||||
"double": {:hex, :double, "0.8.2", "8e1cfcccdaef76c18846bc08e555555a2a699b806fa207b6468572a60513cc6a", [:mix], [], "hexpm", "90287642b2ec86125e0457aaba2ab0e80f7d7050cc80a0cef733e59bd70aa67c"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.31", "a93921cdc6b9b869f519213d5bc79d9e218ba768d7270d46fdcf1c01bacff9e2", [:mix], [], "hexpm", "317d367ee0335ef037a87e46c91a2269fef6306413f731e8ec11fc45a7efd059"},
|
||||
"ecto": {:hex, :ecto, "3.9.5", "9f0aa7ae44a1577b651c98791c6988cd1b69b21bc724e3fd67090b97f7604263", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d4f3115d8cbacdc0bfa4b742865459fb1371d0715515842a1fb17fe31920b74c"},
|
||||
@ -35,8 +37,12 @@
|
||||
"envy": {:hex, :envy, "1.1.1", "0bc9bd654dec24fcdf203f7c5aa1b8f30620f12cfb28c589d5e9c38fe1b07475", [:mix], [], "hexpm", "7061eb1a47415fd757145d8dec10dc0b1e48344960265cb108f194c4252c3a89"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"},
|
||||
"ex_cldr": {:hex, :ex_cldr, "2.36.0", "ccd7c61c4126aa42d3cd9d93097642930f1b8a10c9c8351fc58bb2c627bad839", [:mix], [{:cldr_utils, "~> 2.21", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.19", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: true]}], "hexpm", "5a56c66cd61ebde42277baa828cd1587959b781ac7e2aee135328a78a4de3fe9"},
|
||||
"ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.15.0", "aadd34e91cfac7ef6b03fe8f47f8c6fa8c5daf3f89b5d9fee64ec545ded839cf", [:mix], [{:ex_cldr, "~> 2.34", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "0521316396c66877a2d636219767560bb2397c583341fcb154ecf9f3000e6ff8"},
|
||||
"ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.30.1", "9acd7adb30079057ba606d73ffdaccb86020b07b734f98a229b5674032181668", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.35", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, ">= 2.14.2", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "8a81b63d595a589e72c8b629653755c8b88edd6405a657eba236477f7a85939a"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"},
|
||||
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
|
||||
"ex_money": {:hex, :ex_money, "5.12.4", "2c9778ccac56eb16796dac4cebc02eb7d093639aed08c904444a8d9fa7e69e29", [:mix], [{:cldr_utils, "~> 2.21", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.27", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:gringotts, "~> 1.1", [hex: :gringotts, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.0 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "2b7977fb58af4f79bb7861741314b26b954b8e4d771471490ad68942fcd11619"},
|
||||
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm", "1222419f706e01bfa1095aec9acf6421367dcfab798a6f67c54cf784733cd6b5"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.14.4", "295498f1ae47bdc6dce59af9a585c381e1aefc63298d48172efaaa90c3d251db", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e3ab02f2df4c1c7a519728a6f0a747e71d7d6e846020aae338173619217931c1"},
|
||||
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},
|
||||
|
@ -1,7 +1,7 @@
|
||||
defmodule Plausible.Site.CacheTest do
|
||||
use Plausible.DataCase, async: true
|
||||
|
||||
alias Plausible.Site
|
||||
alias Plausible.{Site, Goal}
|
||||
alias Plausible.Site.Cache
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
@ -53,6 +53,31 @@ defmodule Plausible.Site.CacheTest do
|
||||
refute Cache.get("site3.example.com", cache_name: test, force?: true)
|
||||
end
|
||||
|
||||
test "cache caches revenue goals", %{test: test} do
|
||||
{:ok, _} =
|
||||
Supervisor.start_link([{Cache, [cache_name: test, child_id: :test_cache_caches_id]}],
|
||||
strategy: :one_for_one,
|
||||
name: Test.Supervisor.Cache
|
||||
)
|
||||
|
||||
%{id: site_id} = site = insert(:site, domain: "site1.example.com")
|
||||
insert(:goal, site: site, event_name: "Purchase", currency: :BRL)
|
||||
insert(:goal, site: site, event_name: "Add to Cart", currency: :USD)
|
||||
insert(:goal, site: site, event_name: "Click", currency: nil)
|
||||
|
||||
:ok = Cache.refresh_all(cache_name: test)
|
||||
|
||||
{:ok, _} = Plausible.Repo.delete(site)
|
||||
|
||||
assert %Site{from_cache?: true, id: ^site_id, revenue_goals: cached_goals} =
|
||||
Cache.get("site1.example.com", force?: true, cache_name: test)
|
||||
|
||||
assert [
|
||||
%Goal{event_name: "Add to Cart", currency: :USD},
|
||||
%Goal{event_name: "Purchase", currency: :BRL}
|
||||
] = Enum.sort_by(cached_goals, & &1.event_name)
|
||||
end
|
||||
|
||||
test "cache is ready when no sites exist in the db", %{test: test} do
|
||||
{:ok, _} = start_test_cache(test)
|
||||
assert Cache.ready?(test)
|
||||
|
@ -658,6 +658,62 @@ defmodule PlausibleWeb.SiteControllerTest do
|
||||
assert goal.page_path == nil
|
||||
assert redirected_to(conn, 302) == "/#{site.domain}/settings/goals"
|
||||
end
|
||||
|
||||
test "creates a custom event goal with a revenue value", %{conn: conn, site: site} do
|
||||
conn =
|
||||
post(conn, "/#{site.domain}/goals", %{
|
||||
goal: %{
|
||||
page_path: "",
|
||||
event_name: "Purchase",
|
||||
currency: "EUR"
|
||||
}
|
||||
})
|
||||
|
||||
goal = Repo.get_by(Plausible.Goal, site_id: site.id)
|
||||
|
||||
assert goal.event_name == "Purchase"
|
||||
assert goal.page_path == nil
|
||||
assert goal.currency == :EUR
|
||||
|
||||
assert redirected_to(conn, 302) == "/#{site.domain}/settings/goals"
|
||||
end
|
||||
|
||||
test "fails to create a custom event goal with a non-existant currency", %{
|
||||
conn: conn,
|
||||
site: site
|
||||
} do
|
||||
conn =
|
||||
post(conn, "/#{site.domain}/goals", %{
|
||||
goal: %{
|
||||
page_path: "",
|
||||
event_name: "Purchase",
|
||||
currency: "EEEE"
|
||||
}
|
||||
})
|
||||
|
||||
refute Repo.get_by(Plausible.Goal, site_id: site.id)
|
||||
|
||||
assert html_response(conn, 200) =~ "is invalid"
|
||||
end
|
||||
|
||||
test "Cleans currency for pageview goal creation", %{conn: conn, site: site} do
|
||||
conn =
|
||||
post(conn, "/#{site.domain}/goals", %{
|
||||
goal: %{
|
||||
page_path: "/purchase",
|
||||
event_name: "",
|
||||
currency: "EUR"
|
||||
}
|
||||
})
|
||||
|
||||
goal = Repo.get_by(Plausible.Goal, site_id: site.id)
|
||||
|
||||
assert goal.event_name == nil
|
||||
assert goal.page_path == "/purchase"
|
||||
assert goal.currency == nil
|
||||
|
||||
assert redirected_to(conn, 302) == "/#{site.domain}/settings/goals"
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /:website/goals/:id" do
|
||||
|
20
test/support/exchange_rate_mock.ex
Normal file
20
test/support/exchange_rate_mock.ex
Normal file
@ -0,0 +1,20 @@
|
||||
defmodule Plausible.ExchangeRateMock do
|
||||
@moduledoc false
|
||||
@behaviour Money.ExchangeRates
|
||||
|
||||
def init(config) do
|
||||
config
|
||||
end
|
||||
|
||||
def decode_rates(rates) do
|
||||
Money.ExchangeRates.OpenExchangeRates.decode_rates(rates)
|
||||
end
|
||||
|
||||
def get_latest_rates(_config) do
|
||||
{:ok, %{BRL: Decimal.new("0.7"), EUR: Decimal.new("1.2"), USD: Decimal.new(1)}}
|
||||
end
|
||||
|
||||
def get_historic_rates(_date, _config) do
|
||||
{:ok, %{BRL: Decimal.new("0.8"), EUR: Decimal.new("1.3"), USD: Decimal.new(2)}}
|
||||
end
|
||||
end
|
@ -1,5 +1,6 @@
|
||||
{:ok, _} = Application.ensure_all_started(:ex_machina)
|
||||
Mox.defmock(Plausible.HTTPClient.Mock, for: Plausible.HTTPClient.Interface)
|
||||
Application.ensure_all_started(:double)
|
||||
FunWithFlags.enable(:revenue_goals)
|
||||
Ecto.Adapters.SQL.Sandbox.mode(Plausible.Repo, :manual)
|
||||
ExUnit.configure(exclude: [:slow])
|
||||
|
Loading…
Reference in New Issue
Block a user