Skip to content

Commit

Permalink
Merge pull request #96 from shore-gmbh/FEAT-subscription-create-with-…
Browse files Browse the repository at this point in the history
…items

feat: add `create_with_items/3` to `Subscription`
  • Loading branch information
maximemenager committed Jan 26, 2024
2 parents f4ee631 + 76b976d commit 1c6b051
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 1 deletion.
5 changes: 5 additions & 0 deletions lib/chargebeex/action.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ defmodule Chargebeex.Action do
Path.join([resource_base_path(resource), action])
end

def nested_resource_path_generic_without_id(nested_to, action) do
path = Enum.map(nested_to, fn {resource, id} -> resource_path(resource, id) end)
Path.join(path ++ [action])
end

def delete_path(resource, id) do
Path.join([resource_path(resource, id), "delete"])
end
Expand Down
108 changes: 107 additions & 1 deletion lib/chargebeex/subscription/subscription.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
defmodule Chargebeex.Subscription do
use TypedStruct
use Chargebeex.Resource, resource: "subscription", only: [:list, :retrieve, :update]

@resource "subscription"
use Chargebeex.Resource, resource: @resource, only: [:list, :retrieve, :update]

alias Chargebeex.Builder
alias Chargebeex.Client

@typedoc """
"future" | "in_trial" | "active" | "non_renewing" | "paused" | "cancelled"
Expand Down Expand Up @@ -99,4 +104,105 @@ defmodule Chargebeex.Subscription do
|> super()
|> Chargebeex.Resource.add_custom_fields(raw_data)
end

@doc """
Creates a Subcription with items for a Customer
## Examples
iex> Chargebeex.Subscription.create_with_items("169ljDT1Op0yuxET", %{
subscription_items: [
%{
item_price_id: "DEF789LMN012",
quantity: 1
}
]
})
{:ok, %Chargebeex.Subscription{
id: "GHI456OPQ789",
contract_term: %{},
referral_info: %{},
shipping_address: %{},
coupons: nil,
charged_items: nil,
item_tiers: nil,
subscription_items: [
%{
"amount" => 100,
"free_quantity" => 0,
"item_price_id" => "DEF789LMN012",
"item_type" => "plan",
"object" => "subscription_item",
"quantity" => 1,
"trial_end" => 1705877999,
"unit_price" => 100
}
],
business_entity_id: "ABC123XYZ456",
auto_close_invoices: true,
custom_fields: %{},
metadata: %{},
create_pending_invoices: false,
free_period_unit: nil,
free_period: nil,
cancel_reason_code: nil,
changes_scheduled_at: nil,
deleted: false,
invoice_notes: nil,
base_currency_code: nil,
exchange_rate: nil,
mrr: nil,
total_dues: nil,
due_since: nil,
due_invoices_count: 0,
net_term_days: nil,
channel: "web",
cancel_schedule_created_at: nil,
plan_amount_in_decimal: nil,
plan_free_quantity_in_decimal: nil,
payment_source_id: nil,
has_scheduled_changes: false,
has_scheduled_advance_invoices: false,
updated_at: 1705785896,
resource_version: 1705785896428,
created_from_ip: nil,
cancel_reason: nil,
cancelled_at: nil,
resume_date: nil,
pause_date: nil,
override_relationship: false,
contract_term_billing_cycle_on_renewal: nil,
activated_at: nil,
started_at: 1705705200,
created_at: 1705785896,
next_billing_at: 1705878000,
current_term_end: nil,
current_term_start: nil,
trial_end_action: nil,
currency_code: nil,
start_date: nil,
trial_end: nil,
billing_period: nil,
billing_period_unit: nil,
object: nil,
remaining_billing_cycles: nil,
po_number: nil,
plan_quantity_in_decimal: nil,
plan_unit_price_in_decimal: nil,
customer_id: nil,
status: nil,
trial_start: nil
}}
"""
def create_with_items(customer_id, params, opts \\ []) do
with path <-
Chargebeex.Action.nested_resource_path_generic_without_id(
[customer: customer_id],
"subscription_for_items"
),
{:ok, _status_code, _headers, content} <- Client.post(path, params, opts),
builded <- Builder.build(content) do
{:ok, Map.get(builded, @resource)}
end
end
end
101 changes: 101 additions & 0 deletions test/chargebeex/subscription_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
defmodule Chargebeex.SubscriptionTest do
use ExUnit.Case, async: true

import Hammox

alias Chargebeex.Fixtures.Common
alias Chargebeex.Subscription

setup :verify_on_exit!

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

expect(
Chargebeex.HTTPClientMock,
:post,
fn url, data, headers ->
assert url ==
"https://test-namespace.chargebee.com/api/v2/customers/foobar/subscription_for_items"

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

assert data == ""

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

assert {:error, 401, [], ^unauthorized} =
Chargebeex.Subscription.create_with_items("foobar", %{})
end

test "with invalid data should fail" do
bad_request = Common.bad_request()

expect(
Chargebeex.HTTPClientMock,
:post,
fn url, data, headers ->
assert url ==
"https://test-namespace.chargebee.com/api/v2/customers/foobar/subscription_for_items"

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

assert data ==
"subscription_items[item_price_id][0]=invalid_item_price_id&subscription_items[quantity][0]=1"

{:ok, 400, [], Jason.encode!(bad_request)}
end
)

assert {:error, 400, [], ^bad_request} =
Chargebeex.Subscription.create_with_items("foobar", %{
subscription_items: [
%{
item_price_id: "invalid_item_price_id",
quantity: 1
}
]
})
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/customers/foobar/subscription_for_items"

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

assert data ==
"subscription_items[item_price_id][0]=item_price_id&subscription_items[quantity][0]=1"

{:ok, 200, [], Jason.encode!(%{customer: %{}, subscription: %{}})}
end
)

assert {:ok, %Subscription{}} =
Chargebeex.Subscription.create_with_items("foobar", %{
subscription_items: [
%{
item_price_id: "item_price_id",
quantity: 1
}
]
})
end
end
end

0 comments on commit 1c6b051

Please sign in to comment.