Skip to content

Commit

Permalink
Add support for inline price data (#1235)
Browse files Browse the repository at this point in the history
* Add support for inline price data

* Apply style fixes

* Cleanup

* Update ManagesInvoices.php

Co-authored-by: Dries Vints <[email protected]>
Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
3 people authored Aug 13, 2021
1 parent 04f6461 commit 884ccd9
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 8 deletions.
11 changes: 8 additions & 3 deletions src/Concerns/ManagesInvoices.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ trait ManagesInvoices
*/
public function tab($description, $amount, array $options = [])
{
if ($this->isAutomaticTaxEnabled()) {
throw new LogicException('For now, you cannot add invoice items in combination automatic tax calculation.');
if ($this->isAutomaticTaxEnabled() && ! array_key_exists('price_data', $options)) {
throw new LogicException('When using automatic tax calculation, you need to define the "price_data" in the options.');
}

$this->assertCustomerExists();
Expand All @@ -37,7 +37,12 @@ public function tab($description, $amount, array $options = [])
'description' => $description,
], $options);

if (array_key_exists('quantity', $options)) {
if (array_key_exists('price_data', $options)) {
$options['price_data'] = array_merge([
'unit_amount' => $amount,
'currency' => $this->preferredCurrency(),
], $options['price_data']);
} elseif (array_key_exists('quantity', $options)) {
$options['unit_amount'] = $options['unit_amount'] ?? $amount;
} else {
$options['amount'] = $amount;
Expand Down
5 changes: 4 additions & 1 deletion src/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,13 @@ protected function parseSwapPrices(array $prices)
$options = is_string($options) ? [] : $options;

$payload = [
'price' => $price,
'tax_rates' => $this->getPriceTaxRatesForPayload($price),
];

if (! isset($options['price_data'])) {
$payload['price'] = $price;
}

if ($isSinglePriceSwap && ! is_null($this->quantity)) {
$payload['quantity'] = $this->quantity;
}
Expand Down
12 changes: 8 additions & 4 deletions src/SubscriptionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class SubscriptionBuilder
*
* @param mixed $owner
* @param string $name
* @param string|string[] $prices
* @param string|string[]|array[] $prices
* @return void
*/
public function __construct($owner, $name, $prices = [])
Expand All @@ -91,13 +91,13 @@ public function __construct($owner, $name, $prices = [])
/**
* Set a price on the subscription builder.
*
* @param string $price
* @param string|array $price
* @param int|null $quantity
* @return $this
*/
public function price($price, $quantity = 1)
{
$options = ['price' => $price];
$options = is_array($price) ? $price : ['price' => $price];

if (! is_null($quantity)) {
$options['quantity'] = $quantity;
Expand All @@ -107,7 +107,11 @@ public function price($price, $quantity = 1)
$options['tax_rates'] = $taxRates;
}

$this->items[$price] = $options;
if (is_array($price)) {
$this->items[] = $options;
} else {
$this->items[$price] = $options;
}

return $this;
}
Expand Down
23 changes: 23 additions & 0 deletions tests/Feature/InvoicesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,29 @@ public function test_customer_can_be_invoiced_with_a_price()
$this->assertEquals(998, $response->total);
}

public function test_customer_can_be_invoiced_with_inline_price_data()
{
$user = $this->createCustomer('customer_can_be_invoiced_with_inline_price_data');
$user->createAsStripeCustomer();
$user->updateDefaultPaymentMethod('pm_card_visa');

$productId = self::stripe()->products->create([
'name' => 'Laravel Cashier Test Product',
'type' => 'service',
])->id;

$response = $user->invoiceFor('Laravel T-shirt', 599, [
'price_data' => [
'product' => $productId,
'tax_behavior' => 'exclusive',
],
]);

$this->assertInstanceOf(Invoice::class, $response);
$this->assertEquals(599, $response->total);
$this->assertEquals('exclusive', $response->invoiceLineItems()[0]->price->tax_behavior);
}

public function test_find_invoice_by_id()
{
$user = $this->createCustomer('find_invoice_by_id');
Expand Down
54 changes: 54 additions & 0 deletions tests/Feature/SubscriptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,28 @@ public function test_swapping_subscription_and_adopting_new_quantity()
$this->assertSame(3, $subscription->asStripeSubscription()->quantity);
}

public function test_swapping_subscription_with_inline_price_data()
{
$user = $this->createCustomer('swapping_subscription_with_inline_price_data');
$user->newSubscription('main', static::$priceId)->create('pm_card_visa');
$subscription = $user->subscription('main');

$subscription->swap([[
'price_data' => [
'product' => static::$productId,
'tax_behavior' => 'exclusive',
'currency' => 'USD',
'recurring' => [
'interval' => 'month',
],
'unit_amount' => 1100,
],
]]);

$this->assertEquals(1100, $subscription->asStripeSubscription()->items->data[0]->price->unit_amount);
$this->assertEquals('exclusive', $subscription->asStripeSubscription()->items->data[0]->price->tax_behavior);
}

public function test_declined_card_during_new_quantity()
{
$user = $this->createCustomer('declined_card_during_new_quantity');
Expand Down Expand Up @@ -439,6 +461,38 @@ public function test_creating_subscription_with_coupons()
$this->assertFalse($coupon->isPercentage());
}

public function test_creating_subscription_with_inline_price_data()
{
$user = $this->createCustomer('creating_subscription_with_inline_price_data');

$user->newSubscription('main')->price([
'price_data' => [
'product' => static::$productId,
'tax_behavior' => 'exclusive',
'currency' => 'USD',
'recurring' => [
'interval' => 'month',
],
'unit_amount' => 1100,
],
])->create('pm_card_visa');

$subscription = $user->subscription('main');

$this->assertTrue($user->subscribed('main'));
$this->assertNotNull($user->subscribed('main', static::$otherPriceId));
$this->assertTrue($subscription->active());
$this->assertFalse($subscription->cancelled());
$this->assertFalse($subscription->onGracePeriod());
$this->assertTrue($subscription->recurring());
$this->assertFalse($subscription->ended());

$invoice = $user->invoices()[0];

$this->assertEquals('$11.00', $invoice->total());
$this->assertEquals('exclusive', $invoice->invoiceLineItems()[0]->price->tax_behavior);
}

public function test_creating_subscription_with_an_anchored_billing_cycle()
{
$user = $this->createCustomer('creating_subscription_with_an_anchored_billing_cycle');
Expand Down

0 comments on commit 884ccd9

Please sign in to comment.