feat: integrate CampusScope.filter() into all business services (12 services + 12 modules)

This commit is contained in:
2026-07-05 23:58:51 +08:00
parent eeae06fe30
commit cd6364268d
40 changed files with 949 additions and 172 deletions

View File

@@ -9,7 +9,9 @@ import { Repository, Not } from 'typeorm';
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 { CreateRentalDto, UpdateRentalDto } from './dto/rental.dto';
import { CampusScope } from '../common/campus-scope';
import * as path from 'path';
import * as fs from 'fs';
@@ -29,10 +31,13 @@ const COLOR_PALETTE = [
@Injectable()
export class ClassroomRentalsService {
constructor(
@InjectRepository(ClassroomRental) private repo: Repository<ClassroomRental>,
@InjectRepository(Classroom) private classroomRepo: Repository<Classroom>,
@InjectRepository(Tenant) private tenantRepo: Repository<Tenant>,
@InjectRepository(ClassSchedule) private scheduleRepo: Repository<ClassSchedule>,
private readonly scope: CampusScope,
) {}
get uploadDir(): string {
@@ -52,15 +57,16 @@ export class ClassroomRentalsService {
month?: string;
includeEnded?: boolean;
}) {
const scopeIds = await this.scope.getScopeDepartmentIds();
const qb = this.repo
.createQueryBuilder('r')
.leftJoinAndSelect('r.classroom', 'classroom')
.leftJoinAndSelect('r.tenant', 'tenant')
.orderBy('r.startDate', 'DESC');
if (scopeIds) qb.andWhere('r.departmentId IN (:...scopeIds)', { scopeIds });
if (query?.classroomId) qb.andWhere('r.classroomId = :cid', { cid: query.classroomId });
if (query?.tenantId) qb.andWhere('r.tenantId = :tid', { tid: query.tenantId });
if (query?.month) {
// month 格式 2026-06查询当月有重叠的租赁
const [y, m] = query.month.split('-').map(Number);
const first = `${y}-${String(m).padStart(2, '0')}-01`;
const lastDay = new Date(y, m, 0).getDate();
@@ -270,6 +276,7 @@ export class ClassroomRentalsService {
const day = d.getDate();
if (!matrix[rental.classroomId]) continue;
matrix[rental.classroomId][day] = {
scheduleType: 'RENTAL',
rentalId: rental.id,
tenantId: rental.tenantId,
tenantName: rental.tenant?.name || '未知',
@@ -280,6 +287,37 @@ export class ClassroomRentalsService {
}
}
// ── Overlay internal class schedules ──
const schedules = await this.scheduleRepo
.createQueryBuilder('s')
.leftJoinAndSelect('s.class', 'class')
.leftJoinAndSelect('s.teacher', 'teacher')
.where('s.status = :active', { active: 'active' })
.andWhere('s.scheduleType = :type', { type: 'INTERNAL' })
.andWhere('s.startDate <= :last AND s.endDate >= :first', { first, last })
.getMany();
for (const sched of schedules) {
if (!sched.classroomId) continue;
const schedStart = new Date(Math.max(new Date(sched.startDate).getTime(), new Date(first).getTime()));
const schedEnd = new Date(Math.min(new Date(sched.endDate).getTime(), new Date(last).getTime()));
for (let d = new Date(schedStart); d <= schedEnd; d.setDate(d.getDate() + 1)) {
const dow = d.getDay() === 0 ? 7 : d.getDay();
if (dow !== sched.weekDay) continue;
const day = d.getDate();
if (!matrix[sched.classroomId]) continue;
matrix[sched.classroomId][day] = {
scheduleType: 'INTERNAL',
scheduleId: sched.id,
className: (sched.class as any)?.name || '',
subject: sched.subject,
teacherName: (sched.teacher as any)?.name || '',
startTime: sched.startTime,
endTime: sched.endTime,
color: '#52c41a',
};
}
}
// 统计
for (const cls of classrooms) {
const rented = Object.keys(matrix[cls.id]).length;