fix: handle duplicate usernames and failed role lookups in importDingTalkUsers
This commit is contained in:
@@ -116,13 +116,17 @@ describe('SyncService — new methods', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports teacher when roleId is a number but role not found (logs warning, no roles assigned)', async () => {
|
it('imports teacher when roleId is a number but role not found (creates student as fallback)', async () => {
|
||||||
roleRepo.findOne.mockResolvedValue(null);
|
roleRepo.findOne.mockResolvedValue(null);
|
||||||
|
|
||||||
const mockUser = { id: 11 } as User;
|
const mockUser = { id: 11 } as User;
|
||||||
userRepo.create.mockReturnValue(mockUser);
|
userRepo.create.mockReturnValue(mockUser);
|
||||||
userRepo.save.mockResolvedValue(mockUser);
|
userRepo.save.mockResolvedValue(mockUser);
|
||||||
|
|
||||||
|
const mockStudent = { id: 31 } as Student;
|
||||||
|
studentRepo.create.mockReturnValue(mockStudent);
|
||||||
|
studentRepo.save.mockResolvedValue(mockStudent);
|
||||||
|
|
||||||
mappingRepo.findOne.mockResolvedValue(null);
|
mappingRepo.findOne.mockResolvedValue(null);
|
||||||
mappingRepo.create.mockReturnValue({} as UserDingMapping);
|
mappingRepo.create.mockReturnValue({} as UserDingMapping);
|
||||||
mappingRepo.save.mockResolvedValue({} as UserDingMapping);
|
mappingRepo.save.mockResolvedValue({} as UserDingMapping);
|
||||||
@@ -133,12 +137,21 @@ describe('SyncService — new methods', () => {
|
|||||||
|
|
||||||
const result = await service.importDingTalkUsers(users);
|
const result = await service.importDingTalkUsers(users);
|
||||||
|
|
||||||
expect(result.teacherCount).toBe(1);
|
expect(result.teacherCount).toBe(0);
|
||||||
expect(result.studentCount).toBe(0);
|
expect(result.studentCount).toBe(1);
|
||||||
expect(result.skipped).toBe(0);
|
expect(result.skipped).toBe(0);
|
||||||
|
|
||||||
// User should be saved once (without roles assignment the second time)
|
// User should be saved once (no second save for role assignment)
|
||||||
expect(userRepo.save).toHaveBeenCalledTimes(1);
|
expect(userRepo.save).toHaveBeenCalledTimes(1);
|
||||||
|
// Student record should have been created as fallback
|
||||||
|
expect(studentRepo.create).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
name: 'Li Si',
|
||||||
|
userId: 11,
|
||||||
|
status: 'active',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(studentRepo.save).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('imports student when roleId is null', async () => {
|
it('imports student when roleId is null', async () => {
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export class SyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const username = u.mobile || `dd_${u.dingUserId}`;
|
const username = `dd_${u.dingUserId}`;
|
||||||
const passwordHash = await bcrypt.hash('123456', 10);
|
const passwordHash = await bcrypt.hash('123456', 10);
|
||||||
|
|
||||||
const user = this.userRepo.create({
|
const user = this.userRepo.create({
|
||||||
@@ -155,10 +155,18 @@ export class SyncService {
|
|||||||
if (role) {
|
if (role) {
|
||||||
user.roles = [role];
|
user.roles = [role];
|
||||||
await this.userRepo.save(user);
|
await this.userRepo.save(user);
|
||||||
|
teacherCount++;
|
||||||
} else {
|
} else {
|
||||||
this.logger.warn(`角色 id=${u.roleId} 不存在,用户 ${u.name} 未分配角色`);
|
this.logger.warn(`角色 id=${u.roleId} 不存在,用户 ${u.name} 转为学生`);
|
||||||
|
const student = this.studentRepo.create({
|
||||||
|
name: u.name,
|
||||||
|
phone: u.mobile || undefined,
|
||||||
|
userId: user.id,
|
||||||
|
status: 'active',
|
||||||
|
});
|
||||||
|
await this.studentRepo.save(student);
|
||||||
|
studentCount++;
|
||||||
}
|
}
|
||||||
teacherCount++;
|
|
||||||
} else {
|
} else {
|
||||||
// 学生:创建 Student 记录
|
// 学生:创建 Student 记录
|
||||||
const student = this.studentRepo.create({
|
const student = this.studentRepo.create({
|
||||||
|
|||||||
Reference in New Issue
Block a user