90 lines
3.2 KiB
JavaScript
90 lines
3.2 KiB
JavaScript
/**
|
|
* Backfill tenant fields for multi-tenant consistency (run BEFORE deploying required schema).
|
|
* - Form.tenantOrganization from linked Event.organization
|
|
* - FormSubmission.tenantOrganization from parent Form
|
|
* - Logs Speaker rows missing organization (fix manually or delete)
|
|
*
|
|
* Run: cd backend && npm run backfill:tenant-organization
|
|
*/
|
|
const path = require('path');
|
|
|
|
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
|
|
const mongoose = require('mongoose');
|
|
const Form = require(path.join(__dirname, '..', 'src', 'models', 'Form'));
|
|
const FormSubmission = require(path.join(__dirname, '..', 'src', 'models', 'FormSubmission'));
|
|
const Event = require(path.join(__dirname, '..', 'src', 'models', 'Event'));
|
|
const Speaker = require(path.join(__dirname, '..', 'src', 'models', 'Speaker'));
|
|
|
|
async function run() {
|
|
const uri = process.env.MONGODB_URI;
|
|
if (!uri) {
|
|
console.error('MONGODB_URI is not set');
|
|
process.exit(1);
|
|
}
|
|
await mongoose.connect(uri);
|
|
|
|
const formsNeedingTenant = await Form.find({
|
|
$or: [{ tenantOrganization: { $exists: false } }, { tenantOrganization: null }],
|
|
})
|
|
.select('_id event')
|
|
.lean();
|
|
|
|
let formsUpdated = 0;
|
|
for (const f of formsNeedingTenant) {
|
|
if (!f.event) {
|
|
console.warn(`Form ${f._id} has no event and no tenantOrganization — skipped`);
|
|
continue;
|
|
}
|
|
const ev = await Event.findById(f.event).select('organization').lean();
|
|
if (!ev?.organization) {
|
|
console.warn(`Form ${f._id} event ${f.event} has no organization — skipped`);
|
|
continue;
|
|
}
|
|
await Form.updateOne({ _id: f._id }, { $set: { tenantOrganization: ev.organization } });
|
|
formsUpdated += 1;
|
|
}
|
|
console.log(`Backfilled tenantOrganization on ${formsUpdated} form(s).`);
|
|
|
|
const subsNeedingTenant = await FormSubmission.find({
|
|
$or: [{ tenantOrganization: { $exists: false } }, { tenantOrganization: null }],
|
|
})
|
|
.select('_id form')
|
|
.lean();
|
|
|
|
let subsUpdated = 0;
|
|
for (const s of subsNeedingTenant) {
|
|
const form = await Form.findById(s.form).select('tenantOrganization').lean();
|
|
if (!form?.tenantOrganization) {
|
|
console.warn(`Submission ${s._id} form ${s.form} has no tenantOrganization — skipped`);
|
|
continue;
|
|
}
|
|
await FormSubmission.updateOne({ _id: s._id }, { $set: { tenantOrganization: form.tenantOrganization } });
|
|
subsUpdated += 1;
|
|
}
|
|
console.log(`Backfilled tenantOrganization on ${subsUpdated} form submission(s).`);
|
|
|
|
const orphanSpeakers = await Speaker.countDocuments({
|
|
$or: [{ organization: { $exists: false } }, { organization: null }],
|
|
});
|
|
if (orphanSpeakers > 0) {
|
|
console.warn(
|
|
`${orphanSpeakers} speaker(s) have no organization — assign org or delete before schema requires it.`,
|
|
);
|
|
const sample = await Speaker.find({ $or: [{ organization: { $exists: false } }, { organization: null }] })
|
|
.select('_id email firstName lastName')
|
|
.limit(10)
|
|
.lean();
|
|
console.warn('Sample:', JSON.stringify(sample, null, 2));
|
|
} else {
|
|
console.log('All speakers have an organization.');
|
|
}
|
|
|
|
await mongoose.disconnect();
|
|
console.log('Done.');
|
|
}
|
|
|
|
run().catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
});
|