Skip to content

Commit

Permalink
Add EntitlementOverride upsert_or_delete support (#143)
Browse files Browse the repository at this point in the history
* Add EntitlementOverride upsert_or_delete support

* finish module doc
  • Loading branch information
igorrfc authored Jan 13, 2025
1 parent 537d771 commit 7fd2e66
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/chargebeex/builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Chargebeex.Builder do
Customer,
CustomerEntitlement,
Event,
EntitlementOverride,
Invoice,
HostedPage,
PaymentSource,
Expand Down Expand Up @@ -40,6 +41,7 @@ defmodule Chargebeex.Builder do
def build_resource(%{"customer_entitlement" => params}), do: CustomerEntitlement.build(params)
def build_resource(%{"portal_session" => params}), do: PortalSession.build(params)
def build_resource(%{"event" => params}), do: Event.build(params)
def build_resource(%{"entitlement_override" => params}), do: EntitlementOverride.build(params)
def build_resource(%{"card" => params}), do: Card.build(params)
def build_resource(%{"billing_address" => params}), do: BillingAddress.build(params)
def build_resource(%{"payment_source" => params}), do: PaymentSource.build(params)
Expand All @@ -61,6 +63,7 @@ defmodule Chargebeex.Builder do
def build_resource("customer_entitlement", params), do: CustomerEntitlement.build(params)
def build_resource("portal_session", params), do: PortalSession.build(params)
def build_resource("event", params), do: Event.build(params)
def build_resource("entitlement_override", params), do: EntitlementOverride.build(params)
def build_resource("card", params), do: Card.build(params)
def build_resource("billing_address", params), do: BillingAddress.build(params)
def build_resource("payment_source", params), do: PaymentSource.build(params)
Expand Down
99 changes: 99 additions & 0 deletions lib/chargebeex/entitlement_override/entitlement_override.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
defmodule Chargebeex.EntitlementOverride do
use TypedStruct

@resource "entitlement_override"
use Chargebeex.Resource, resource: @resource, only: []

@moduledoc """
Struct that represent a Chargebee's API entitlement override resource.
"""

@typedoc """
"subscription"
"""
@type entity_type :: String.t()

typedstruct do
field :entity_id, String.t()
field :entity_type, entity_type()
field :feature_id, String.t()
field :feature_name, String.t()
field :id, String.t()
field :name, String.t()
field :object, String.t()
field :value, String.t()
end

use ExConstructor, :build

@typedoc """
A single entitlement override map.
"""
@type entitlement_override :: %{
required(:feature_id) => String.t(),
optional(:value) => String.t(),
optional(:expires_at) => non_neg_integer(),
optional(:effective_from) => non_neg_integer()
}

@typedoc """
Parameters for the `upsert_or_remove` function.
The `action` field must be either `upsert` or `remove`.
"""
@type upsert_or_remove_params :: %{
required(:action) => :upsert | :remove,
optional(:entitlement_overrides) => [entitlement_override()],
optional(any()) => any()
}

@doc """
Upserts or removes a set of entitlement_overrides for a subscription depending on the action specified
More info: https://apidocs.eu.chargebee.com/docs/api/entitlement_overrides?lang=curl#upsert/remove_entitlement_overrides_for_a_subscription
## Examples
iex(1)> subscription_id = "BTLybZUInBGCXDMY"
"BTLybZUInBGCXDMY"
iex(2)> params = %{
...(2)> "action" => :upsert,
...(2)> "entitlement_overrides" => [
...(2)> %{
...(2)> "feature_id" => "foo",
...(2)> "value" => "false"
...(2)> }
...(2)> ]
...(2)> }
%{
"action" => :upsert,
"entitlement_overrides" => [
%{"feature_id" => "foo", "value" => "false"}
]
}
iex(3)> Chargebeex.EntitlementOverride.upsert_or_remove(subscription_id, params)
{:ok,
[
%Chargebeex.EntitlementOverride{...}
], %{"next_offset" => nil}}
"""
@spec upsert_or_remove(String.t(), upsert_or_remove_params(), keyword()) :: any()
def upsert_or_remove(subscription_id, params, opts \\ [])

def upsert_or_remove(_subscription_id, %{"action" => action} = _params, _opts)
when action not in [:upsert, :remove] do
raise ArgumentError, """
Invalid action provided to `upsert_or_remove`. Ensure that `params[:action]` is either `:upsert` or `:remove`.
"""
end

def upsert_or_remove(subscription_id, params, opts) do
nested_generic_action_without_id(
:post,
[subscription: subscription_id],
@resource,
"entitlement_overrides",
params,
opts
)
end
end
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ defmodule Chargebeex.MixProject do
Chargebeex.Customer,
Chargebeex.CustomerEntitlement,
Chargebeex.Event,
Chargebeex.EntitlementOverride,
Chargebeex.Invoice,
Chargebeex.PortalSession,
Chargebeex.Subscription,
Expand Down
37 changes: 37 additions & 0 deletions test/chargebeex/builder/entitlement_override_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule Chargebeex.Builder.EntitlementOverrideTest do
use ExUnit.Case, async: true

alias Chargebeex.Builder
alias Chargebeex.Fixtures.EntitlementOverride, as: EntitlementOverrideFixture
alias Chargebeex.EntitlementOverride

describe "build/1" do
test "should build an entitlement override" do
builded =
EntitlementOverrideFixture.retrieve()
|> Jason.decode!()
|> Builder.build()

assert %{"entitlement_override" => %EntitlementOverride{}} = builded
end

test "should have the entitlement_override params" do
entitlement_override =
EntitlementOverrideFixture.retrieve()
|> Jason.decode!()
|> Builder.build()
|> Map.get("entitlement_override")

params = EntitlementOverrideFixture.entitlement_override_params() |> Jason.decode!()

assert entitlement_override.entity_id == Map.get(params, "entity_id")
assert entitlement_override.entity_type == Map.get(params, "entity_type")
assert entitlement_override.feature_id == Map.get(params, "feature_id")
assert entitlement_override.feature_name == Map.get(params, "feature_name")
assert entitlement_override.id == Map.get(params, "id")
assert entitlement_override.name == Map.get(params, "name")
assert entitlement_override.object == Map.get(params, "object")
assert entitlement_override.value == Map.get(params, "value")
end
end
end
84 changes: 84 additions & 0 deletions test/chargebeex/entitlement_override_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
defmodule Chargebeex.EntitlementOverrideTest do
use ExUnit.Case, async: true

import Hammox

alias Chargebeex.Fixtures.Common
alias Chargebeex.EntitlementOverride
alias Chargebeex.Fixtures.EntitlementOverride, as: EntitlementOverrideFixture

setup :verify_on_exit!

describe "upsert_or_remove" do
test "with bad authentication should fail" do
unauthorized = Common.unauthorized()

expect(
Chargebeex.HTTPClientMock,
:post,
fn url, body, headers ->
assert url ==
"https://test-namespace.chargebee.com/api/v2/subscriptions/subscription_id/entitlement_overrides"

assert headers == [
{"Authorization", "Basic dGVzdF9jaGFyZ2VlYmVlX2FwaV9rZXk6"},
{"Content-Type", "application/x-www-form-urlencoded"}
]

assert body == ""

{:ok, 401, [], Jason.encode!(unauthorized)}
end
)

assert {:error, 401, [], ^unauthorized} =
EntitlementOverride.upsert_or_remove("subscription_id", %{})
end

test "with valid data should succeed" do
expect(
Chargebeex.HTTPClientMock,
:post,
fn url, data, headers ->
assert url ==
"https://test-namespace.chargebee.com/api/v2/subscriptions/subscription_id/entitlement_overrides"

assert headers == [
{"Authorization", "Basic dGVzdF9jaGFyZ2VlYmVlX2FwaV9rZXk6"},
{"Content-Type", "application/x-www-form-urlencoded"}
]

assert data ==
"action=upsert&entitlement_overrides[feature_id][0]=override-1935f8d6-b791-4181-9fa2-65fd8bfbd7ae&entitlement_overrides[value][0]=true"

{:ok, 200, [], EntitlementOverrideFixture.list()}
end
)

subscription_id = "subscription_id"

params = %{
"action" => :upsert,
"entitlement_overrides" => [
%{
"feature_id" => "override-1935f8d6-b791-4181-9fa2-65fd8bfbd7ae",
"value" => "true"
}
]
}

assert {:ok, [%EntitlementOverride{}], %{"next_offset" => nil}} =
Chargebeex.EntitlementOverride.upsert_or_remove(subscription_id, params)
end

test "raises an error when action is invalid" do
subscription_id = "sub_123"
invalid_params = %{"action" => :invalid_action}
opts = []

assert_raise ArgumentError, ~r/Invalid action provided to `upsert_or_remove`/, fn ->
EntitlementOverride.upsert_or_remove(subscription_id, invalid_params, opts)
end
end
end
end
34 changes: 34 additions & 0 deletions test/support/fixtures/entitlement_override.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule Chargebeex.Fixtures.EntitlementOverride do
def entitlement_override_params() do
"""
{
"id": "override-1935f8d6-b791-4181-9fa2-65fd8bfbd7ae",
"entity_id": "Jdf63vklssSDFdb",
"entity_type": "subscription",
"feature_id": "fea-be1a9281-d8df-48ce-82e2-294667eb4d94",
"feature_name": "Quickbooks Integration_123",
"name": "Available",
"object": "entitlement_override",
"value": "true"
}
"""
end

def retrieve() do
"""
{
"entitlement_override": #{entitlement_override_params()}
}
"""
end

def list() do
"""
{
"list": [
#{retrieve()}
]
}
"""
end
end

0 comments on commit 7fd2e66

Please sign in to comment.