![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/public_html/ |
# Migration Guide: Calendar Month → Subscription Period-Based Usage ## What Changed The subscription system now tracks usage based on **individual subscription billing periods** instead of calendar months. ### Before (Calendar Month) - All users' limits reset on the 1st of each month - If you subscribed on Jan 15, you got usage for Jan 15-31, then reset on Feb 1 - Billing cycle and limit reset didn't align ### After (Subscription Period) - Each user's limit resets on their individual billing date - If you subscribe on Jan 15, your limit resets on Feb 15 (your next billing date) - Billing cycle and limit reset are perfectly aligned ## Migration Steps ### 1. Run Database Migration Run the migration script to update the database schema: ```bash php migrate_to_period_based_usage.php ``` Or visit: `https://soundstudiopro.com/migrate_to_period_based_usage.php` This will: - Add `subscription_period_start` column to `monthly_track_usage` - Add `subscription_id` column for easier tracking - Migrate existing usage records to use subscription periods - Update unique constraints ### 2. Update Cron Job Schedule The cron job is now a **backup check** that runs daily to ensure all subscriptions have usage records: **Old schedule:** `0 0 1 * *` (1st of month at midnight) **New schedule:** `0 2 * * *` (Daily at 2 AM) **Why daily?** The webhook automatically handles resets when subscriptions renew. The cron is just a safety net. ### 3. Verify Webhook is Working The webhook (`webhooks/stripe.php`) now automatically: - Creates usage records when subscriptions are created - Resets usage when subscriptions renew (subscription.updated event) Make sure your Stripe webhook is configured and receiving events. ## How It Works Now ### Subscription Creation 1. User subscribes → Stripe creates subscription 2. Webhook receives `customer.subscription.created` 3. System creates usage record for current subscription period 4. User can start using tracks immediately ### Subscription Renewal 1. Stripe renews subscription (new billing period starts) 2. Webhook receives `customer.subscription.updated` 3. System detects new `current_period_start` 4. Creates new usage record for new period (resets count to 0) 5. User's limit resets on their billing date ### Daily Cron Check 1. Runs daily at 2 AM 2. Checks all active subscriptions 3. Ensures each has a usage record for their current period 4. Creates missing records (backup in case webhook failed) ## Database Schema Changes ### monthly_track_usage Table **New columns:** - `subscription_id` INT - Links to user_subscriptions.id - `subscription_period_start` DATETIME - Start of subscription period (primary key for tracking) **Kept for compatibility:** - `year_month` VARCHAR(7) - Still populated but not used for tracking **New unique constraint:** - `unique_user_period (user_id, subscription_period_start)` - Ensures one record per user per period ## Testing Checklist - [ ] Run migration script successfully - [ ] Verify existing subscriptions have usage records - [ ] Test new subscription creation - [ ] Test subscription renewal (webhook) - [ ] Verify cron job runs and checks subscriptions - [ ] Check UI shows correct reset dates (billing date, not calendar month) - [ ] Verify track creation respects subscription period limits ## Rollback (If Needed) If you need to rollback to calendar month system: 1. Restore old helper functions from git 2. Restore old webhook handlers 3. Restore old cron job 4. The database columns can stay (they won't break anything) ## Benefits ✅ **Fair billing** - Users get full month's worth of tracks aligned with their billing ✅ **No confusion** - Limit resets on the same day they're billed ✅ **Better UX** - Clear messaging about when limits reset (billing date) ✅ **Automatic** - Webhooks handle everything, cron is just backup