diff --git a/lib/chargebeex/builder.ex b/lib/chargebeex/builder.ex index 75949e6..42b37d0 100644 --- a/lib/chargebeex/builder.ex +++ b/lib/chargebeex/builder.ex @@ -12,6 +12,7 @@ defmodule Chargebeex.Builder do PaymentSource, PortalSession, Subscription, + SubscriptionEntitlement, Item, ItemPrice, Quote, @@ -50,6 +51,9 @@ defmodule Chargebeex.Builder do def build_resource(%{"usage" => params}), do: Usage.build(params) def build_resource(%{"attached_item" => params}), do: AttachedItem.build(params) + def build_resource(%{"subscription_entitlement" => params}), + do: SubscriptionEntitlement.build(params) + def build_resource("subscription", params), do: Subscription.build(params) def build_resource("customer", params), do: Customer.build(params) def build_resource("portal_session", params), do: PortalSession.build(params) @@ -67,5 +71,8 @@ defmodule Chargebeex.Builder do def build_resource("usage", params), do: Usage.build(params) def build_resource("attached_item", params), do: AttachedItem.build(params) + def build_resource("subscription_entitlement", params), + do: SubscriptionEntitlement.build(params) + def build_resource(_resource, params), do: params end diff --git a/lib/chargebeex/subscription_entitlement/subscription_entitlement.ex b/lib/chargebeex/subscription_entitlement/subscription_entitlement.ex new file mode 100644 index 0000000..8544b3d --- /dev/null +++ b/lib/chargebeex/subscription_entitlement/subscription_entitlement.ex @@ -0,0 +1,51 @@ +defmodule Chargebeex.SubscriptionEntitlement do + use TypedStruct + + @resource "subscription_entitlement" + use Chargebeex.Resource, resource: @resource, only: [] + + @moduledoc """ + Struct that represent a Chargebee's API subscription entitlement resource. + """ + + @typedoc """ + "switch" | "custom" | "quantity" | "range" + """ + @type feature_type :: String.t() + + typedstruct do + field :subscription_id, String.t() + field :feature_id, String.t() + field :feature_name, String.t() + field :feature_type, feature_type() + field :value, String.t() + field :name, String.t() + field :is_overridden, boolean() + field :is_enabled, boolean() + field :object, String.t() + end + + use ExConstructor, :build + + @doc """ + Allows to list Subscription Entitlements + + Available filters can be found here: https://apidocs.chargebee.com/docs/api/subscription_entitlements#list_subscription_entitlements + + ## Examples + + iex> filters = %{limit: 2} + iex(2)> Chargebeex.SubscriptionEntitlement.list(filters) + {:ok, [%Chargebeex.SubscriptionEntitlement{...}, %Chargebeex.SubscriptionEntitlement{...}], %{"next_offset" => nil}} + """ + def list(subscription_id, params \\ %{}, opts \\ []) do + nested_generic_action_without_id( + :get, + [subscription: subscription_id], + @resource, + "subscription_entitlements", + params, + opts + ) + end +end diff --git a/mix.exs b/mix.exs index 27af8d4..1f3691c 100644 --- a/mix.exs +++ b/mix.exs @@ -78,6 +78,7 @@ defmodule Chargebeex.MixProject do Chargebeex.Invoice, Chargebeex.PortalSession, Chargebeex.Subscription, + Chargebeex.SubscriptionEntitlement, Chargebeex.Quote, Chargebeex.HostedPage, Chargebeex.ItemPrice, diff --git a/test/chargebeex/builder/subscription_entitlement_test.exs b/test/chargebeex/builder/subscription_entitlement_test.exs new file mode 100644 index 0000000..eefc222 --- /dev/null +++ b/test/chargebeex/builder/subscription_entitlement_test.exs @@ -0,0 +1,38 @@ +defmodule Chargebeex.Builder.SubscriptionEntitlementTest do + use ExUnit.Case, async: true + + alias Chargebeex.Builder + alias Chargebeex.Fixtures.SubscriptionEntitlement, as: SubscriptionEntitlementFixture + alias Chargebeex.SubscriptionEntitlement + + describe "build/1" do + test "should build an subscription_entitlement" do + builded = + SubscriptionEntitlementFixture.retrieve() + |> Jason.decode!() + |> Builder.build() + + assert %{"subscription_entitlement" => %SubscriptionEntitlement{}} = builded + end + + test "should have the subscription_entitlement params" do + subscription_entitlement = + SubscriptionEntitlementFixture.retrieve() + |> Jason.decode!() + |> Builder.build() + |> Map.get("subscription_entitlement") + + params = SubscriptionEntitlementFixture.subscription_entitlement_params() |> Jason.decode!() + + assert subscription_entitlement.subscription_id == Map.get(params, "subscription_id") + assert subscription_entitlement.feature_id == Map.get(params, "feature_id") + assert subscription_entitlement.feature_name == Map.get(params, "feature_name") + assert subscription_entitlement.feature_type == Map.get(params, "feature_type") + assert subscription_entitlement.value == Map.get(params, "value") + assert subscription_entitlement.name == Map.get(params, "name") + assert subscription_entitlement.is_overridden == Map.get(params, "is_overridden") + assert subscription_entitlement.is_enabled == Map.get(params, "is_enabled") + assert subscription_entitlement.object == Map.get(params, "object") + end + end +end diff --git a/test/chargebeex/subscription_entitlement_test.exs b/test/chargebeex/subscription_entitlement_test.exs new file mode 100644 index 0000000..f3cb537 --- /dev/null +++ b/test/chargebeex/subscription_entitlement_test.exs @@ -0,0 +1,82 @@ +defmodule Chargebeex.SubscriptionEntitlementTest do + use ExUnit.Case, async: true + + import Hammox + + alias Chargebeex.Fixtures.Common + alias Chargebeex.SubscriptionEntitlement + + setup :verify_on_exit! + + describe "list" do + test "with bad authentication should fail" do + unauthorized = Common.unauthorized() + + expect( + Chargebeex.HTTPClientMock, + :get, + fn url, body, headers -> + assert url == + "https://test-namespace.chargebee.com/api/v2/subscriptions/subscription_id/subscription_entitlements" + + assert headers == [{"Authorization", "Basic dGVzdF9jaGFyZ2VlYmVlX2FwaV9rZXk6"}] + assert body == "" + + {:ok, 401, [], Jason.encode!(unauthorized)} + end + ) + + assert {:error, 401, [], ^unauthorized} = SubscriptionEntitlement.list("subscription_id") + end + + test "with no param, no offset should succeed" do + expect( + Chargebeex.HTTPClientMock, + :get, + fn url, body, headers -> + assert url == + "https://test-namespace.chargebee.com/api/v2/subscriptions/subscription_id/subscription_entitlements" + + assert headers == [{"Authorization", "Basic dGVzdF9jaGFyZ2VlYmVlX2FwaV9rZXk6"}] + assert body == "" + + {:ok, 200, [], + Jason.encode!(%{ + list: [%{subscription_entitlement: %{}}, %{subscription_entitlement: %{}}] + })} + end + ) + + assert {:ok, [%SubscriptionEntitlement{}, %SubscriptionEntitlement{}], + %{"next_offset" => nil}} = + SubscriptionEntitlement.list("subscription_id") + end + + test "with limit & offset params should succeed" do + expect( + Chargebeex.HTTPClientMock, + :get, + fn url, body, headers -> + assert url == + "https://test-namespace.chargebee.com/api/v2/subscriptions/subscription_id/subscription_entitlements?limit=1&feature_type%5Bis%5D=switch" + + assert headers == [{"Authorization", "Basic dGVzdF9jaGFyZ2VlYmVlX2FwaV9rZXk6"}] + assert body == "" + + result = %{ + list: [%{subscription_entitlement: %{subscription_id: "subscription_id"}}], + next_offset: "bar" + } + + {:ok, 200, [], Jason.encode!(result)} + end + ) + + assert {:ok, [%SubscriptionEntitlement{}], %{"next_offset" => "bar"}} = + SubscriptionEntitlement.list("subscription_id", %{ + "feature_type[is]" => "switch", + limit: 1 + }) + end + end +end diff --git a/test/support/fixtures/subscription_entitlement.ex b/test/support/fixtures/subscription_entitlement.ex new file mode 100644 index 0000000..264773b --- /dev/null +++ b/test/support/fixtures/subscription_entitlement.ex @@ -0,0 +1,37 @@ +defmodule Chargebeex.Fixtures.SubscriptionEntitlement do + def subscription_entitlement_params() do + """ + { + "subscription_id": "Azq8g8ULPXqdL6zM", + "feature_id": "xero-integration", + "feature_name": "Xero Integration", + "feature_type": "SWITCH", + "value": "true", + "name": "Available", + "is_overridden": true, + "is_enabled": true, + "object": "subscription_entitlement" + } + """ + end + + def retrieve() do + """ + { + "subscription_entitlement": #{subscription_entitlement_params()} + } + """ + end + + def list() do + """ + { + "list": [ + #{retrieve()}, + #{retrieve()} + ], + "next_offset": "1612890918000" + } + """ + end +end