-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Subscriptions: use djstripe for Plan and PlanFeature models #9313
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
Comments
There is ongoing work here, but in other PR's. |
We also need to be able to make this per-subscription, Are we okay with creating a custom product/price on stripe for any custom plans we have or may have in the future? If so, I have three solutions: Using metadataStripe doesn't allow us to have nested metadata (only one top level key/value),
The metadata would be attached to the Price stripe models. The values are always strings, A query for example would be something like: prices = Price.objects.filter(**{'metadata__feature:private-docs': '1'})
organizations = Organization.objects.filter(stripe_customer__subscriptions__items__price__metadata__foo='bar') I don't see that we have queries that do comparisons ( Attaching a Price object to a rtd Plan objectInstead of having the features as metadata, This is organizations = Organization.objects.filter(stripe_customer__subscriptions__items__price__rtd_plan__features__value=1) The advantage is that we will be able to use the lt/gt operators and we don't have to cast the values. Attaching a Price object to several FeaturePlan objectsThis is the same as the previous solution, This is organizations = Organization.objects.filter(stripe_customer__subscriptions__items__price__rtd_features__value=1) |
@stsewd which solution do you think is best? |
I may be slightly in favor of A, since we won't be needing our own models, but it has its own disadvantages... I'm good with B and C too p: A
B
C
|
Heh, gotcha. I do think trying to fit all our data into Stripe feels useful, but also constraining. I'd be curious to hear what @humitos and other folks think here. I saw a talk about migrated to djstripe, and they mentioned not including your plan data in Stripe to keep things simpler to manage, but I can't find a link to that currently. |
Notes after reading https://www.saaspegasus.com/guides/django-stripe-integrate/
So, the solution that I'm thinking would be something like the described in the item B. And we can create new models or re-use the ones (they have a lot of information we don't need). And they would be attached to a product, not a price, this means we would need to create a new product with one price in it for custom subscriptions (like enterprise plans). |
We should document how to do this correctly, so we don't mess it up.
This sounds like a good approach. I don't have a strong feeling about new or reusing models, as long as it's easy to transfer the data. Glad the document was useful! |
I have the same feeling here. I would say that I like having all the data in Stripe to avoid having to sync things, but at what cost? I understand that item A makes the usage of all of this more complicated/complex. It seems that B is a middle ground solution here that gives us the best of the two worlds without complicating things too much. However, I'm not 100% sure to understand all the goals and constraints here. What's the main goal of this task? I'm assuming that we want to be able to answer the questions "does this organization pays for Pro plan?" (e.g. when checking for Google SSO) and "does this organization pays for "extra builders"? If so, how many it pays for?" (e.g. when checking for concurrency limit). Am I correct here?
I think this makes sense, because a product will be "Basic Plan" and a price is "Yearly" / "Monthly", where prices do not affect the features the organization has available, so 👍🏼
I skimmed this document, but it's too big. Do you have a specific section you would recommend that's related to what we are talking here? I think I found the important section https://www.saaspegasus.com/guides/django-stripe-integrate/#adding-metadata-to-your-stripe-objects
After reading the section that I linked previously, I'm leaning towards hard code this in our code. It will be easier to follow the code, know exactly what are all the extra features we have and all our environments will be in sync. The use of dataclasses makes it really easy to follow. I don't expect require making changes on production about these plan features "on the fly", so I think it makes sense to have them hardcoded to reduce the complexity. Besides, we won't have issues about missing relationships between a Plan and a PlanFeature (as I remember having with the current code) In case you disagree here, I'd like to know more about why do you think that for our case it's better to have these relations in the database. |
that's the goal, yes.
I could recommend some sections
(that may be must part of the post...)
We do need to make such changes when adding enterprise plans, since we would be creating a new product with another set of features. |
I'd say these don't happen too frequent to absorb the overhead of managing all these relationships and complexity for the most common cases. Usually, Enterprise plans take some weeks/months to finally get approved and paid --which will give us enough time to do a deploy with these changes. We can also do hotfix if we have to. |
After reading this, I think I'm mostly OK with hard-coding it. I do think the ability to have the plans in sync between development is useful, but I don't know how useful. But I do think that most Enterprise users have a standard set of requirements that they need. If we find that we're having to do hotfix deploys very frequently though, we should re-evaluate this decision. I'm also 👍 on keeping it in the code if it's already written, and hard-coding is going to require extra work. I don't think there's a strong reason for either approach, so I'm mostly just advocating for the quickest option :) |
Before making the big change, I want to unify the way we check for features #8920, that way it is easier to change the logic in a single place. |
@stsewd just to confirm, in the plan so far, we'd still retain our plans as products with multiple prices, correct? The checkout UI is a bit nicer in this case, compared to the legacy version of this, where each plan price is it's own product. |
yes, we will have multiple products with several prices, but features will be attached to the product, not the price. |
Blocked on #8920 |
Gonna push this back, since it's not seeming to be priority. |
Instead of relying on our subscription models, we are now relying on the djstripe models, but the features of each subscription are still attached to our subscription models. In the new modeling, we have features attached to stripe products. I'm using some data classes to make the representation instead of using plain dictionaries, they are more verbose than a plain dictionary, but are easier to manipulate in the code. After this change has been deployed, we won't be needing our subscription models anymore. The available products are defined in .com, since in .org we don't have subscriptions. If we feel like we can have this in the DB, we can also switch the data classes to be Django models. Closes #9313
Similar to #9312 we'll want to use djstripe for these models as well. This is a little bit more work, as there is no Stripe resource for PlanFeature.
The text was updated successfully, but these errors were encountered: