/** * One-time migration: Member.contributionTier (String: "0"|"5"|"15"|"30"|"50") → * Member.contributionAmount (Number). Idempotent: only acts on docs that still * have contributionTier; safe to re-run. * * Usage: * node scripts/migrate-contribution-amount.cjs # dry-run (default) * node scripts/migrate-contribution-amount.cjs --apply # writes changes */ require('dotenv').config() const mongoose = require('mongoose') async function run() { const apply = process.argv.includes('--apply') if (!process.env.MONGODB_URI) { console.error('MONGODB_URI not set in environment') process.exit(1) } await mongoose.connect(process.env.MONGODB_URI) const db = mongoose.connection.db const col = db.collection('members') // Count docs that still have the old field const legacyCount = await col.countDocuments({ contributionTier: { $exists: true } }) console.log(`Found ${legacyCount} members with legacy contributionTier`) if (legacyCount === 0) { console.log('Nothing to migrate.') await mongoose.disconnect() return } const cursor = col.find({ contributionTier: { $exists: true } }) let updated = 0 let skipped = 0 while (await cursor.hasNext()) { const doc = await cursor.next() const raw = doc.contributionTier const amount = parseInt(raw, 10) if (!Number.isInteger(amount) || amount < 0) { console.warn(` SKIP ${doc._id}: cannot parse contributionTier=${JSON.stringify(raw)}`) skipped++ continue } if (apply) { await col.updateOne( { _id: doc._id }, { $set: { contributionAmount: amount }, $unset: { contributionTier: '' } }, ) } updated++ } console.log(`${apply ? 'Updated' : 'Would update'} ${updated} documents, skipped ${skipped}`) if (!apply) console.log('Dry-run complete. Re-run with --apply to write changes.') await mongoose.disconnect() } run().catch(async (err) => { console.error(err) try { await mongoose.disconnect() } catch {} process.exit(1) })