- SchedulesService.checkConflict 增加对 classroom_rentals 的冲突检测 - ClassroomRentalsService.findConflicts 增加对 class_schedules 的冲突检测 - 创建排课时若教室已被租赁,给出明确冲突提示 - 创建租赁时若教室已有排课,给出明确冲突提示
90 lines
4.1 KiB
TypeScript
90 lines
4.1 KiB
TypeScript
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
|
import { ConflictException } from '@nestjs/common';
|
|
import { Repository } from 'typeorm';
|
|
import { ClassroomRentalsService } from './classroom-rentals.service';
|
|
import { ClassroomRental } from '../entities/classroom-rental.entity';
|
|
import { Classroom } from '../entities/classroom.entity';
|
|
import { Tenant } from '../entities/tenant.entity';
|
|
import { ClassSchedule } from '../entities/class-schedule.entity';
|
|
import { CampusScope } from '../common/campus-scope';
|
|
|
|
function mockQueryBuilder<T>(results: T[] = []) {
|
|
const qb = {
|
|
where: jest.fn().mockReturnThis(),
|
|
andWhere: jest.fn().mockReturnThis(),
|
|
leftJoinAndSelect: jest.fn().mockReturnThis(),
|
|
getMany: jest.fn().mockResolvedValue(results),
|
|
};
|
|
return qb;
|
|
}
|
|
|
|
describe('ClassroomRentalsService — findConflicts', () => {
|
|
let service: ClassroomRentalsService;
|
|
let rentalRepo: jest.Mocked<Pick<Repository<ClassroomRental>, 'createQueryBuilder'>>;
|
|
let scheduleRepo: jest.Mocked<Pick<Repository<ClassSchedule>, 'createQueryBuilder'>>;
|
|
|
|
beforeEach(async () => {
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
ClassroomRentalsService,
|
|
{ provide: getRepositoryToken(ClassroomRental), useValue: { createQueryBuilder: jest.fn() } },
|
|
{ provide: getRepositoryToken(Classroom), useValue: {} },
|
|
{ provide: getRepositoryToken(Tenant), useValue: {} },
|
|
{ provide: getRepositoryToken(ClassSchedule), useValue: { createQueryBuilder: jest.fn() } },
|
|
{ provide: CampusScope, useValue: { getScopeDepartmentIds: jest.fn().mockResolvedValue(null) } },
|
|
],
|
|
}).compile();
|
|
|
|
service = module.get<ClassroomRentalsService>(ClassroomRentalsService);
|
|
rentalRepo = module.get(getRepositoryToken(ClassroomRental));
|
|
scheduleRepo = module.get(getRepositoryToken(ClassSchedule));
|
|
});
|
|
|
|
it('returns rental conflicts when no schedule conflicts exist', async () => {
|
|
const rental = { id: 1, startDate: '2026-03-01', endDate: '2026-03-31', tenant: { name: 'A机构' } } as ClassroomRental;
|
|
const rentalQb = mockQueryBuilder<ClassroomRental>([rental]);
|
|
const scheduleQb = mockQueryBuilder<ClassSchedule>([]);
|
|
(rentalRepo.createQueryBuilder as jest.Mock).mockReturnValue(rentalQb);
|
|
(scheduleRepo.createQueryBuilder as jest.Mock).mockReturnValue(scheduleQb);
|
|
|
|
const result = await service.findConflicts(1, '2026-03-15', '2026-04-15');
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].id).toBe(1);
|
|
});
|
|
|
|
it('throws ConflictException when an active schedule overlaps the same classroom and date range', async () => {
|
|
const rentalQb = mockQueryBuilder<ClassroomRental>([]);
|
|
const scheduleQb = mockQueryBuilder<ClassSchedule>([
|
|
{ id: 5, subject: '数学', startDate: '2026-03-01', endDate: '2026-06-30' } as ClassSchedule,
|
|
]);
|
|
(rentalRepo.createQueryBuilder as jest.Mock).mockReturnValue(rentalQb);
|
|
(scheduleRepo.createQueryBuilder as jest.Mock).mockReturnValue(scheduleQb);
|
|
|
|
await expect(service.findConflicts(1, '2026-03-15', '2026-04-15')).rejects.toThrow(ConflictException);
|
|
});
|
|
|
|
it('does not throw when schedule is outside the requested date range', async () => {
|
|
const rentalQb = mockQueryBuilder<ClassroomRental>([]);
|
|
const scheduleQb = mockQueryBuilder<ClassSchedule>([]);
|
|
(rentalRepo.createQueryBuilder as jest.Mock).mockReturnValue(rentalQb);
|
|
(scheduleRepo.createQueryBuilder as jest.Mock).mockReturnValue(scheduleQb);
|
|
|
|
const result = await service.findConflicts(1, '2026-07-01', '2026-08-31');
|
|
|
|
expect(result).toHaveLength(0);
|
|
});
|
|
|
|
it('excludes the given rental id from rental conflict check', async () => {
|
|
const rentalQb = mockQueryBuilder<ClassroomRental>([]);
|
|
const scheduleQb = mockQueryBuilder<ClassSchedule>([]);
|
|
(rentalRepo.createQueryBuilder as jest.Mock).mockReturnValue(rentalQb);
|
|
(scheduleRepo.createQueryBuilder as jest.Mock).mockReturnValue(scheduleQb);
|
|
|
|
await service.findConflicts(1, '2026-03-01', '2026-03-31', 99);
|
|
|
|
expect(rentalQb.andWhere).toHaveBeenCalledWith('r.id != :excludeId', { excludeId: 99 });
|
|
});
|
|
});
|