fix(lms): support direct R2 map uploads and preserve empty course groups
This commit is contained in:
@@ -22,6 +22,7 @@ import { R2PublicFileService } from '../storage/r2-public-file.service';
|
||||
import { CreateInstructorPlatformDto } from './dto/create-instructor-platform.dto';
|
||||
import { CreateInstructorStudentDto } from './dto/create-instructor-student.dto';
|
||||
import { SaveInstructorGroupDto } from './dto/save-instructor-group.dto';
|
||||
import { groupCourseScope } from './group-course-scope';
|
||||
import { SaveSubmissionScoreDto } from './dto/save-submission-score.dto';
|
||||
import { UpdateInstructorCurriculumDto } from './dto/update-instructor-curriculum.dto';
|
||||
import { UpdateInstructorPlatformDto } from './dto/update-instructor-platform.dto';
|
||||
@@ -1126,6 +1127,8 @@ export class InstructorService {
|
||||
? { courseId: course.id }
|
||||
: { course: { teacherId: instructor.id } };
|
||||
|
||||
if (courseId?.trim() && !course) throw new NotFoundException('Course not found');
|
||||
|
||||
const groups = await this.prisma.studentGroup.findMany({
|
||||
where: {
|
||||
AND: [
|
||||
@@ -1135,20 +1138,7 @@ export class InstructorService {
|
||||
organizationName ? { organizationName } : undefined,
|
||||
].filter(Boolean) as Prisma.StudentGroupWhereInput[],
|
||||
},
|
||||
{
|
||||
members: {
|
||||
some: {
|
||||
user: {
|
||||
enrollments: {
|
||||
some: {
|
||||
status: 'ACTIVE',
|
||||
...enrollmentScope,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
groupCourseScope(instructor.id, course?.id),
|
||||
],
|
||||
},
|
||||
orderBy: { name: 'asc' },
|
||||
@@ -2568,6 +2558,9 @@ export class InstructorService {
|
||||
const organizationName = authUser.primaryAffiliation?.organizationName?.trim();
|
||||
if (!organizationName) throw new BadRequestException('Instructor organization is required');
|
||||
|
||||
const course = await this.findInstructorCourse(organizationName, instructor.id, input.courseId);
|
||||
if (!course) throw new NotFoundException('Course not found');
|
||||
|
||||
const name = input.name.trim();
|
||||
if (!name) throw new BadRequestException('Group name is required');
|
||||
|
||||
@@ -2584,6 +2577,7 @@ export class InstructorService {
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
const group = await tx.studentGroup.create({
|
||||
data: {
|
||||
courseId: course.id,
|
||||
organizationId,
|
||||
organizationName,
|
||||
name,
|
||||
@@ -2637,7 +2631,9 @@ export class InstructorService {
|
||||
const organizationName = authUser.primaryAffiliation?.organizationName?.trim();
|
||||
if (!organizationName) throw new BadRequestException('Instructor organization is required');
|
||||
|
||||
const group = await this.findInstructorGroup(groupId, organizationId, organizationName);
|
||||
const course = await this.findInstructorCourse(organizationName, instructor.id, input.courseId);
|
||||
if (!course) throw new NotFoundException('Course not found');
|
||||
const group = await this.findInstructorGroup(groupId, organizationId, organizationName, instructor.id, course.id);
|
||||
const name = input.name.trim();
|
||||
if (!name) throw new BadRequestException('Group name is required');
|
||||
const memberIds = await this.validateActiveStudentIds(
|
||||
@@ -2665,6 +2661,7 @@ export class InstructorService {
|
||||
await tx.studentGroup.update({
|
||||
where: { id: group.id },
|
||||
data: {
|
||||
courseId: course.id,
|
||||
name,
|
||||
instructorPlatformId: assignedPlatform?.id ?? null,
|
||||
platformName: assignedPlatform?.displayName ?? null,
|
||||
@@ -2734,12 +2731,14 @@ export class InstructorService {
|
||||
}
|
||||
|
||||
async deleteGroup(accessToken: string | undefined, groupId: string, courseId?: string | null) {
|
||||
const { authUser } = await this.getInstructor(accessToken);
|
||||
const { authUser, instructor } = await this.getInstructor(accessToken);
|
||||
const organizationId = authUser.primaryAffiliation?.organizationId;
|
||||
const organizationName = authUser.primaryAffiliation?.organizationName?.trim();
|
||||
if (!organizationName) throw new BadRequestException('Instructor organization is required');
|
||||
|
||||
const group = await this.findInstructorGroup(groupId, organizationId, organizationName);
|
||||
const course = await this.findInstructorCourse(organizationName, instructor.id, courseId);
|
||||
if (!course) throw new NotFoundException('Course not found');
|
||||
const group = await this.findInstructorGroup(groupId, organizationId, organizationName, instructor.id, course.id);
|
||||
const previousAssignment = await this.getGroupPlatformAssignment(group.id);
|
||||
const termination = await this.prepareGroupPlatformTermination({
|
||||
groupId: group.id,
|
||||
@@ -3004,10 +3003,13 @@ export class InstructorService {
|
||||
groupId: string,
|
||||
organizationId: string | undefined,
|
||||
organizationName: string,
|
||||
instructorId: string,
|
||||
courseId: string,
|
||||
) {
|
||||
const group = await this.prisma.studentGroup.findFirst({
|
||||
where: {
|
||||
id: groupId,
|
||||
AND: [groupCourseScope(instructorId, courseId)],
|
||||
OR: [
|
||||
organizationId ? { organizationId } : undefined,
|
||||
{ organizationName },
|
||||
|
||||
Reference in New Issue
Block a user