feat: replace tenants with organization management
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { uuidV7 } from '../common/uuid-v7';
|
||||
|
||||
@Injectable()
|
||||
export class DatabaseMigrationsService implements OnApplicationBootstrap {
|
||||
@@ -8,9 +9,129 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
|
||||
constructor(private readonly dataSource: DataSource) {}
|
||||
|
||||
async onApplicationBootstrap(): Promise<void> {
|
||||
await this.backfillOrganizations();
|
||||
await this.normalizeClassDates();
|
||||
}
|
||||
|
||||
private async backfillOrganizations(): Promise<void> {
|
||||
const runner = this.dataSource.createQueryRunner();
|
||||
await runner.connect();
|
||||
try {
|
||||
const tables = await runner.getTables([
|
||||
'tenants',
|
||||
'organizations',
|
||||
'students',
|
||||
'occupancies',
|
||||
'classroom_rentals',
|
||||
]);
|
||||
const tableNames = new Set(tables.map((table) => table.name));
|
||||
if (!tableNames.has('organizations')) return;
|
||||
|
||||
const organizationRows = () =>
|
||||
runner.query('SELECT * FROM organizations WHERE is_host = 1 LIMIT 1');
|
||||
let host = (await organizationRows())[0];
|
||||
if (!host) {
|
||||
await runner.query(
|
||||
`INSERT INTO organizations (public_id, code, name, is_host, color, notes, status, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
|
||||
[
|
||||
uuidV7(),
|
||||
'HOST',
|
||||
process.env.HOST_ORGANIZATION_NAME || '本机构',
|
||||
1,
|
||||
'#1677ff',
|
||||
'系统默认运营主体',
|
||||
'active',
|
||||
],
|
||||
);
|
||||
host = (await organizationRows())[0];
|
||||
}
|
||||
if (!host) return;
|
||||
|
||||
if (tableNames.has('tenants')) {
|
||||
const legacyTenants: Array<Record<string, unknown>> =
|
||||
await runner.query('SELECT * FROM tenants');
|
||||
for (const legacy of legacyTenants) {
|
||||
const name = String(legacy.name || '').trim();
|
||||
if (!name) continue;
|
||||
let external = (
|
||||
await runner.query('SELECT * FROM organizations WHERE name = ? LIMIT 1', [name])
|
||||
)[0];
|
||||
if (!external) {
|
||||
await runner.query(
|
||||
`INSERT INTO organizations (public_id, code, name, is_host, contact_name, phone, color, notes, status, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`,
|
||||
[
|
||||
uuidV7(),
|
||||
`ORG_${legacy.id}`,
|
||||
name,
|
||||
0,
|
||||
legacy.contact || null,
|
||||
legacy.phone || null,
|
||||
legacy.color || null,
|
||||
legacy.notes || null,
|
||||
legacy.status || 'active',
|
||||
],
|
||||
);
|
||||
external = (
|
||||
await runner.query('SELECT * FROM organizations WHERE name = ? LIMIT 1', [name])
|
||||
)[0];
|
||||
}
|
||||
if (!external) continue;
|
||||
if (tableNames.has('students')) {
|
||||
await runner
|
||||
.query(
|
||||
'UPDATE students SET organization_id = ? WHERE organization_id IS NULL AND tenant_id = ?',
|
||||
[external.id, legacy.id],
|
||||
)
|
||||
.catch(() => undefined);
|
||||
}
|
||||
if (tableNames.has('occupancies')) {
|
||||
await runner
|
||||
.query(
|
||||
'UPDATE occupancies SET responsible_organization_id = ? WHERE responsible_organization_id IS NULL AND tenant_id = ?',
|
||||
[external.id, legacy.id],
|
||||
)
|
||||
.catch(() => undefined);
|
||||
}
|
||||
if (tableNames.has('classroom_rentals')) {
|
||||
await runner
|
||||
.query(
|
||||
'UPDATE classroom_rentals SET lessee_organization_id = ?, lessor_organization_id = ? WHERE lessee_organization_id IS NULL AND tenant_id = ?',
|
||||
[external.id, host.id, legacy.id],
|
||||
)
|
||||
.catch(() => undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tableNames.has('students')) {
|
||||
await runner.query(
|
||||
'UPDATE students SET organization_id = ? WHERE organization_id IS NULL',
|
||||
[host.id],
|
||||
);
|
||||
}
|
||||
if (tableNames.has('occupancies')) {
|
||||
await runner.query(
|
||||
`UPDATE occupancies
|
||||
SET responsible_organization_id = COALESCE(
|
||||
(SELECT organization_id FROM students WHERE students.id = occupancies.student_id), ?
|
||||
)
|
||||
WHERE responsible_organization_id IS NULL`,
|
||||
[host.id],
|
||||
);
|
||||
}
|
||||
if (tableNames.has('classroom_rentals')) {
|
||||
await runner.query(
|
||||
'UPDATE classroom_rentals SET lessor_organization_id = ? WHERE lessor_organization_id IS NULL',
|
||||
[host.id],
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
await runner.release();
|
||||
}
|
||||
}
|
||||
|
||||
private async normalizeClassDates(): Promise<void> {
|
||||
const driver = this.dataSource.options.type;
|
||||
const dateExpression = (column: string) =>
|
||||
|
||||
Reference in New Issue
Block a user