Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If the invoice has more than 10 items, from item number 11 tax_amounts does not include expanded tax_rate. #1400

Closed
padre opened this issue Nov 18, 2022 · 19 comments
Labels

Comments

@padre
Copy link

padre commented Nov 18, 2022

Describe the bug

Here is the PR laravel/cashier-stripe#1475

To Reproduce

Attempting to generate a pdf of an invoice with more than ten line items

Expected behavior

All lines on an invoice should be expanded, including the tax_rate for a tax_amount.

Code snippets

No response

OS

Ubuntu / Centos

PHP version

PHP 8.1

Library version

stripe/stripe-php v9.9.0

API version

2022-11-15

Additional context

No response

@padre padre added the bug label Nov 18, 2022
@remi-stripe
Copy link
Contributor

@padre Can you provide a lot more specific details to reproduce this exact issue? What code are you using? How are you expanding the extra lines? When you retrieve an Invoice you only get 10 lines at most in lines by default so it's not clear what is blocking you.

@padre
Copy link
Author

padre commented Nov 18, 2022

@remi-stripe I am using the package https://github.com/laravel/cashier-stripe

When I get the invoice to generate the pdf document, $invoice->invoiceLineItems() should show expanded all lines of an invoice, including the tax rate for a tax amount (or at least we think so laravel/cashier-stripe#1475 (comment))

But I only get the first ten line items expanded.

These are line items number 10 and 11 for an invoice:


{
    "id": "il_1M30onCelkdgTLAvq4octXkm",
    "object": "line_item",
    "amount": 195,
    "amount_excluding_tax": 195,
    "currency": "eur",
    "description": "11/11/2022 18:15:05 - I(",
    "discount_amounts": [
      
    ],
    "discountable": true,
    "discounts": [
      
    ],
    "invoice_item": "ii_1M30onCelkdgTLAvYvaJwXk9",
    "livemode": false,
    "metadata": {
      "contractId": "6"
    },
    "period": {
      "end": 1668186905,
      "start": 1668186905
    },
    "plan": null,
    "price": {
      "id": "price_1LwNCTCelkdgTLAv6mPrp23G",
      "object": "price",
      "active": true,
      "billing_scheme": "per_unit",
      "created": 1666604645,
      "currency": "eur",
      "custom_unit_amount": null,
      "livemode": false,
      "lookup_key": null,
      "metadata": [
        
      ],
      "nickname": null,
      "product": "prod_MfidrAKlJcx2TN",
      "recurring": null,
      "tax_behavior": "exclusive",
      "tiers_mode": null,
      "transform_quantity": null,
      "type": "one_time",
      "unit_amount": 195,
      "unit_amount_decimal": "195"
    },
    "proration": false,
    "proration_details": {
      "credited_items": null
    },
    "quantity": 1,
    "subscription": null,
    "tax_amounts": [
      {
        "amount": 41,
        "inclusive": false,
        "tax_rate": {
          "id": "txr_1KxZESCelkdgTLAvmlfA4gHl",
          "object": "tax_rate",
          "active": false,
          "country": "ES",
          "created": 1652112888,
          "description": null,
          "display_name": "VAT",
          "inclusive": false,
          "jurisdiction": "Spain",
          "livemode": false,
          "metadata": [
            
          ],
          "percentage": 21,
          "state": null,
          "tax_type": "vat"
        }
      }
    ],
    "tax_rates": [
      
    ],
    "type": "invoiceitem",
    "unit_amount_excluding_tax": "195"
  },
  {
    "id": "il_1M30XxCelkdgTLAvzph6mjPl",
    "object": "line_item",
    "amount": 195,
    "amount_excluding_tax": 195,
    "currency": "eur",
    "description": "11/11/2022 17:57:41 - I(",
    "discount_amounts": [
      
    ],
    "discountable": true,
    "discounts": [
      
    ],
    "invoice_item": "ii_1M30XxCelkdgTLAvDOdfm1df",
    "livemode": false,
    "metadata": {
      "contractId": "5"
    },
    "period": {
      "end": 1668185861,
      "start": 1668185861
    },
    "plan": null,
    "price": {
      "id": "price_1LwNCTCelkdgTLAv6mPrp23G",
      "object": "price",
      "active": true,
      "billing_scheme": "per_unit",
      "created": 1666604645,
      "currency": "eur",
      "custom_unit_amount": null,
      "livemode": false,
      "lookup_key": null,
      "metadata": [
        
      ],
      "nickname": null,
      "product": "prod_MfidrAKlJcx2TN",
      "recurring": null,
      "tax_behavior": "exclusive",
      "tiers_mode": null,
      "transform_quantity": null,
      "type": "one_time",
      "unit_amount": 195,
      "unit_amount_decimal": "195"
    },
    "proration": false,
    "proration_details": {
      "credited_items": null
    },
    "quantity": 1,
    "subscription": null,
    "tax_amounts": [
      {
        "amount": 41,
        "inclusive": false,
        "tax_rate": "txr_1KxZESCelkdgTLAvmlfA4gHl"
      }
    ],
    "tax_rates": [
      
    ],
    "type": "invoiceitem",
    "unit_amount_excluding_tax": "195"
  },

The line item of invoice number 11 does not include expanded the tax rate for a tax amount:

This is the code: https://github.com/laravel/cashier-stripe/blob/14.x/src/Invoice.php#L567

Is it a problem with stripe or laravel/cashier-stripe?

Thanks!

@remi-stripe
Copy link
Contributor

We need Stripe-specific exact end to end code to repro. Since you use Cashier and they wrap around our API it's hard to grasp which exact part is or isn't working exactly here unfortunately. Can you get the developer in that other issue to write a simple Stripe reproduction first? To me it doesn't look like they are passing the expansion parameters properly during pagination at least

@driesvints
Copy link

@padre it would help if you could lookup the Stripe request in your Stripe dashboard and post the entire request. That would help @remi-stripe in checking what's exactly going on here.

@driesvints
Copy link

Here's the code that calls performs the call btw: it's just an invoice retrieve request with the provided expanse data:

https://github.com/laravel/cashier-stripe/blob/14.x/src/Invoice.php#L564-L575

@padre
Copy link
Author

padre commented Nov 21, 2022

GET /v1/invoices/in_1M4UugCelkdgTLAvIytlZbcj (req_BJ0AzGAXdgho8U)

Params:

{
  "expand": {
    "0": "account_tax_ids",
    "1": "discounts",
    "2": "lines.data.tax_amounts.tax_rate",
    "3": "total_discount_amounts.discount",
    "4": "total_tax_amounts.tax_rate"
  }
}

@remi-stripe
Copy link
Contributor

@driesvints but that code just retrieves the Invoice and gets the first 10 InvoiceLineItems back. Expansion should work totally fine in that one case.
My understanding of the problem was on the next call when you paginate the next line items.

@padre
Copy link
Author

padre commented Nov 22, 2022

@remi-stripe That's the problem, the invoiceLineItems function only gets the first 10 expanded items.

@driesvints
Copy link

@padre if that's the case then how are you running into this issue? What are you doing that triggers the next set of items?

@driesvints
Copy link

@remi-stripe I think I found it. We seem to be using the autoPagingIterator which the Stripe PHP SDK provides. Do you have any idea how we can use it while also expanding the data?

https://github.com/laravel/cashier-stripe/blob/14.x/src/Invoice.php#L501

@padre
Copy link
Author

padre commented Nov 22, 2022

@driesvints All I do is try to download an invoice that has more than 10 items.

$user->downloadInvoice($invoiceId);

@driesvints
Copy link

driesvints commented Dec 9, 2022

Hi @remi-stripe. You can use the following snippet to recreate the bug. As soon as you have an invoice with more than 10 line items that use tax rates it'll fail with the following error:

Attempt to read property "display_name" on string

$stripe = new \Stripe\StripeClient('stripe-secret');

$invoice = $stripe->invoices->retrieve('in_xxx', [
    'expand' => ['lines.data.tax_amounts.tax_rate'],
]);

foreach ($invoice->lines->autoPagingIterator() as $line) {
    foreach ($line->tax_amounts as $tax_amount) {
        $tax_rate = $tax_amount->tax_rate;
        echo $tax_rate->display_name . ' ' . $tax_rate->percentage . '%' . PHP_EOL;
    }
}

After 10 line items, the next ones don't seem to include the expanded data and thus a string ID for tax_amounts is returned rather than the expected expanded object.

@driesvints
Copy link

driesvints commented Dec 9, 2022

Off the bat I think one quick solution could be to pass a $params argument to the autoPagingIterator method that's passed down to the nextPage or previousPage method inside it. That way we can pass the expand list to it. I tried this approach and it worked:

$stripe = new \Stripe\StripeClient('stripe-secret');

$invoice = $stripe->invoices->retrieve('in_xxx', [
    'expand' => ['lines.data.tax_amounts.tax_rate'],
]);

foreach ($invoice->lines->autoPagingIterator(['expand' => ['data.tax_amounts.tax_rate']) as $line) {
    foreach ($line->tax_amounts as $tax_amount) {
        $tax_rate = $tax_amount->tax_rate;
        echo $tax_rate->display_name . ' ' . $tax_rate->percentage . '%' . PHP_EOL;
    }
}

I guess solving this automatically isn't possible.

@driesvints
Copy link

I sent in a PR for this: #1409

@richardm-stripe
Copy link
Contributor

This should now be resolved by a server-side fix! Thank you all! Please feel free to re-open if you notice any problems.

@driesvints
Copy link

Cool, thanks! @padre can you try it out?

@padre
Copy link
Author

padre commented Jan 11, 2023

@driesvints Nothing has changed :-(

Attempt to read property "percentage" on string (View: /var/app/current/vendor/laravel/cashier/resources/views/receipt.blade.php) {"exception":"[object] (Illuminate\\View\\ViewException(code: 0): Attempt to read property \"percentage\" on string (View: /var/app/current/vendor/laravel/cashier/resources/views/receipt.blade.php) at /var/app/current/vendor/laravel/cashier/src/InvoiceLineItem.php:138)

@driesvints
Copy link

@padre that's unfortunate. Can you re-open the issue like @richardm-stripe asked?

@padre
Copy link
Author

padre commented Jan 12, 2023

@driesvints, done (thank you very much for your dedication)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants