feat: add college archive fields
This commit is contained in:
@@ -59,6 +59,8 @@ interface StudentInfo {
|
|||||||
interface ProfileData {
|
interface ProfileData {
|
||||||
targetCollege?: string;
|
targetCollege?: string;
|
||||||
targetMajor?: string;
|
targetMajor?: string;
|
||||||
|
collegeSchool?: string;
|
||||||
|
collegeMajor?: string;
|
||||||
subjectDirection?: string;
|
subjectDirection?: string;
|
||||||
grade?: string;
|
grade?: string;
|
||||||
profileDate?: string;
|
profileDate?: string;
|
||||||
@@ -481,6 +483,24 @@ const InlineArchiveSummary: React.FC<{
|
|||||||
{profile?.targetMajor || '-'}
|
{profile?.targetMajor || '-'}
|
||||||
</EditableCell>
|
</EditableCell>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="大专院校">
|
||||||
|
<EditableCell
|
||||||
|
value={profile?.collegeSchool}
|
||||||
|
permission="student:edit"
|
||||||
|
onSave={(next) => saveProfile('collegeSchool', next)}
|
||||||
|
>
|
||||||
|
{profile?.collegeSchool || '-'}
|
||||||
|
</EditableCell>
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="大专专业">
|
||||||
|
<EditableCell
|
||||||
|
value={profile?.collegeMajor}
|
||||||
|
permission="student:edit"
|
||||||
|
onSave={(next) => saveProfile('collegeMajor', next)}
|
||||||
|
>
|
||||||
|
{profile?.collegeMajor || '-'}
|
||||||
|
</EditableCell>
|
||||||
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="选科方向">
|
<Descriptions.Item label="选科方向">
|
||||||
<EditableCell
|
<EditableCell
|
||||||
value={profile?.subjectDirection}
|
value={profile?.subjectDirection}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ async function main() {
|
|||||||
supervisor: '',
|
supervisor: '',
|
||||||
targetCollege: `目标院校${(i % 20) + 1}`,
|
targetCollege: `目标院校${(i % 20) + 1}`,
|
||||||
targetMajor: `目标专业${(i % 10) + 1}`,
|
targetMajor: `目标专业${(i % 10) + 1}`,
|
||||||
|
collegeSchool: `大专院校${(i % 12) + 1}`,
|
||||||
|
collegeMajor: `大专专业${(i % 8) + 1}`,
|
||||||
subjectDirection: ['物化生', '物化地', '史政地'][i % 3],
|
subjectDirection: ['物化生', '物化地', '史政地'][i % 3],
|
||||||
grade: '高三',
|
grade: '高三',
|
||||||
profileDate: '2024-09-01',
|
profileDate: '2024-09-01',
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { IsOptional, IsString, IsNumber, IsDateString, IsNotEmpty, Min } from 'c
|
|||||||
export class UpsertProfileDto {
|
export class UpsertProfileDto {
|
||||||
@IsOptional() @IsString() targetCollege?: string;
|
@IsOptional() @IsString() targetCollege?: string;
|
||||||
@IsOptional() @IsString() targetMajor?: string;
|
@IsOptional() @IsString() targetMajor?: string;
|
||||||
|
@IsOptional() @IsString() collegeSchool?: string;
|
||||||
|
@IsOptional() @IsString() collegeMajor?: string;
|
||||||
@IsOptional() @IsString() subjectDirection?: string;
|
@IsOptional() @IsString() subjectDirection?: string;
|
||||||
@IsOptional() @IsString() grade?: string;
|
@IsOptional() @IsString() grade?: string;
|
||||||
@IsOptional() @IsDateString() profileDate?: string;
|
@IsOptional() @IsDateString() profileDate?: string;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
|
|||||||
async onApplicationBootstrap(): Promise<void> {
|
async onApplicationBootstrap(): Promise<void> {
|
||||||
await this.ensureAiConfigTable();
|
await this.ensureAiConfigTable();
|
||||||
await this.ensureSyncStateLeaseColumns();
|
await this.ensureSyncStateLeaseColumns();
|
||||||
|
await this.ensureStudentProfileCollegeColumns();
|
||||||
await this.ensureCourseAttendanceSchema();
|
await this.ensureCourseAttendanceSchema();
|
||||||
await this.ensureAttendanceDevicesSchema();
|
await this.ensureAttendanceDevicesSchema();
|
||||||
await this.ensureStudentWalletSchema();
|
await this.ensureStudentWalletSchema();
|
||||||
@@ -42,6 +43,25 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ensureStudentProfileCollegeColumns(): Promise<void> {
|
||||||
|
const runner = this.dataSource.createQueryRunner();
|
||||||
|
await runner.connect();
|
||||||
|
try {
|
||||||
|
const table = await runner.getTable('student_profiles');
|
||||||
|
if (!table) return;
|
||||||
|
const columns = new Set(table.columns.map((column) => column.name));
|
||||||
|
const additions: Array<[string, string]> = [
|
||||||
|
['college_school', 'VARCHAR(100)'],
|
||||||
|
['college_major', 'VARCHAR(100)'],
|
||||||
|
];
|
||||||
|
for (const [name, definition] of additions) {
|
||||||
|
if (!columns.has(name)) await runner.query(`ALTER TABLE student_profiles ADD COLUMN ${name} ${definition}`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await runner.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async ensureAttendanceDevicesSchema(): Promise<void> {
|
private async ensureAttendanceDevicesSchema(): Promise<void> {
|
||||||
const runner = this.dataSource.createQueryRunner();
|
const runner = this.dataSource.createQueryRunner();
|
||||||
await runner.connect();
|
await runner.connect();
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ export class StudentProfile {
|
|||||||
@Column({ name: 'target_major', length: 100, nullable: true })
|
@Column({ name: 'target_major', length: 100, nullable: true })
|
||||||
targetMajor: string;
|
targetMajor: string;
|
||||||
|
|
||||||
|
@Column({ name: 'college_school', length: 100, nullable: true })
|
||||||
|
collegeSchool: string;
|
||||||
|
|
||||||
|
@Column({ name: 'college_major', length: 100, nullable: true })
|
||||||
|
collegeMajor: string;
|
||||||
|
|
||||||
@Column({ name: 'subject_direction', length: 50, nullable: true })
|
@Column({ name: 'subject_direction', length: 50, nullable: true })
|
||||||
subjectDirection: string;
|
subjectDirection: string;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class InitialSchema1784520727860 implements MigrationInterface {
|
|||||||
await queryRunner.query(`CREATE TABLE \`bills\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`period_start\` date NOT NULL, \`period_end\` date NOT NULL, \`shared_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`personal_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`total_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`source\` varchar(30) NOT NULL DEFAULT 'batch', \`paid_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`outstanding_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`status\` varchar(20) NOT NULL DEFAULT 'unpaid', \`cancelled_at\` datetime NULL, \`cancel_reason\` varchar(300) NULL, \`generated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`bills\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`period_start\` date NOT NULL, \`period_end\` date NOT NULL, \`shared_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`personal_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`total_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`source\` varchar(30) NOT NULL DEFAULT 'batch', \`paid_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`outstanding_amount\` decimal(10,2) NOT NULL DEFAULT '0.00', \`status\` varchar(20) NOT NULL DEFAULT 'unpaid', \`cancelled_at\` datetime NULL, \`cancel_reason\` varchar(300) NULL, \`generated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
await queryRunner.query(`CREATE TABLE \`students\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(50) NOT NULL, \`student_no\` varchar(30) NULL, \`phone\` varchar(20) NULL, \`id_number\` varchar(30) NULL, \`gender\` varchar(10) NULL, \`ethnicity\` varchar(20) NULL, \`emergency_contact\` varchar(50) NULL, \`emergency_phone\` varchar(20) NULL, \`status\` varchar(20) NOT NULL DEFAULT 'active', \`supervisor\` varchar(50) NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`user_id\` int NULL, \`organization_id\` int NULL, UNIQUE INDEX \`IDX_fb3eff90b11bddf7285f9b4e28\` (\`user_id\`), UNIQUE INDEX \`REL_fb3eff90b11bddf7285f9b4e28\` (\`user_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`students\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(50) NOT NULL, \`student_no\` varchar(30) NULL, \`phone\` varchar(20) NULL, \`id_number\` varchar(30) NULL, \`gender\` varchar(10) NULL, \`ethnicity\` varchar(20) NULL, \`emergency_contact\` varchar(50) NULL, \`emergency_phone\` varchar(20) NULL, \`status\` varchar(20) NOT NULL DEFAULT 'active', \`supervisor\` varchar(50) NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`user_id\` int NULL, \`organization_id\` int NULL, UNIQUE INDEX \`IDX_fb3eff90b11bddf7285f9b4e28\` (\`user_id\`), UNIQUE INDEX \`REL_fb3eff90b11bddf7285f9b4e28\` (\`user_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
await queryRunner.query(`CREATE TABLE \`student_wallets\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`balance\` decimal(12,2) NOT NULL DEFAULT '0.00', \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_07a434ad1a960d506386754d59\` (\`student_id\`), UNIQUE INDEX \`REL_07a434ad1a960d506386754d59\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`student_wallets\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`balance\` decimal(12,2) NOT NULL DEFAULT '0.00', \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_07a434ad1a960d506386754d59\` (\`student_id\`), UNIQUE INDEX \`REL_07a434ad1a960d506386754d59\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
await queryRunner.query(`CREATE TABLE \`student_profiles\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`target_college\` varchar(100) NULL, \`target_major\` varchar(100) NULL, \`subject_direction\` varchar(50) NULL, \`grade\` varchar(20) NULL, \`profile_date\` date NULL, \`notes\` text NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_4cedc08d3dc1f2c2da8a12f7a8\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`student_profiles\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`target_college\` varchar(100) NULL, \`target_major\` varchar(100) NULL, \`college_school\` varchar(100) NULL, \`college_major\` varchar(100) NULL, \`subject_direction\` varchar(50) NULL, \`grade\` varchar(20) NULL, \`profile_date\` date NULL, \`notes\` text NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_4cedc08d3dc1f2c2da8a12f7a8\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
await queryRunner.query(`CREATE TABLE \`student_enrollments\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`course_category\` varchar(50) NULL, \`class_type\` varchar(50) NULL, \`class_name\` varchar(100) NULL, \`head_teacher\` varchar(50) NULL, \`subject_teacher\` varchar(50) NULL, \`start_date\` date NULL, \`end_date\` date NULL, \`status\` varchar(20) NOT NULL DEFAULT 'active', \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`student_enrollments\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`course_category\` varchar(50) NULL, \`class_type\` varchar(50) NULL, \`class_name\` varchar(100) NULL, \`head_teacher\` varchar(50) NULL, \`subject_teacher\` varchar(50) NULL, \`start_date\` date NULL, \`end_date\` date NULL, \`status\` varchar(20) NOT NULL DEFAULT 'active', \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
await queryRunner.query(`CREATE TABLE \`student_ding_mapping\` (\`id\` int NOT NULL AUTO_INCREMENT, \`ding_user_id\` varchar(100) NOT NULL, \`student_id\` int NOT NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_0d1ec47e2f901d37e3b6e56331\` (\`ding_user_id\`), UNIQUE INDEX \`IDX_f9ba15ff04de8ffbd8679ae9db\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`student_ding_mapping\` (\`id\` int NOT NULL AUTO_INCREMENT, \`ding_user_id\` varchar(100) NOT NULL, \`student_id\` int NOT NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_0d1ec47e2f901d37e3b6e56331\` (\`ding_user_id\`), UNIQUE INDEX \`IDX_f9ba15ff04de8ffbd8679ae9db\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
await queryRunner.query(`CREATE TABLE \`result_archives\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`culture_final_score\` decimal(5,2) NULL, \`professional_final_score\` decimal(5,2) NULL, \`admission_status\` varchar(50) NULL, \`admitted_college\` varchar(100) NULL, \`admitted_major\` varchar(100) NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_377bba8eb6a027eecd9737d4ed\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
await queryRunner.query(`CREATE TABLE \`result_archives\` (\`id\` int NOT NULL AUTO_INCREMENT, \`student_id\` int NOT NULL, \`culture_final_score\` decimal(5,2) NULL, \`professional_final_score\` decimal(5,2) NULL, \`admission_status\` varchar(50) NULL, \`admitted_college\` varchar(100) NULL, \`admitted_major\` varchar(100) NULL, \`created_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updated_at\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), UNIQUE INDEX \`IDX_377bba8eb6a027eecd9737d4ed\` (\`student_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
||||||
|
|||||||
@@ -16,10 +16,19 @@ describe('student import workbook', () => {
|
|||||||
'课堂回访',
|
'课堂回访',
|
||||||
]);
|
]);
|
||||||
expect(students?.rowCount).toBe(2);
|
expect(students?.rowCount).toBe(2);
|
||||||
|
const headerRow = students?.getRow(1);
|
||||||
|
const columnByHeader = new Map<string, number>();
|
||||||
|
headerRow?.eachCell((cell, colNumber) => columnByHeader.set(String(cell.value), colNumber));
|
||||||
expect(students?.getRow(2).getCell(1).value).toBe('13800138000');
|
expect(students?.getRow(2).getCell(1).value).toBe('13800138000');
|
||||||
expect(students?.getRow(2).getCell(19).value).toBe('pending');
|
expect(students?.getRow(2).getCell(columnByHeader.get('大专院校') || 0).value).toBe(
|
||||||
expect(students?.getRow(2).getCell(20).value || '').toBe('');
|
'北京职业技术学院',
|
||||||
expect(students?.getRow(2).getCell(21).value || '').toBe('');
|
);
|
||||||
|
expect(students?.getRow(2).getCell(columnByHeader.get('大专专业') || 0).value).toBe(
|
||||||
|
'软件技术',
|
||||||
|
);
|
||||||
|
expect(students?.getRow(2).getCell(columnByHeader.get('录取状态') || 0).value).toBe('pending');
|
||||||
|
expect(students?.getRow(2).getCell(columnByHeader.get('录取院校') || 0).value || '').toBe('');
|
||||||
|
expect(students?.getRow(2).getCell(columnByHeader.get('录取专业') || 0).value || '').toBe('');
|
||||||
expect(workbook.getWorksheet('报读班型')?.rowCount).toBe(1);
|
expect(workbook.getWorksheet('报读班型')?.rowCount).toBe(1);
|
||||||
expect(workbook.getWorksheet('考试成绩')?.rowCount).toBe(1);
|
expect(workbook.getWorksheet('考试成绩')?.rowCount).toBe(1);
|
||||||
expect(workbook.getWorksheet('课堂回访')?.rowCount).toBe(1);
|
expect(workbook.getWorksheet('课堂回访')?.rowCount).toBe(1);
|
||||||
@@ -32,11 +41,22 @@ describe('student import workbook', () => {
|
|||||||
'手机号*',
|
'手机号*',
|
||||||
'姓名*',
|
'姓名*',
|
||||||
'目标院校',
|
'目标院校',
|
||||||
|
'大专院校',
|
||||||
|
'大专专业',
|
||||||
'建档日期',
|
'建档日期',
|
||||||
'文化课最终分',
|
'文化课最终分',
|
||||||
'录取状态',
|
'录取状态',
|
||||||
]);
|
]);
|
||||||
students.addRow(['13800138000', '张三', '北京大学', '2024/9/1', 620, 'pending']);
|
students.addRow([
|
||||||
|
'13800138000',
|
||||||
|
'张三',
|
||||||
|
'北京大学',
|
||||||
|
'北京职业技术学院',
|
||||||
|
'软件技术',
|
||||||
|
'2024/9/1',
|
||||||
|
620,
|
||||||
|
'pending',
|
||||||
|
]);
|
||||||
|
|
||||||
const enrollments = workbook.addWorksheet('报读班型');
|
const enrollments = workbook.addWorksheet('报读班型');
|
||||||
enrollments.addRow(['手机号*', '课程类别*', '班型*', '班级名称']);
|
enrollments.addRow(['手机号*', '课程类别*', '班型*', '班级名称']);
|
||||||
@@ -57,6 +77,8 @@ describe('student import workbook', () => {
|
|||||||
phone: '13800138000',
|
phone: '13800138000',
|
||||||
name: '张三',
|
name: '张三',
|
||||||
targetCollege: '北京大学',
|
targetCollege: '北京大学',
|
||||||
|
collegeSchool: '北京职业技术学院',
|
||||||
|
collegeMajor: '软件技术',
|
||||||
profileDate: '2024-09-01',
|
profileDate: '2024-09-01',
|
||||||
cultureFinalScore: 620,
|
cultureFinalScore: 620,
|
||||||
admissionStatus: 'pending',
|
admissionStatus: 'pending',
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export interface StudentImportRow {
|
|||||||
organizationId?: number;
|
organizationId?: number;
|
||||||
targetCollege?: string;
|
targetCollege?: string;
|
||||||
targetMajor?: string;
|
targetMajor?: string;
|
||||||
|
collegeSchool?: string;
|
||||||
|
collegeMajor?: string;
|
||||||
subjectDirection?: string;
|
subjectDirection?: string;
|
||||||
grade?: string;
|
grade?: string;
|
||||||
profileDate?: string;
|
profileDate?: string;
|
||||||
@@ -89,6 +91,8 @@ export const STUDENT_IMPORT_COLUMNS: ColumnDef<StudentImportRow>[] = [
|
|||||||
{ header: '负责人', key: 'supervisor', width: 15, aliases: ['负责人/班主任'] },
|
{ header: '负责人', key: 'supervisor', width: 15, aliases: ['负责人/班主任'] },
|
||||||
{ header: '目标院校', key: 'targetCollege', width: 18 },
|
{ header: '目标院校', key: 'targetCollege', width: 18 },
|
||||||
{ header: '目标专业', key: 'targetMajor', width: 22 },
|
{ header: '目标专业', key: 'targetMajor', width: 22 },
|
||||||
|
{ header: '大专院校', key: 'collegeSchool', width: 18 },
|
||||||
|
{ header: '大专专业', key: 'collegeMajor', width: 22 },
|
||||||
{ header: '选科方向', key: 'subjectDirection', width: 14 },
|
{ header: '选科方向', key: 'subjectDirection', width: 14 },
|
||||||
{ header: '年级', key: 'grade', width: 10 },
|
{ header: '年级', key: 'grade', width: 10 },
|
||||||
{ header: '建档日期', key: 'profileDate', width: 14, kind: 'date' },
|
{ header: '建档日期', key: 'profileDate', width: 14, kind: 'date' },
|
||||||
@@ -302,6 +306,8 @@ export function createStudentImportTemplateWorkbook(): ExcelJS.Workbook {
|
|||||||
supervisor: '李老师',
|
supervisor: '李老师',
|
||||||
targetCollege: '北京大学',
|
targetCollege: '北京大学',
|
||||||
targetMajor: '计算机科学与技术',
|
targetMajor: '计算机科学与技术',
|
||||||
|
collegeSchool: '北京职业技术学院',
|
||||||
|
collegeMajor: '软件技术',
|
||||||
subjectDirection: '物化生',
|
subjectDirection: '物化生',
|
||||||
grade: '高三',
|
grade: '高三',
|
||||||
profileDate: '2024-09-01',
|
profileDate: '2024-09-01',
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ export class StudentsController {
|
|||||||
supervisor: s.supervisor || '',
|
supervisor: s.supervisor || '',
|
||||||
targetCollege: profile?.targetCollege || '',
|
targetCollege: profile?.targetCollege || '',
|
||||||
targetMajor: profile?.targetMajor || '',
|
targetMajor: profile?.targetMajor || '',
|
||||||
|
collegeSchool: profile?.collegeSchool || '',
|
||||||
|
collegeMajor: profile?.collegeMajor || '',
|
||||||
subjectDirection: profile?.subjectDirection || '',
|
subjectDirection: profile?.subjectDirection || '',
|
||||||
grade: profile?.grade || '',
|
grade: profile?.grade || '',
|
||||||
profileDate: profile?.profileDate || '',
|
profileDate: profile?.profileDate || '',
|
||||||
|
|||||||
@@ -50,7 +50,11 @@ describe('StudentsService — archive lifecycle boundaries', () => {
|
|||||||
|
|
||||||
it('builds export archive maps from profile and result rows', async () => {
|
it('builds export archive maps from profile and result rows', async () => {
|
||||||
const profileRepo = {
|
const profileRepo = {
|
||||||
find: jest.fn().mockResolvedValue([{ studentId: 1, targetCollege: '北京大学' }]),
|
find: jest.fn().mockResolvedValue([{
|
||||||
|
studentId: 1,
|
||||||
|
targetCollege: '北京大学',
|
||||||
|
collegeSchool: '北京职业技术学院',
|
||||||
|
}]),
|
||||||
};
|
};
|
||||||
const resultRepo = {
|
const resultRepo = {
|
||||||
find: jest.fn().mockResolvedValue([{ studentId: 1, admissionStatus: 'pending' }]),
|
find: jest.fn().mockResolvedValue([{ studentId: 1, admissionStatus: 'pending' }]),
|
||||||
@@ -72,6 +76,7 @@ describe('StudentsService — archive lifecycle boundaries', () => {
|
|||||||
const maps = await service.getArchiveExportMaps([1]);
|
const maps = await service.getArchiveExportMaps([1]);
|
||||||
|
|
||||||
expect(maps.profiles.get(1)?.targetCollege).toBe('北京大学');
|
expect(maps.profiles.get(1)?.targetCollege).toBe('北京大学');
|
||||||
|
expect(maps.profiles.get(1)?.collegeSchool).toBe('北京职业技术学院');
|
||||||
expect(maps.results.get(1)?.admissionStatus).toBe('pending');
|
expect(maps.results.get(1)?.admissionStatus).toBe('pending');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -333,6 +333,8 @@ export class StudentsService {
|
|||||||
return [
|
return [
|
||||||
row.targetCollege,
|
row.targetCollege,
|
||||||
row.targetMajor,
|
row.targetMajor,
|
||||||
|
row.collegeSchool,
|
||||||
|
row.collegeMajor,
|
||||||
row.subjectDirection,
|
row.subjectDirection,
|
||||||
row.grade,
|
row.grade,
|
||||||
row.profileDate,
|
row.profileDate,
|
||||||
@@ -391,6 +393,8 @@ export class StudentsService {
|
|||||||
const entity = (await this.profileRepo.findOne({ where: { studentId } })) || this.profileRepo.create({ studentId });
|
const entity = (await this.profileRepo.findOne({ where: { studentId } })) || this.profileRepo.create({ studentId });
|
||||||
if (row.targetCollege?.trim()) entity.targetCollege = row.targetCollege.trim();
|
if (row.targetCollege?.trim()) entity.targetCollege = row.targetCollege.trim();
|
||||||
if (row.targetMajor?.trim()) entity.targetMajor = row.targetMajor.trim();
|
if (row.targetMajor?.trim()) entity.targetMajor = row.targetMajor.trim();
|
||||||
|
if (row.collegeSchool?.trim()) entity.collegeSchool = row.collegeSchool.trim();
|
||||||
|
if (row.collegeMajor?.trim()) entity.collegeMajor = row.collegeMajor.trim();
|
||||||
if (row.subjectDirection?.trim()) entity.subjectDirection = row.subjectDirection.trim();
|
if (row.subjectDirection?.trim()) entity.subjectDirection = row.subjectDirection.trim();
|
||||||
if (row.grade?.trim()) entity.grade = row.grade.trim();
|
if (row.grade?.trim()) entity.grade = row.grade.trim();
|
||||||
if (row.profileDate?.trim()) entity.profileDate = row.profileDate.trim();
|
if (row.profileDate?.trim()) entity.profileDate = row.profileDate.trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user