mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
7.6 KiB
7.6 KiB
Subscription Multi-Buzz Type Migration Plan
Overview
Enable users to have multiple subscriptions (one per buzz type) instead of the current single subscription per user.
Current State
Database Schema
CustomerSubscriptiontable hasuserIdwith@uniqueconstraint- This prevents users from having multiple subscriptions
- Products already have
buzzTypein their metadata (yellow, green, blue, red)
Code Dependencies
- Creator program checks for active membership
- Subscription queries assume single subscription per user
- User tier is derived from product metadata
tierfield
Migration Strategy
Phase 1: Database Schema Changes
1. Remove Unique Constraint on userId
model CustomerSubscription {
id String @id
userId Int // Remove @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
buzzType String // Add new field
// ... rest of fields
@@unique([userId, buzzType]) // New composite unique constraint
}
Migration Steps:
- Add
buzzTypecolumn (nullable first for existing data) - Backfill existing subscriptions with buzzType from product metadata
- Add composite unique constraint on
[userId, buzzType] - Make
buzzTypenon-nullable - Drop old
userIdunique constraint
2. Migration Script Considerations
- Existing subscriptions need to be assigned a buzzType
- Default to 'yellow' for existing subscriptions
- Use product metadata
buzzTypeif available
Phase 2: Code Updates
1. Creator Program Service Updates
Current:
const activeMembership = await dbWrite.customerSubscription.findFirst({
where: {
userId,
status: 'active',
currentPeriodEnd: { gt: new Date() },
},
});
Updated:
const activeMembership = await dbWrite.customerSubscription.findFirst({
where: {
userId,
buzzType, // Filter by specific buzz type
status: 'active',
currentPeriodEnd: { gt: new Date() },
},
});
Files to Update:
src/server/services/creator-program.service.tsbankBuzz()- Check membership for specific buzzTypeuserCapCachelookupFn - Filter subscriptions by buzzTypegetCreatorRequirements()- May need to accept buzzType parameter
2. Subscription Service Updates
Files to Update:
src/server/services/subscriptions.service.tsgetUserSubscription()- Add buzzType parameter- All queries that fetch subscriptions need buzzType filter
3. User Service Updates
Files to Update:
src/server/services/user.service.ts- Update tier derivation to consider buzzType
- May need helper:
getUserTierForBuzzType(userId, buzzType)
4. Stripe/Paddle Service Updates
Files to Update:
src/server/services/stripe.service.tssrc/server/services/paddle.service.ts- Need to handle multiple active subscriptions per user
- Product metadata already contains
buzzType
5. Frontend Updates
Files to Update:
src/components/Subscriptions/*.tsx- Membership management UI needs to show multiple subscriptions
- Each subscription card should display its buzzType
- Allow managing each subscription independently
Phase 3: Creator Program Integration
1. Membership Checks per BuzzType
Update functions that check membership:
bankBuzz(userId, amount, buzzType)- Check membership for that buzzTypegetCreatorRequirements(userId, buzzType?)- Get requirements per buzzType or aggregate
2. Cap Calculations per BuzzType
userCapCachealready separated by buzzType- Ensure tier lookup considers correct buzzType subscription
Phase 4: Backward Compatibility
1. Helper Functions
Create helpers for common patterns:
// Get user's subscription for specific buzzType
async function getUserSubscriptionForBuzzType(userId: number, buzzType: BuzzSpendType)
// Get user's tier for specific buzzType
async function getUserTierForBuzzType(userId: number, buzzType: BuzzSpendType)
// Check if user has active membership for buzzType
async function hasActiveMembershipForBuzzType(userId: number, buzzType: BuzzSpendType)
// Get all active subscriptions for user
async function getUserActiveSubscriptions(userId: number)
2. Migration Period Support
- Existing code that doesn't pass buzzType should default to yellow
- Log warnings when buzzType is not specified
- Phase out over time
Implementation Order
-
✅ Database Migration (highest priority)
- Add buzzType column
- Backfill data
- Add composite constraint
- Remove old constraint
-
Core Service Updates
- Update subscription queries with buzzType filter
- Add helper functions
- Update creator program membership checks
-
Payment Provider Updates
- Stripe subscription handling
- Paddle subscription handling
- Ensure product metadata buzzType is used
-
Frontend Updates
- Subscription management UI
- Display multiple subscriptions
- Creator program UI (already done)
-
Testing & Validation
- Test multiple subscriptions per user
- Test creator program with different buzzTypes
- Test subscription upgrades/downgrades
Additional Considerations from Review
Session Management
Current State:
- Session stores single tier and
isMemberstatus - Derived from single subscription
Required Changes:
// Current session
interface Session {
tier: string;
isMember: boolean;
}
// New session structure
interface Session {
subscriptions: {
[buzzType: string]: {
tier: string;
isMember: boolean;
}
}
// Helper computed properties for backward compatibility
tier: string; // Highest tier across all subscriptions
isMember: boolean; // Has any active membership
}
Subscription Hooks
Files to Update:
src/hooks/useCurrentUser.ts- Access subscription by buzzTypesrc/components/Stripe/memberships.util.ts- Update hooks- Need hooks like:
useSubscriptionForBuzzType(buzzType)useAllUserSubscriptions()useHasMembershipForBuzzType(buzzType)
Pricing Page
Files to Update:
src/pages/pricing/index.tsxsrc/components/Purchase/MembershipPlans.tsxsrc/components/Purchase/GreenMembershipPlans.tsx
Changes Needed:
- Filter products by domain buzzType
- Show only yellow buzz subscriptions on main domain
- Show only green buzz subscriptions on green domain
- Display current subscription status per buzzType
Risks & Considerations
-
Data Migration
- Existing subscriptions must be correctly assigned buzzType
- Need to validate product metadata has buzzType
-
Multiple Active Subscriptions
- Users could have multiple active subscriptions
- Billing implications need consideration
- UI needs to clearly show which subscription is for what
-
Creator Program
- Cap calculations per buzzType
- Banking requires active membership for that buzzType
- Need clear messaging to users
-
Payment Providers
- Ensure they handle multiple subscriptions correctly
- Webhooks need to handle multiple subscriptions
- Cancellation/changes need to target correct subscription
Rollout Strategy
- Week 1: Database migration + basic service updates
- Week 2: Payment provider updates + testing
- Week 3: Frontend updates + extensive testing
- Week 4: Gradual rollout with monitoring
@dev: Please review this plan. Key questions:
- Should we support multiple subscriptions immediately or phase it in?
- What should be the default buzzType for existing subscriptions?
- Do we want users to be able to have multiple active subscriptions or just one at a time?