#rcc_schedule-update

1 messages ยท Page 1 of 1 (latest)

lunar narwhalBOT
#

๐Ÿ‘‹ Welcome to your new thread!

โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

๐Ÿ”— This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1415390401162117192

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.

knotty burrow
flint nacelle
#

So, here's the scenario:

I have a concept of a permit fee that renews annually at a lower rate than the initial permit fee cost. Let's assume this is a Commercial permit fee of $50 for the first year and $25 every year thereafter. There is also a Residential permit fee of $25 and $15 every year thereafter.

Now assume that the administrator sets this up based on a permit application received, but accidentally selects "Commercial" when it should have been "Residential". Say a month goes by before someone recognizes the mistake. I now need to update both phases to use the lower price and credit the permit holder for the difference.

Since updating the phases would cause an incorrect proration on the current active phase, I have to do one of the following:

  • Update both phases but turn off prorations. Then credit the user manually outside of stripe automatic prorations.
  • Update only the second phase to the correct price, but leave the first phase unchanged. Then use the subscriptions API to backdate the proration to the lower price while it is still attached to the schedule, getting the schedule and the subscription out of sync on the first phase. I believe the second phase transition will still happen normally.

I'm not sure of the full implications of the second option. I'm actively testing this in my sandbox today.

#

So I don't believe the suggestion would work since I need to update an already active and paid for subscription.

knotty burrow
#

Why could not you create a new subscription for the 'Commercial' price for that customer and cancel the 'Residential' subscription?

#

If you want to keep it on the same subscription, you could also use Credit Notes, https://docs.stripe.com/invoicing/dashboard/credit-notes instead of having to manually create it outside of Stripe. The credit note balances either increases/ decreases the amount that is owned on the future invoices.

flint nacelle
knotty burrow
#

In which of the above two flows?

flint nacelle
#

so I would cancel the subscription schedule, cancelling the original Commecial subscription. I would then backdate a new Residential subscription to the original subscription date.

#

but I need the Commercial subscription cancellation to basically credit the entire amount already collected.

knotty burrow
#

You can offer a freaa trial for what ever that amount to

#

Or, you can create a credit note for that amount on the customer so the next invoice is lower

#

You can test both and see which one works best for your use case

flint nacelle
#

ok. But to confirm, it's not possible to backdate a cancellation of a subscription?

knotty burrow
flint nacelle
#

ok. Let me test some things out then.

#

btw, is any metadata set on subscription_schedule.phases.metadata propagated to the subscription itself, the subscription invoices, and the subscription invoice items?

knotty burrow
flint nacelle
#

Do subscription created invoice items not show up in stripe_client.v1.invoice_items.list(options={"stripe_account": account.id})?

#
invoice_items
<ListObject list at 0x70352ed0f250> JSON: {
  "data": [],
  "has_more": false,
  "object": "list",
  "url": "/v1/invoiceitems"
}
#

req_5SwZgWj4QQXoV1

knotty burrow
flint nacelle
#

sure one second

#
>>> invoice.id
'in_1S5sG5Pfgdk4NFmKO7TDqe0L'
>>> invoice.parent.subscription_details.subscription
'sub_1S5sG4Pfgdk4NFmKpUr7M6US'
>>> invoice.lines
<ListObject list at 0x70352ed0ec60> JSON: {
  "data": [
    {
      "amount": 5000,
      "currency": "usd",
      "description": "1 \u00d7 industry permit fee (at $50.00 / year)",
      "discount_amounts": [],
      "discountable": true,
      "discounts": [],
      "id": "il_1QcFLwPfgdk4NFmKhfAGNyfv",
      "invoice": "in_1S5sG5Pfgdk4NFmKO7TDqe0L",
      "livemode": false,
      "metadata": {
        "alarm_system_id": "alarmsystem_MAwOQmzCZ2JQJFeG79ohogIa1WT",
        "alarm_user_id": "alarmuser_rF4lWENh9YithPNR41sccfyqkyQ",
        "jurisdiction_id": "org_CNxBkQbcXA6ZLXx3oikyeKaOKaQ"
      },
      "object": "line_item",
      "parent": {
        "invoice_item_details": null,
        "subscription_item_details": {
          "invoice_item": null,
          "proration": false,
          "proration_details": {
            "credited_items": null
          },
          "subscription": "sub_1S5sG4Pfgdk4NFmKpUr7M6US",
          "subscription_item": "si_T1w8S88QnnLgzp"
        },
        "type": "subscription_item_details"
      },
      "period": {
        "end": 1767225600,
        "start": 1735689600
      },
      "pretax_credit_amounts": [],
      "pricing": {
        "price_details": {
          "price": "price_1S5sG4Pfgdk4NFmK4X7vjfIO",
          "product": "permittype_qZqPtM0edgNy7bSri6RqWwhB2nj"
        },
        "type": "price_details",
        "unit_amount_decimal": "5000"
      },
      "quantity": 1,
      "taxes": []
    }
  ],
  "has_more": false,
  "object": "list",
  "total_count": 1,
  "url": "/v1/invoices/in_1S5sG5Pfgdk4NFmKO7TDqe0L/lines"
}
>>> stripe_client.v1.invoice_items.list(options={"stripe_account": account.id})
<ListObject list at 0x70352ecf6710> JSON: {
  "data": [],
  "has_more": false,
  "object": "list",
  "url": "/v1/invoiceitems"
}
#
>>> invoice.stripe_account
'acct_1S5sG0Pfgdk4NFmK'
>>> account.id
'acct_1S5sG0Pfgdk4NFmK'
knotty burrow
flint nacelle
#

sure, one second

#
>>> subscription_schedule2 = SubscriptionScheduleFactory(
...     stripe_test_client=stripe_client, stripe_account=account.id
... )
>>> stripe_client.v1.invoice_items.list(options={"stripe_account": account.id})
<ListObject list at 0x70352ed0fe80> JSON: {
  "data": [],
  "has_more": false,
  "object": "list",
  "url": "/v1/invoiceitems"
}
>>> subscription_schedule2.id
'sub_sched_1S5szVPfgdk4NFmKUlPjD3td'
>>> subscription2 = stripe_client.v1.subscriptions.retrieve(subscription_schedule2.subscription, options={"stripe_account": account.id})
>>> subscription2.id
'sub_1S5szVPfgdk4NFmKb9oXIwTh'
>>> invoice2 = stripe_client.v1.invoices.retrieve(subscription.latest_invoice, options={"stripe_account": account.id})
>>> invoice2.id
'in_1S5sG5Pfgdk4NFmKO7TDqe0L'
#
>>> invoice2.lines
<ListObject list at 0x70352ed25040> JSON: {
  "data": [
    {
      "amount": 5000,
      "currency": "usd",
      "description": "1 \u00d7 industry permit fee (at $50.00 / year)",
      "discount_amounts": [],
      "discountable": true,
      "discounts": [],
      "id": "il_1QcFLwPfgdk4NFmKhfAGNyfv",
      "invoice": "in_1S5sG5Pfgdk4NFmKO7TDqe0L",
      "livemode": false,
      "metadata": {
        "alarm_system_id": "alarmsystem_MAwOQmzCZ2JQJFeG79ohogIa1WT",
        "alarm_user_id": "alarmuser_rF4lWENh9YithPNR41sccfyqkyQ",
        "jurisdiction_id": "org_CNxBkQbcXA6ZLXx3oikyeKaOKaQ"
      },
      "object": "line_item",
      "parent": {
        "invoice_item_details": null,
        "subscription_item_details": {
          "invoice_item": null,
          "proration": false,
          "proration_details": {
            "credited_items": null
          },
          "subscription": "sub_1S5sG4Pfgdk4NFmKpUr7M6US",
          "subscription_item": "si_T1w8S88QnnLgzp"
        },
        "type": "subscription_item_details"
      },
      "period": {
        "end": 1767225600,
        "start": 1735689600
      },
      "pretax_credit_amounts": [],
      "pricing": {
        "price_details": {
          "price": "price_1S5sG4Pfgdk4NFmK4X7vjfIO",
          "product": "permittype_qZqPtM0edgNy7bSri6RqWwhB2nj"
        },
        "type": "price_details",
        "unit_amount_decimal": "5000"
      },
      "quantity": 1,
      "taxes": []
    }
  ],
  "has_more": false,
  "object": "list",
  "total_count": 1,
  "url": "/v1/invoices/in_1S5sG5Pfgdk4NFmKO7TDqe0L/lines"
}
knotty burrow
#

Worked?

flint nacelle
#

no, the invoice items list call returns nothing still

#
>>> stripe_client.v1.invoice_items.list(options={"stripe_account": account.id})
<ListObject list at 0x70352ed25db0> JSON: {
  "data": [],
  "has_more": false,
  "object": "list",
  "url": "/v1/invoiceitems"
}
#

is it because the invoice isn't finalized yet?

knotty burrow
#

I tested this end to end, and I can confirm that should return invoice items from subscription invoices.

#

Ah potentially, can you try that?

flint nacelle
#

can you confirm which api endpoint you're listing from?

#

sure one second

#
>>> stripe_client.v1.invoice_items.list(options={"stripe_account": account.id})
<ListObject list at 0x70352ed0eb20> JSON: {
  "data": [],
  "has_more": false,
  "object": "list",
  "url": "/v1/invoiceitems"
}
>>> invoice.status
'open'
>>>
knotty burrow
flint nacelle
#

yes, I'm doing a GET /v1/invoiceitems not GET /v1/invoices/:id/lines

knotty burrow
#

yeah, I'm able to see what you're seeing. Let me look around to confirm what the expected behavior is.

#

Sorry for the confusion

flint nacelle
#

np

lunar narwhalBOT
oak solar
#

๐Ÿ‘‹ taking over and trying to grasp what you are doing (and failing for now) so give me some time

flint nacelle
#

currently attempting to understand why a subscription invoice's items don't show up when listing invoice items.

oak solar
#

yeah my colleague said the same and I don't get the wording at all ๐Ÿ˜“

#

InvoiceItems are special and have the id ii_12345. They are separate from an Invoice's lines called InvoiceLineItem with the id ili_1234

#

So if you have an Invoice for $100 with one line for the recurring Price ili_ABC that one will never appear in the List InvoiceItems API.

flint nacelle
#

OK, so having a line item on an invoice != an invoice item.

oak solar
#

yeah it's super confusing to ~everyone

flint nacelle
#

so when do line items on an invoice correspond to an invoice item? Only when I manually create an invoice item?

oak solar
#

or for proration for example

#

but yeah never for the "normal" recurring Price.

flint nacelle
#

ok, that's good to know

#

Is there a difference of behavior when changing a price on a subscription item through updating the subscription vs updating the subscription item directly?

oak solar
#

no that should be identical

#

rcc_schedule-update

flint nacelle
#

is there a way to customize the description on created invoice items from a proration?

#

also, do test clocks prevent proration invoice items from appearing in the list endpoint?

oak solar
#

and no TestClocks shouldn't be relevant here. But just make a simple thing/test with no TestClock to start and confirm

flint nacelle
#

ok, because I created a proration and I see pending invoice items in the dashboard but no invoice items are being returned from the API.

oak solar
#

hmmm so maybe we ignore those if they are associated with a TestClock. Are you passing the Customer id on the List call?

flint nacelle
#

no, I'm not passing anything

#

let me try adding the customer

#

ah, so now it shows them

oak solar
#

yeah I think anything related to a TestClock in the API requires passing the TestClock or associated Customer id. Definitely confusing though ๐Ÿ˜“

lunar narwhalBOT
flint nacelle
#

So I noticed that the proration code logic creates negative unit amount invoice items, where if I did it manually I would have used credit notes. What's the difference between the two and why would one use one over the other?

lament light
#

๐Ÿ‘‹ stepping in here

#

You can create/add negative Invoice Items as well.

#

Generally Credit Notes are meant to be used to adjust the value of a finalized Invoice.

#

But on creation you wouldn't generally use Credit Notes

flint nacelle
#

Right, but since this use case is for crediting an overcharge because we set up the subscription on the wrong plan, I would use a credit note on the subscription invoice(s) to denote that if I was doing it manually. That sounds like the right way for the manual approach if I don't attempt to use Stripe's proration logic.

#

For example, we charged them $50 when it should have been on the $25/year plan. So we need to credit them the entire $50 and charge $25.

lament light
#

Gotcha, it might be easiest here actually to just give them a Credit Balance: https://docs.stripe.com/invoicing/customer/balance

That would just reduce the amount of the next finalized Invoice.

However if you want to be more descriptive on the Invoice then yes, a Credit Note would work.

flint nacelle
#

ok. Trying to find the best way of handling this case so I'm messing around with the proration and manual processes.