-
Notifications
You must be signed in to change notification settings - Fork 28
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
API: Migrate to Plan / Tier Tables #1099
Open
ajay-sentry
wants to merge
15
commits into
main
Choose a base branch
from
Ajay/milestone-3-migration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+716
−206
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
947954a
starting transition, need the other PR merged to do imports and test …
ajay-sentry a06b8c8
other api stuff
ajay-sentry 1f2e63b
revert trial status changes, update other instances of plan stuff
ajay-sentry 5050704
fix a couple instances... still need to fix availablePlans
ajay-sentry 40abd2d
a few more references for PAID and TEAM_PLANS
ajay-sentry 16f7fba
missing s
ajay-sentry 3a5b3af
add missing imports + refactor to call 1 query
RulaKhaled d26259a
update tests
RulaKhaled f21a5f1
testing locally, fix the tier checks and first test
ajay-sentry ba63895
starting to fix tests and some logic
ajay-sentry 91ea64b
update api with mocked plans
RulaKhaled 42488fb
fix all tests except account_viewset
ajay-sentry 1bfc6d8
all tests passing now, fixed a couple small logic bugs too
ajay-sentry 99a63e1
fix this suite, when using ttestcase need to have setup vs setupClass
ajay-sentry 49f2af8
clean up the logic for update plan
ajay-sentry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,14 +7,12 @@ | |
from rest_framework import serializers | ||
from rest_framework.exceptions import PermissionDenied | ||
from shared.plan.constants import ( | ||
PAID_PLANS, | ||
SENTRY_PAID_USER_PLAN_REPRESENTATIONS, | ||
TEAM_PLAN_MAX_USERS, | ||
TEAM_PLAN_REPRESENTATIONS, | ||
TierName, | ||
) | ||
from shared.plan.service import PlanService | ||
|
||
from codecov_auth.models import Owner | ||
from codecov_auth.models import Owner, Plan | ||
from services.billing import BillingService | ||
from services.sentry import send_user_webhook as send_sentry_webhook | ||
|
||
|
@@ -137,11 +135,6 @@ def validate_value(self, value: str) -> str: | |
plan["value"] for plan in plan_service.available_plans(current_owner) | ||
] | ||
if value not in plan_values: | ||
if value in SENTRY_PAID_USER_PLAN_REPRESENTATIONS: | ||
log.warning( | ||
"Non-Sentry user attempted to transition to Sentry plan", | ||
extra=dict(owner_id=current_owner.pk, plan=value), | ||
) | ||
raise serializers.ValidationError( | ||
f"Invalid value for plan: {value}; must be one of {plan_values}" | ||
) | ||
|
@@ -154,8 +147,18 @@ def validate(self, plan: Dict[str, Any]) -> Dict[str, Any]: | |
detail="You cannot update your plan manually, for help or changes to plan, connect with [email protected]" | ||
) | ||
|
||
active_plans = list( | ||
Plan.objects.select_related("tier").filter(paid_plan=True, is_active=True) | ||
) | ||
active_plan_names = {plan.name for plan in active_plans} | ||
team_tier_plans = { | ||
plan.name | ||
for plan in active_plans | ||
if plan.tier.tier_name == TierName.TEAM.value | ||
} | ||
|
||
# Validate quantity here because we need access to whole plan object | ||
if plan["value"] in PAID_PLANS: | ||
if plan["value"] in active_plan_names: | ||
if "quantity" not in plan: | ||
raise serializers.ValidationError( | ||
"Field 'quantity' required for updating to paid plans" | ||
|
@@ -184,7 +187,7 @@ def validate(self, plan: Dict[str, Any]) -> Dict[str, Any]: | |
"Quantity or plan for paid plan must be different from the existing one" | ||
) | ||
if ( | ||
plan["value"] in TEAM_PLAN_REPRESENTATIONS | ||
plan["value"] in team_tier_plans | ||
and plan["quantity"] > TEAM_PLAN_MAX_USERS | ||
): | ||
raise serializers.ValidationError( | ||
|
@@ -219,7 +222,7 @@ def get_plan(self, phase: Dict[str, Any]) -> str: | |
plan_name = list(stripe_plan_dict.keys())[ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can probably be further cleaned up by doing a get on the stripe_id 🤔 |
||
list(stripe_plan_dict.values()).index(plan_id) | ||
] | ||
marketing_plan_name = PAID_PLANS[plan_name].billing_rate | ||
marketing_plan_name = Plan.objects.get(name=plan_name).marketing_name | ||
return marketing_plan_name | ||
|
||
def get_quantity(self, phase: Dict[str, Any]) -> int: | ||
|
@@ -342,7 +345,11 @@ def update(self, instance: Owner, validated_data: Dict[str, Any]) -> object: | |
instance, desired_plan | ||
) | ||
|
||
if desired_plan["value"] in SENTRY_PAID_USER_PLAN_REPRESENTATIONS: | ||
sentry_plans = Plan.objects.filter( | ||
tier__tier_name=TierName.SENTRY.value, is_active=True | ||
).values_list("name", flat=True) | ||
|
||
if desired_plan["value"] in sentry_plans: | ||
current_owner = self.context["view"].request.current_owner | ||
send_sentry_webhook(current_owner, instance) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
...nt_viewset/AccountViewSetTests/test_update_must_fail_if_team_plan_and_too_many_users.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
interactions: | ||
- request: | ||
body: billing_address_collection=required&payment_method_collection=if_required&client_reference_id=65&success_url=http%3A%2F%2Flocalhost%3A3000%2Fplan%2Fgh%2Fjustin47%3Fsuccess&cancel_url=http%3A%2F%2Flocalhost%3A3000%2Fplan%2Fgh%2Fjustin47%3Fcancel&customer=1000&mode=subscription&line_items[0][price]=price_1OCM0gGlVGuVgOrkWDYEBtSL&line_items[0][quantity]=11&subscription_data[metadata][service]=github&subscription_data[metadata][obo_organization]=65&subscription_data[metadata][username]=justin47&subscription_data[metadata][obo_name]=Kelly+Williams&subscription_data[metadata][obo_email]=christopher27%40lopez-welch.com&subscription_data[metadata][obo]=65&tax_id_collection[enabled]=True&customer_update[name]=auto&customer_update[address]=auto | ||
headers: | ||
Accept: | ||
- '*/*' | ||
Accept-Encoding: | ||
- gzip, deflate | ||
Connection: | ||
- keep-alive | ||
Content-Length: | ||
- '744' | ||
Content-Type: | ||
- application/x-www-form-urlencoded | ||
Idempotency-Key: | ||
- 2e7e12e1-9051-4766-b947-1abe985b5e98 | ||
Stripe-Version: | ||
- 2024-12-18.acacia | ||
User-Agent: | ||
- Stripe/v1 PythonBindings/11.4.1 | ||
X-Stripe-Client-User-Agent: | ||
- '{"bindings_version": "11.4.1", "lang": "python", "publisher": "stripe", "httplib": | ||
"requests", "lang_version": "3.12.8", "platform": "Linux-6.10.14-linuxkit-aarch64-with-glibc2.36", | ||
"uname": "Linux 35c9e7c77efc 6.10.14-linuxkit #1 SMP Fri Nov 29 17:22:03 UTC | ||
2024 aarch64 "}' | ||
method: POST | ||
uri: https://api.stripe.com/v1/checkout/sessions | ||
response: | ||
body: | ||
string: "{\n \"error\": {\n \"code\": \"resource_missing\",\n \"doc_url\": | ||
\"https://stripe.com/docs/error-codes/resource-missing\",\n \"message\": | ||
\"No such customer: '1000'\",\n \"param\": \"customer\",\n \"request_log_url\": | ||
\"https://dashboard.stripe.com/test/logs/req_oevRZUbMiaT1kM?t=1737668618\",\n | ||
\ \"type\": \"invalid_request_error\"\n }\n}\n" | ||
headers: | ||
Access-Control-Allow-Credentials: | ||
- 'true' | ||
Access-Control-Allow-Methods: | ||
- GET, HEAD, PUT, PATCH, POST, DELETE | ||
Access-Control-Allow-Origin: | ||
- '*' | ||
Access-Control-Expose-Headers: | ||
- Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, | ||
X-Stripe-Privileged-Session-Required | ||
Access-Control-Max-Age: | ||
- '300' | ||
Cache-Control: | ||
- no-cache, no-store | ||
Connection: | ||
- keep-alive | ||
Content-Length: | ||
- '325' | ||
Content-Security-Policy: | ||
- base-uri 'none'; default-src 'none'; form-action 'none'; frame-ancestors 'none'; | ||
img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'; upgrade-insecure-requests; | ||
report-uri https://q.stripe.com/csp-violation?q=ieXMYrsoTw4hsNfwL6RhDPN6zQnVwnAAc0QsFb8i8xtl4N7V94VZzDmgDhKzWxW8mHRRg08-d5GW6oHr | ||
Content-Type: | ||
- application/json | ||
Cross-Origin-Opener-Policy-Report-Only: | ||
- same-origin; report-to="coop" | ||
Date: | ||
- Thu, 23 Jan 2025 21:43:38 GMT | ||
Idempotency-Key: | ||
- 2e7e12e1-9051-4766-b947-1abe985b5e98 | ||
Original-Request: | ||
- req_oevRZUbMiaT1kM | ||
Report-To: | ||
- '{"group":"coop","max_age":8640,"endpoints":[{"url":"https://q.stripe.com/coop-report"}],"include_subdomains":true}' | ||
Reporting-Endpoints: | ||
- coop="https://q.stripe.com/coop-report" | ||
Request-Id: | ||
- req_oevRZUbMiaT1kM | ||
Server: | ||
- nginx | ||
Strict-Transport-Security: | ||
- max-age=63072000; includeSubDomains; preload | ||
Stripe-Version: | ||
- 2024-12-18.acacia | ||
Vary: | ||
- Origin | ||
X-Content-Type-Options: | ||
- nosniff | ||
X-Stripe-Priority-Routing-Enabled: | ||
- 'true' | ||
X-Stripe-Routing-Context-Priority-Tier: | ||
- api-testmode | ||
X-Wc: | ||
- AB | ||
status: | ||
code: 400 | ||
message: Bad Request | ||
version: 1 |
95 changes: 95 additions & 0 deletions
95
...ewSetTests/test_update_team_plan_must_fail_if_currently_team_plan_add_too_many_users.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
interactions: | ||
- request: | ||
body: billing_address_collection=required&payment_method_collection=if_required&client_reference_id=93&success_url=http%3A%2F%2Flocalhost%3A3000%2Fplan%2Fgh%2Fjocelyn62%3Fsuccess&cancel_url=http%3A%2F%2Flocalhost%3A3000%2Fplan%2Fgh%2Fjocelyn62%3Fcancel&customer=1000&mode=subscription&line_items[0][price]=price_1OCM0gGlVGuVgOrkWDYEBtSL&line_items[0][quantity]=11&subscription_data[metadata][service]=github&subscription_data[metadata][obo_organization]=93&subscription_data[metadata][username]=jocelyn62&subscription_data[metadata][obo_name]=Crystal+Schmitt&subscription_data[metadata][obo_email]=smithamanda%40flowers.biz&subscription_data[metadata][obo]=93&tax_id_collection[enabled]=True&customer_update[name]=auto&customer_update[address]=auto | ||
headers: | ||
Accept: | ||
- '*/*' | ||
Accept-Encoding: | ||
- gzip, deflate | ||
Connection: | ||
- keep-alive | ||
Content-Length: | ||
- '742' | ||
Content-Type: | ||
- application/x-www-form-urlencoded | ||
Idempotency-Key: | ||
- 26000f5a-feb8-4647-ac57-32a5e5ff8729 | ||
Stripe-Version: | ||
- 2024-12-18.acacia | ||
User-Agent: | ||
- Stripe/v1 PythonBindings/11.4.1 | ||
X-Stripe-Client-Telemetry: | ||
- '{"last_request_metrics": {"request_id": "req_AaY8IvHbbSDcvz", "request_duration_ms": | ||
2}}' | ||
X-Stripe-Client-User-Agent: | ||
- '{"bindings_version": "11.4.1", "lang": "python", "publisher": "stripe", "httplib": | ||
"requests", "lang_version": "3.12.8", "platform": "Linux-6.10.14-linuxkit-aarch64-with-glibc2.36", | ||
"uname": "Linux 35c9e7c77efc 6.10.14-linuxkit #1 SMP Fri Nov 29 17:22:03 UTC | ||
2024 aarch64 "}' | ||
method: POST | ||
uri: https://api.stripe.com/v1/checkout/sessions | ||
response: | ||
body: | ||
string: "{\n \"error\": {\n \"code\": \"resource_missing\",\n \"doc_url\": | ||
\"https://stripe.com/docs/error-codes/resource-missing\",\n \"message\": | ||
\"No such customer: '1000'\",\n \"param\": \"customer\",\n \"request_log_url\": | ||
\"https://dashboard.stripe.com/test/logs/req_k8lY68XdxWIFHo?t=1737668619\",\n | ||
\ \"type\": \"invalid_request_error\"\n }\n}\n" | ||
headers: | ||
Access-Control-Allow-Credentials: | ||
- 'true' | ||
Access-Control-Allow-Methods: | ||
- GET, HEAD, PUT, PATCH, POST, DELETE | ||
Access-Control-Allow-Origin: | ||
- '*' | ||
Access-Control-Expose-Headers: | ||
- Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, | ||
X-Stripe-Privileged-Session-Required | ||
Access-Control-Max-Age: | ||
- '300' | ||
Cache-Control: | ||
- no-cache, no-store | ||
Connection: | ||
- keep-alive | ||
Content-Length: | ||
- '325' | ||
Content-Security-Policy: | ||
- base-uri 'none'; default-src 'none'; form-action 'none'; frame-ancestors 'none'; | ||
img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'; upgrade-insecure-requests; | ||
report-uri https://q.stripe.com/csp-violation?q=1vgSiZ6UPd0qoBXo1Mjsk02GXFGP3M7PXsjua2jiowWQKm8jByxTHbhTeRirsQsrZ7jscQLjXtdCc_sh | ||
Content-Type: | ||
- application/json | ||
Cross-Origin-Opener-Policy-Report-Only: | ||
- same-origin; report-to="coop" | ||
Date: | ||
- Thu, 23 Jan 2025 21:43:39 GMT | ||
Idempotency-Key: | ||
- 26000f5a-feb8-4647-ac57-32a5e5ff8729 | ||
Original-Request: | ||
- req_k8lY68XdxWIFHo | ||
Report-To: | ||
- '{"group":"coop","max_age":8640,"endpoints":[{"url":"https://q.stripe.com/coop-report"}],"include_subdomains":true}' | ||
Reporting-Endpoints: | ||
- coop="https://q.stripe.com/coop-report" | ||
Request-Id: | ||
- req_k8lY68XdxWIFHo | ||
Server: | ||
- nginx | ||
Strict-Transport-Security: | ||
- max-age=63072000; includeSubDomains; preload | ||
Stripe-Version: | ||
- 2024-12-18.acacia | ||
Vary: | ||
- Origin | ||
X-Content-Type-Options: | ||
- nosniff | ||
X-Stripe-Priority-Routing-Enabled: | ||
- 'true' | ||
X-Stripe-Routing-Context-Priority-Tier: | ||
- api-testmode | ||
X-Wc: | ||
- AB | ||
status: | ||
code: 400 | ||
message: Bad Request | ||
version: 1 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this because it would now just be an extra DB call for a log lol