feat: Add subscription management system

- Add subscription fields to organizations (status, plan, trial_ends_at, etc.)
- Add subscription middleware for access control
- Add /auth/me returns subscription info
- Add admin endpoints for subscription management:
  - GET/PUT /admin/organizations/:id/subscription
  - POST /admin/organizations/:id/pause
  - POST /admin/organizations/:id/activate
  - POST /admin/organizations/:id/extend-trial
  - GET /admin/subscriptions (with filters)
- New orgs get 14-day trial automatically
This commit is contained in:
2026-03-13 05:58:00 +00:00
parent 6e421efef1
commit 40adeb15ee
5 changed files with 377 additions and 10 deletions

View File

@@ -46,7 +46,30 @@ async function runMigrations(client: ReturnType<Pool["connect"]> extends Promise
`;
console.log("✅ Migration: logo_url column checked");
} catch (e) {
// Column might already exist, that's fine
console.log(" Migration note:", e instanceof Error ? e.message : String(e));
}
// Add subscription fields to organizations
try {
await client.queryObject`
ALTER TABLE organizations
ADD COLUMN IF NOT EXISTS subscription_status TEXT DEFAULT 'trial',
ADD COLUMN IF NOT EXISTS subscription_plan TEXT DEFAULT 'starter',
ADD COLUMN IF NOT EXISTS trial_ends_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS subscription_ends_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS subscription_paused_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS subscription_pause_reason TEXT
`;
console.log("✅ Migration: subscription columns checked");
// Set trial_ends_at for existing orgs without it (14 days from now)
await client.queryObject`
UPDATE organizations
SET trial_ends_at = NOW() + INTERVAL '14 days'
WHERE trial_ends_at IS NULL AND subscription_status = 'trial'
`;
console.log("✅ Migration: trial dates initialized");
} catch (e) {
console.log(" Migration note:", e instanceof Error ? e.message : String(e));
}
}