feat(tests): общие тесты с автором, в истории только результаты ученика (для всех ролей)
Made-with: Cursor
This commit is contained in:
+33
-14
@@ -17,27 +17,41 @@ const DEFAULT_TEST_PROMPT = `Ты — составитель тестов. Сг
|
||||
ВАЖНО: Верни ТОЛЬКО JSON-массив, без markdown-обёрток (\`\`\`json), без пояснений, ЧИСТЫЙ JSON:
|
||||
[{"question":"текст вопроса","options":{"a":"вариант А","b":"вариант Б","c":"вариант В","d":"вариант Г"},"correct":"a"}]`;
|
||||
|
||||
/** Тесты привязаны к текущему пользователю (ученик — свои; наставник — свои черновые, не к ученику). */
|
||||
function testOwnerId(req: AuthRequest): number {
|
||||
return req.user!.id;
|
||||
/** Контекст пары: id назначенного ученика (общие тесты для наставника и ученика). */
|
||||
function pairStudentScopeId(req: AuthRequest): number {
|
||||
return req.studentId!;
|
||||
}
|
||||
|
||||
const authorSelect = { username: true, displayName: true } as const;
|
||||
|
||||
router.get("/", async (req: AuthRequest, res: Response) => {
|
||||
const ownerId = testOwnerId(req);
|
||||
const scopeId = pairStudentScopeId(req);
|
||||
const tests = await prisma.test.findMany({
|
||||
where: { studentId: ownerId },
|
||||
where: { studentId: scopeId },
|
||||
orderBy: { createdAt: "desc" },
|
||||
include: { results: true },
|
||||
include: {
|
||||
author: { select: authorSelect },
|
||||
results: {
|
||||
where: { studentId: scopeId },
|
||||
orderBy: { createdAt: "asc" },
|
||||
},
|
||||
},
|
||||
});
|
||||
res.json(tests);
|
||||
});
|
||||
|
||||
router.get("/:id", async (req: AuthRequest, res: Response) => {
|
||||
const id = parseInt(req.params.id as string, 10);
|
||||
const ownerId = testOwnerId(req);
|
||||
const scopeId = pairStudentScopeId(req);
|
||||
const test = await prisma.test.findFirst({
|
||||
where: { id, studentId: ownerId },
|
||||
include: { results: true },
|
||||
where: { id, studentId: scopeId },
|
||||
include: {
|
||||
author: { select: authorSelect },
|
||||
results: {
|
||||
where: { studentId: scopeId },
|
||||
orderBy: { createdAt: "asc" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!test) {
|
||||
@@ -50,8 +64,7 @@ router.get("/:id", async (req: AuthRequest, res: Response) => {
|
||||
|
||||
router.post("/generate", async (req: AuthRequest, res: Response) => {
|
||||
const { topic, fromQuestions } = req.body;
|
||||
const ownerId = testOwnerId(req);
|
||||
/** Вопросы «по моим вопросам» берутся из базы назначенного ученика (для наставника — его ученик). */
|
||||
const scopeId = pairStudentScopeId(req);
|
||||
const questionBankStudentId = req.studentId!;
|
||||
|
||||
const client = await getDeepSeekClient();
|
||||
@@ -92,7 +105,12 @@ router.post("/generate", async (req: AuthRequest, res: Response) => {
|
||||
data: {
|
||||
topic: topic || "По прошлым вопросам",
|
||||
questions: questionsJson,
|
||||
studentId: ownerId,
|
||||
studentId: scopeId,
|
||||
authorId: req.user!.id,
|
||||
},
|
||||
include: {
|
||||
author: { select: authorSelect },
|
||||
results: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -104,10 +122,10 @@ router.post("/generate", async (req: AuthRequest, res: Response) => {
|
||||
|
||||
router.post("/:id/submit", async (req: AuthRequest, res: Response) => {
|
||||
const id = parseInt(req.params.id as string, 10);
|
||||
const ownerId = testOwnerId(req);
|
||||
const scopeId = pairStudentScopeId(req);
|
||||
const { answers } = req.body as { answers: Record<string, string> };
|
||||
|
||||
const test = await prisma.test.findFirst({ where: { id, studentId: ownerId } });
|
||||
const test = await prisma.test.findFirst({ where: { id, studentId: scopeId } });
|
||||
if (!test) {
|
||||
res.status(404).json({ error: "Test not found" });
|
||||
return;
|
||||
@@ -131,6 +149,7 @@ router.post("/:id/submit", async (req: AuthRequest, res: Response) => {
|
||||
const result = await prisma.testResult.create({
|
||||
data: {
|
||||
testId: id,
|
||||
studentId: req.user!.id,
|
||||
answers: JSON.stringify(answers),
|
||||
score,
|
||||
total,
|
||||
|
||||
Reference in New Issue
Block a user