Step 2f — archive the legacy plans instead of deleting them - #806
Draft
mitchelljkotler wants to merge 2 commits into
Draft
Step 2f — archive the legacy plans instead of deleting them#806mitchelljkotler wants to merge 2 commits into
mitchelljkotler wants to merge 2 commits into
Conversation
6 tasks
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 5, 2026 20:02
58a7876 to
11c49a8
Compare
mitchelljkotler
temporarily deployed
to
squarelet-pi-pricing-mo-7gefih
September 5, 2026 20:02
Inactive
7 tasks
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 8, 2026 20:07
11c49a8 to
c8b87a9
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 8, 2026 20:19
c8b87a9 to
23a8a85
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 8, 2026 20:43
23a8a85 to
e0e7035
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
2 times, most recently
from
September 9, 2026 16:31
2dab650 to
6cb8f5c
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 9, 2026 17:45
6cb8f5c to
ec1bce6
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 9, 2026 18:24
ec1bce6 to
649ce3f
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
2 times, most recently
from
September 9, 2026 19:25
2b0ed4b to
e98874f
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 9, 2026 20:34
e98874f to
cc9e588
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 9, 2026 22:09
cc9e588 to
4409699
Compare
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 10, 2026 02:19
4409699 to
111c888
Compare
Step 2f. A plan is finished once no live subscription sits on it and it has no active price: everyone has been moved off, and it cannot be bought because there is nothing to bill. The step was drafted as "delete the now-empty legacy row", and the database will not allow it. OrganizationChangeLog holds four PROTECT foreign keys to Plan and writes an entry on every subscription change, so any plan anyone ever subscribed to is referenced by history -- deleting the row would mean destroying the record of who used to be on what. SubscriptionItem.plan is CASCADE on top of that, so a plan still carrying cancelled lines would take them with it. Mitch's call, and the right one: a flag instead. Nothing here is worth losing for a shorter list, and archiving is reversible where a delete is not. It also removes the "no subscribers" trap -- the inventory column is *live* subscribers, so plans I had described as never-used may well have cancelled lines and history behind them. Cancelled lines therefore do not block archiving; they are the record, and they keep pointing at the archived plan quite happily. Only a live line or an active price does. Archived plans drop out of Plan.objects.choices(), including for an organization currently on one -- that clause matches the organization's own subscriptions, and would otherwise offer the plan back to exactly the people being moved off it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A seeded database has legacy plans of its own, so the run archives sixteen of them rather than the one the test made -- and the canonical-plan case was asserting against `<slug>-2`, because PlanFactory get-or-creates on name while slug is an AutoSlugField. Adopt the seeded row rather than making a second one, and assert on the plan in hand rather than on a global count.
mitchelljkotler
force-pushed
the
pricing-models-plan-archive
branch
from
September 10, 2026 02:42
111c888 to
2b27200
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Stacks on #805.
A plan is finished once no live subscription sits on it and it has no active price: everyone has been moved off, and it cannot be bought because there is nothing to bill.
Why archive rather than delete
The step was drafted as "delete the now-empty legacy row", and the database will not allow it:
OrganizationChangeLogholds four PROTECT foreign keys toPlanand writes an entry on every subscription change. Any plan anyone ever subscribed to is referenced by history — deleting the row destroys the record of who used to be on what.SubscriptionItem.planis CASCADE. A plan still carrying cancelled lines would take them with it.Also worth knowing: the plan inventory's "no subscribers" column is live subscribers, so rows that look never-used may well have cancelled lines and history behind them. Archiving sidesteps that question entirely, and is reversible where a delete is not.
What to look at
Plan.objects.choices()— including for an organization currently on one. That clause matches the organization's own subscriptions and would otherwise offer the plan back to exactly the people being moved off it.Plan.archived(0086_plan_archived), defaultFalse.QA
archive_legacy_plans --dry-runfirst. Plans reported "still in use" are not a failure — they mean 2d hasn't finished moving everyone off them.Then check the plan list on the purchase page is unchanged, and that an org on an archived plan isn't offered it at renewal.
🤖 Generated with Claude Code
https://claude.ai/code/session_0151rwxtvLg1vKEiz7XsJfzf