/** * Seed subscription plans (FREE, AGENT_PRO, INVESTOR, ENTERPRISE). * * Usage: npx tsx scripts/seed-plans.ts * Idempotent: uses upsert on PlanTier unique constraint. */ import { PrismaClient, PlanTier } from '@prisma/client'; const prisma = new PrismaClient(); export const PLANS = [ { tier: PlanTier.FREE, name: 'Miễn phí', priceMonthlyVND: BigInt(0), priceYearlyVND: BigInt(0), maxListings: 3, maxSavedSearches: 5, features: { basicSearch: true, listingPost: true, maxPhotos: 5, analytics: false, prioritySupport: false, aiValuation: false, featuredListing: false, }, }, { tier: PlanTier.AGENT_PRO, name: 'Agent Pro', priceMonthlyVND: BigInt(499_000), priceYearlyVND: BigInt(4_990_000), maxListings: 50, maxSavedSearches: 30, features: { basicSearch: true, listingPost: true, maxPhotos: 30, analytics: true, prioritySupport: true, aiValuation: true, featuredListing: true, leadManagement: true, agentProfile: true, }, }, { tier: PlanTier.INVESTOR, name: 'Investor', priceMonthlyVND: BigInt(999_000), priceYearlyVND: BigInt(9_990_000), maxListings: 20, maxSavedSearches: 100, features: { basicSearch: true, listingPost: true, maxPhotos: 15, analytics: true, prioritySupport: true, aiValuation: true, featuredListing: false, marketReports: true, priceAlerts: true, portfolioTracking: true, }, }, { tier: PlanTier.ENTERPRISE, name: 'Enterprise', priceMonthlyVND: BigInt(4_990_000), priceYearlyVND: BigInt(49_900_000), maxListings: null, maxSavedSearches: null, features: { basicSearch: true, listingPost: true, maxPhotos: 100, analytics: true, prioritySupport: true, aiValuation: true, featuredListing: true, leadManagement: true, agentProfile: true, marketReports: true, priceAlerts: true, portfolioTracking: true, apiAccess: true, whiteLabel: true, dedicatedSupport: true, }, }, ]; async function seedPlans() { console.log('Seeding subscription plans...\n'); for (const plan of PLANS) { const _result = await prisma.plan.upsert({ where: { tier: plan.tier }, update: { name: plan.name, priceMonthlyVND: plan.priceMonthlyVND, priceYearlyVND: plan.priceYearlyVND, maxListings: plan.maxListings, maxSavedSearches: plan.maxSavedSearches, features: plan.features, }, create: plan, }); const monthly = Number(plan.priceMonthlyVND).toLocaleString('vi-VN'); console.log(` ${plan.tier.padEnd(12)} ${plan.name.padEnd(14)} ${monthly} VND/tháng`); } console.log(`\n${PLANS.length} plans seeded.`); } if (require.main === module) { seedPlans() .catch((e) => { console.error('Seed plans failed:', e); process.exit(1); }) .finally(() => prisma.$disconnect()); } export { seedPlans };