Files
uldp-degree-mangement-system/scripts/2025_12_11_075500_booking.js
r2xrzh9q2z-lab d1b931d547 first commit
2026-02-02 11:07:09 +07:00

179 lines
5.5 KiB
JavaScript

const mongoose = require('mongoose');
const Booking = require('../models/booking');
const fs = require('fs');
const path = require('path');
require('dotenv').config();
const filePath = path.join(__dirname, '..', 'data', 'booking.json');
let raw = '{}';
try {
raw = fs.readFileSync(filePath, 'utf8');
} catch (e) {
console.error('Could not read booking.json at', filePath);
process.exit(2);
}
let data;
try {
data = JSON.parse(raw || '{}');
} catch (e) {
console.error('Invalid JSON in booking.json:', e.message);
process.exit(3);
}
// Remove _id fields recursively to avoid conflicts
function stripIds(obj) {
if (Array.isArray(obj)) return obj.map(i => stripIds(i));
if (obj && typeof obj === 'object') {
const out = {};
for (const k in obj) {
if (k !== '_id') out[k] = stripIds(obj[k]);
}
return out;
}
return obj;
}
data = stripIds(data);
// Normalize vouchers to an array of objects so Mongoose casting won't fail
function normalizeVouchers(doc) {
if (!doc) return;
// support root-level `vouchers` and `configuration.vouchers`
let v = doc.vouchers || (doc.configuration && doc.configuration.vouchers);
if (!v) return;
// Try to parse stringified arrays (may use single quotes or JS literal)
if (typeof v === 'string') {
try {
v = JSON.parse(v);
} catch (e1) {
try {
// try parsing JS object-literal style strings
// eslint-disable-next-line no-new-func
v = (new Function('return ' + v))();
} catch (e2) {
// fallback: attempt to extract codes by splitting on commas
v = v.split && v.split(',').map(s => s.trim()).filter(Boolean).map(s => ({ validCodes: s, type: 'unknown', value: null }));
}
}
}
// Normalize array items into objects
if (Array.isArray(v)) {
v = v.map(item => {
if (typeof item === 'string') return { validCodes: item, type: 'unknown', value: null };
if (item && typeof item === 'object') {
return {
validCodes: item.validCodes || item.code || '',
type: item.type || '',
value: typeof item.value === 'number' ? item.value : (item.amount && Number(item.amount)) || null,
};
}
return item;
});
}
// If Booking schema expects array of strings, convert objects -> string codes
try {
const Booking = require('../models/booking');
const pathType = Booking.schema.path('vouchers') || Booking.schema.path('configuration.vouchers');
if (pathType && pathType.instance === 'Array' && pathType.caster && pathType.caster.instance === 'String') {
const mapped = (v || []).map(it => (typeof it === 'string' ? it : (it && typeof it === 'object' ? it.validCodes || JSON.stringify(it) : String(it))));
if (doc.vouchers) doc.vouchers = mapped;
else if (doc.configuration) doc.configuration.vouchers = mapped;
return;
}
} catch (e) {
// ignore and keep object form
}
if (doc.vouchers) doc.vouchers = v;
else if (doc.configuration) doc.configuration.vouchers = v;
}
normalizeVouchers(data);
// Also normalize discounts (some inputs have them stringified or as objects)
function normalizeDiscounts(doc) {
if (!doc) return;
let d = doc.discounts || (doc.configuration && doc.configuration.discounts);
if (!d) return;
if (typeof d === 'string') {
try {
d = JSON.parse(d);
} catch (e1) {
try {
// eslint-disable-next-line no-new-func
d = (new Function('return ' + d))();
} catch (e2) {
d = d.split && d.split('\n').map(s => s.trim()).filter(Boolean).map(s => ({ id: '', name: s }));
}
}
}
if (Array.isArray(d)) {
d = d.map(item => {
if (typeof item === 'string') return { id: '', name: item };
if (item && typeof item === 'object') return item;
return item;
});
}
try {
const Booking = require('../models/booking');
const pathType = Booking.schema.path('discounts') || Booking.schema.path('configuration.discounts');
if (pathType && pathType.instance === 'Array' && pathType.caster && pathType.caster.instance === 'String') {
const mapped = (d || []).map(it => (typeof it === 'string' ? it : (it.id || it.name || JSON.stringify(it))));
if (doc.discounts) doc.discounts = mapped;
else if (doc.configuration) doc.configuration.discounts = mapped;
return;
}
} catch (e) {
// ignore
}
if (doc.discounts) doc.discounts = d;
else if (doc.configuration) doc.configuration.discounts = d;
}
normalizeDiscounts(data);
const dryRun = process.argv.includes('--dry-run') || process.argv.includes('-n');
async function run() {
try {
const dbUri = process.env.MONGODB_URI || process.env.MONGO_URL || 'mongodb://127.0.0.1:27017/cms';
console.log('Using DB URI:', dbUri);
if (dryRun) {
console.log('\nDRY RUN - preview of document to upsert:\n');
console.log(JSON.stringify(data, null, 2));
process.exit(0);
}
await mongoose.connect(dbUri, { useNewUrlParser: true, useUnifiedTopology: true });
console.log('Connected to MongoDB');
const result = await Booking.findOneAndUpdate({}, data, {
upsert: true,
new: true,
setDefaultsOnInsert: true,
});
console.log('Upsert complete. Document id:', result._id.toString());
console.log('Summary: programs=', (data.programs || []).length, 'camps=', (data.camps || []).length);
await mongoose.disconnect();
process.exit(0);
} catch (err) {
console.error('Migration failed:', err && err.message ? err.message : err);
process.exit(1);
}
}
run();