Vereinfacht accounting software API closes #431 #432
6 changed files with 98 additions and 11 deletions
|
|
@ -36,3 +36,4 @@ ASSOCIATION_NAME="Sportsclub XYZ"
|
|||
# VEREINFACHT_API_URL=https://api.verein.visuel.dev/api/v1
|
||||
# VEREINFACHT_API_KEY=your-api-key
|
||||
# VEREINFACHT_CLUB_ID=2
|
||||
# VEREINFACHT_APP_URL=https://app.verein.visuel.dev
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ defmodule Mv.Membership.Setting do
|
|||
:default_membership_fee_type_id,
|
||||
:vereinfacht_api_url,
|
||||
:vereinfacht_api_key,
|
||||
:vereinfacht_club_id
|
||||
:vereinfacht_club_id,
|
||||
:vereinfacht_app_url
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -87,7 +88,8 @@ defmodule Mv.Membership.Setting do
|
|||
:default_membership_fee_type_id,
|
||||
:vereinfacht_api_url,
|
||||
:vereinfacht_api_key,
|
||||
:vereinfacht_club_id
|
||||
:vereinfacht_club_id,
|
||||
:vereinfacht_app_url
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -251,6 +253,13 @@ defmodule Mv.Membership.Setting do
|
|||
description "Vereinfacht club ID for multi-tenancy"
|
||||
end
|
||||
|
||||
attribute :vereinfacht_app_url, :string do
|
||||
allow_nil? true
|
||||
public? true
|
||||
|
||||
description "Vereinfacht app base URL for contact view links (e.g. https://app.verein.visuel.dev)"
|
||||
end
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,37 @@ defmodule Mv.Config do
|
|||
env_or_setting("VEREINFACHT_CLUB_ID", :vereinfacht_club_id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the Vereinfacht app base URL for contact view links (frontend, not API).
|
||||
|
||||
Reads from `VEREINFACHT_APP_URL` env first, then from Settings.
|
||||
Used to build links like https://app.verein.visuel.dev/en/admin/finances/contacts/{id}.
|
||||
If not set, derived from API URL by replacing host \"api.\" with \"app.\" when possible.
|
||||
"""
|
||||
@spec vereinfacht_app_url() :: String.t() | nil
|
||||
def vereinfacht_app_url do
|
||||
env_or_setting("VEREINFACHT_APP_URL", :vereinfacht_app_url) ||
|
||||
derive_app_url_from_api_url(vereinfacht_api_url())
|
||||
end
|
||||
|
||||
defp derive_app_url_from_api_url(nil), do: nil
|
||||
|
||||
defp derive_app_url_from_api_url(api_url) when is_binary(api_url) do
|
||||
api_url = String.trim(api_url)
|
||||
uri = URI.parse(api_url)
|
||||
host = uri.host || ""
|
||||
|
||||
if String.starts_with?(host, "api.") do
|
||||
app_host = "app." <> String.slice(host, 4..-1//1)
|
||||
scheme = uri.scheme || "https"
|
||||
"#{scheme}://#{app_host}"
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
defp derive_app_url_from_api_url(_), do: nil
|
||||
|
||||
@doc """
|
||||
Returns true if Vereinfacht is fully configured (URL, API key, and club ID all set).
|
||||
"""
|
||||
|
|
@ -211,6 +242,11 @@ defmodule Mv.Config do
|
|||
"""
|
||||
def vereinfacht_club_id_env_set?, do: env_set?("VEREINFACHT_CLUB_ID")
|
||||
|
||||
@doc """
|
||||
Returns true if VEREINFACHT_APP_URL is set (field is read-only in Settings).
|
||||
"""
|
||||
def vereinfacht_app_url_env_set?, do: env_set?("VEREINFACHT_APP_URL")
|
||||
|
||||
defp env_set?(key) do
|
||||
case System.get_env(key) do
|
||||
nil -> false
|
||||
|
|
@ -241,18 +277,22 @@ defmodule Mv.Config do
|
|||
end
|
||||
|
||||
@doc """
|
||||
Returns the URL to view a finance contact (e.g. in Vereinfacht frontend or API).
|
||||
Returns the URL to view a finance contact in the Vereinfacht app (frontend).
|
||||
|
||||
Uses the configured API base URL and appends /finance-contacts/{id}.
|
||||
Can be extended later with a dedicated frontend URL setting.
|
||||
Uses the configured app base URL (or derived from API URL) and appends
|
||||
/en/admin/finances/contacts/{id}. Returns nil if no app URL can be determined.
|
||||
"""
|
||||
@spec vereinfacht_contact_view_url(String.t()) :: String.t() | nil
|
||||
def vereinfacht_contact_view_url(contact_id) when is_binary(contact_id) do
|
||||
base = vereinfacht_api_url()
|
||||
base = vereinfacht_app_url()
|
||||
|
||||
if present?(base),
|
||||
do: base |> String.trim_trailing("/") |> then(&"#{&1}/finance-contacts/#{contact_id}"),
|
||||
else: nil
|
||||
if present?(base) do
|
||||
base
|
||||
|> String.trim_trailing("/")
|
||||
|> then(&"#{&1}/en/admin/finances/contacts/#{contact_id}")
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
defp present?(nil), do: false
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
|> assign(:vereinfacht_api_url_env_set, Mv.Config.vereinfacht_api_url_env_set?())
|
||||
|> assign(:vereinfacht_api_key_env_set, Mv.Config.vereinfacht_api_key_env_set?())
|
||||
|> assign(:vereinfacht_club_id_env_set, Mv.Config.vereinfacht_club_id_env_set?())
|
||||
|> assign(:vereinfacht_app_url_env_set, Mv.Config.vereinfacht_app_url_env_set?())
|
||||
|> assign(:vereinfacht_api_key_set, present?(settings.vereinfacht_api_key))
|
||||
|> assign(:last_vereinfacht_sync_result, nil)
|
||||
|> assign_form()
|
||||
|
|
@ -142,6 +143,18 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
if(@vereinfacht_club_id_env_set, do: gettext("From VEREINFACHT_CLUB_ID"), else: "2")
|
||||
}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:vereinfacht_app_url]}
|
||||
type="text"
|
||||
label={gettext("App URL (contact view link)")}
|
||||
disabled={@vereinfacht_app_url_env_set}
|
||||
placeholder={
|
||||
if(@vereinfacht_app_url_env_set,
|
||||
do: gettext("From VEREINFACHT_APP_URL"),
|
||||
else: "https://app.verein.visuel.dev"
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<.button
|
||||
:if={
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
defmodule Mv.Repo.Migrations.AddVereinfachtAppUrl do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:settings) do
|
||||
add :vereinfacht_app_url, :text
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:settings) do
|
||||
remove :vereinfacht_app_url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -39,14 +39,23 @@ defmodule Mv.ConfigVereinfachtTest do
|
|||
assert Mv.Config.vereinfacht_contact_view_url("123") == nil
|
||||
end
|
||||
|
||||
test "returns URL when API URL is set" do
|
||||
test "returns app contact view URL when API URL is set (derived app URL)" do
|
||||
set_vereinfacht_env("VEREINFACHT_API_URL", "https://api.example.com/api/v1")
|
||||
|
||||
assert Mv.Config.vereinfacht_contact_view_url("42") ==
|
||||
"https://api.example.com/api/v1/finance-contacts/42"
|
||||
"https://app.example.com/en/admin/finances/contacts/42"
|
||||
after
|
||||
clear_vereinfacht_env()
|
||||
end
|
||||
|
||||
test "returns app contact view URL when VEREINFACHT_APP_URL is set" do
|
||||
set_vereinfacht_env("VEREINFACHT_APP_URL", "https://app.verein.visuel.dev")
|
||||
|
||||
assert Mv.Config.vereinfacht_contact_view_url("abc") ==
|
||||
"https://app.verein.visuel.dev/en/admin/finances/contacts/abc"
|
||||
after
|
||||
System.delete_env("VEREINFACHT_APP_URL")
|
||||
end
|
||||
end
|
||||
|
||||
defp set_vereinfacht_env(key, value) do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue