40227-vm/backend/src/db/migrations/20260612060000-frame-entries-tenant.ts

46 lines
1.5 KiB
TypeScript

import { DataTypes, type QueryInterface } from 'sequelize';
/**
* Per-tenant FRAME content (WS-B). FRAME entries become dedicated per tenant
* level — each of org / school / campus / class owns its own entries. Adds
* nullable `schoolId` and `classId`; the owning tenant is the most specific
* non-null of (classId, campusId, schoolId, organizationId). Idempotent.
*/
async function columnExists(
queryInterface: QueryInterface,
table: string,
column: string,
): Promise<boolean> {
const [results] = await queryInterface.sequelize.query(`
SELECT 1 FROM information_schema.columns
WHERE table_name = '${table}' AND column_name = '${column}'
`);
return (results as unknown[]).length > 0;
}
export default {
up: async (queryInterface: QueryInterface) => {
if (!(await columnExists(queryInterface, 'frame_entries', 'schoolId'))) {
await queryInterface.addColumn('frame_entries', 'schoolId', {
type: DataTypes.UUID,
allowNull: true,
});
}
if (!(await columnExists(queryInterface, 'frame_entries', 'classId'))) {
await queryInterface.addColumn('frame_entries', 'classId', {
type: DataTypes.UUID,
allowNull: true,
});
}
},
down: async (queryInterface: QueryInterface) => {
if (await columnExists(queryInterface, 'frame_entries', 'classId')) {
await queryInterface.removeColumn('frame_entries', 'classId');
}
if (await columnExists(queryInterface, 'frame_entries', 'schoolId')) {
await queryInterface.removeColumn('frame_entries', 'schoolId');
}
},
};