feat: replace tenants with organization management

This commit is contained in:
2026-07-10 21:27:26 +08:00
parent 8ed1682b90
commit 8f0991a51f
49 changed files with 1292 additions and 698 deletions

View File

@@ -16,7 +16,7 @@ import {
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Tenant } from '../entities/tenant.entity';
import { Organization } from '../entities/organization.entity';
import { ClassTeacher } from '../entities/class-teacher.entity';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
@@ -34,7 +34,7 @@ export class StudentsController {
constructor(
private service: StudentsService,
private logService: OperationLogsService,
@InjectRepository(Tenant) private tenantRepo: Repository<Tenant>,
@InjectRepository(Organization) private organizationRepo: Repository<Organization>,
) {}
private canManageAllStudents(user: { isSuperAdmin?: boolean; permissions?: string[] }): boolean {
@@ -51,7 +51,7 @@ export class StudentsController {
@Query('name') name: string | undefined,
@Query('status') status: string | undefined,
@Query('includeArchived') includeArchived: string | undefined,
@Query('tenantId') tenantId: string | undefined,
@Query('organizationId') organizationId: string | undefined,
@Request() req: { user: { id: number; isSuperAdmin?: boolean; permissions?: string[] } },
) {
const classIds = await this.service.getAccessibleClassIds(
@@ -63,7 +63,7 @@ export class StudentsController {
name,
status,
includeArchived: includeArchived === 'true',
tenantId: tenantId ? +tenantId : undefined,
organizationId: organizationId ? +organizationId : undefined,
},
classIds,
);
@@ -94,7 +94,7 @@ export class StudentsController {
{ header: '民族', key: 'ethnicity', width: 10 },
{ header: '紧急联系人', key: 'emergencyContact', width: 15 },
{ header: '紧急联系人电话', key: 'emergencyPhone', width: 18 },
{ header: '所属机构', key: 'tenant', width: 18 },
{ header: '所属机构', key: 'organization', width: 18 },
{ header: '负责人/班主任', key: 'supervisor', width: 15 },
{ header: '状态', key: 'status', width: 10 },
];
@@ -115,7 +115,7 @@ export class StudentsController {
ethnicity: s.ethnicity || '',
emergencyContact: s.emergencyContact || '',
emergencyPhone: s.emergencyPhone || '',
tenant: s.tenant?.name || '',
organization: s.organization?.name || '',
supervisor: s.supervisor || '',
status: statusMap[s.status] || s.status,
});
@@ -152,7 +152,7 @@ export class StudentsController {
{ header: '民族', key: 'ethnicity', width: 10 },
{ header: '紧急联系人', key: 'emergencyContact', width: 15 },
{ header: '紧急联系人电话', key: 'emergencyPhone', width: 18 },
{ header: '所属机构(租赁方名称', key: 'tenant', width: 18 },
{ header: '所属机构名称', key: 'organization', width: 18 },
{ header: '负责人/班主任', key: 'supervisor', width: 15 },
];
ws.getRow(1).font = { bold: true };
@@ -165,7 +165,7 @@ export class StudentsController {
ethnicity: '汉族',
emergencyContact: '张父',
emergencyPhone: '13900000000',
tenant: 'XX教育公司',
organization: 'XX教育公司',
supervisor: '',
});
res.setHeader(
@@ -290,9 +290,9 @@ export class StudentsController {
ethnicity?: string;
emergencyContact?: string;
emergencyPhone?: string;
tenant?: string;
organization?: string;
supervisor?: string;
tenantId?: number;
organizationId?: number;
}[] = [];
ws.eachRow((row, idx) => {
if (idx === 1) return;
@@ -304,16 +304,18 @@ export class StudentsController {
ethnicity: String(row.getCell(5).value || '').trim() || undefined,
emergencyContact: String(row.getCell(6).value || '').trim() || undefined,
emergencyPhone: String(row.getCell(7).value || '').trim() || undefined,
tenant: String(row.getCell(8).value || '').trim() || undefined,
organization: String(row.getCell(8).value || '').trim() || undefined,
supervisor: String(row.getCell(9).value || '').trim() || undefined,
});
});
// Resolve tenant names to IDs
// Resolve organization names to IDs
for (const row of rows) {
if (row.tenant) {
const tenant = await this.tenantRepo.findOne({ where: { name: row.tenant } });
if (tenant) {
row.tenantId = tenant.id;
if (row.organization) {
const organization = await this.organizationRepo.findOne({
where: { name: row.organization },
});
if (organization) {
row.organizationId = organization.id;
}
}
}
@@ -348,7 +350,7 @@ export class StudentsController {
emergencyPhone?: string;
organization?: string;
supervisor?: string;
tenantId?: number;
organizationId?: number;
}[] = [];
ws.eachRow((row, idx) => {
if (idx === 1) return;
@@ -364,11 +366,13 @@ export class StudentsController {
supervisor: String(row.getCell(9).value || '').trim() || undefined,
});
});
// Resolve tenant names to IDs
// Resolve organization names to IDs
for (const row of rows) {
if (row.organization) {
const tenant = await this.tenantRepo.findOne({ where: { name: row.organization } });
if (tenant) row.tenantId = tenant.id;
const organization = await this.organizationRepo.findOne({
where: { name: row.organization },
});
if (organization) row.organizationId = organization.id;
}
}
const result = await this.service.matchImport(rows);