Files
reloop-v2/backend/prisma/seed.ts
reloop d892d8298b feat(phase10A): KICE 비수학 제거 + 수학 단원 분리
- schema: MathUnit enum (common/prob_stat/calculus/geometry)
- User: focusUnits(Json), bojHandle(VarChar32)
- ProblemSet: mathUnit optional + unique(year,examType,subjectName,mathUnit)
- migration: phase10_math_units_and_ps
- scripts: wipe-non-math (dry/apply), kice-import refactor (math only,
  30문항을 공통22 + 확통/미적/기하 8씩으로 분할 → 2년×4 = 8 ProblemSet)
- parsing strategy/ocr-fix/seed/me/study-logs: 비수학 참조 전면 제거
- data/kice, backend/uploads/problems: 비수학 폴더 삭제
- Plans.md: Phase 10 계획 확정

Phase 10A DoD 통과 — prisma validate/format OK, nest build OK,
kice-import dry-run 2년 각 46문항 확인, wipe dry-run 8 set/260 problems 확인.
2026-04-14 18:27:00 +09:00

140 lines
3.1 KiB
TypeScript

/**
* Dev seed — creates a default demo user with 수능 과목/태그 preset.
* Run via: `pnpm prisma:seed` (or `ts-node prisma/seed.ts`).
*
* Idempotent: re-running just upserts.
*/
import {
OrgRole,
OrgType,
Persona,
PrismaClient,
ReviewIntensity,
} from "@prisma/client";
import * as bcrypt from "bcrypt";
const prisma = new PrismaClient();
const DEMO_EMAIL = "demo@reloop.local";
const DEMO_PASSWORD = "demo1234";
interface SubjectSeed {
name: string;
color: string;
tags: string[];
}
const SUBJECTS: SubjectSeed[] = [
{
name: "수학",
color: "#3b82f6",
tags: [
"미적분",
"확률과통계",
"기하",
"수1 지수로그",
"수1 삼각함수",
"수2 미분",
"수2 적분",
],
},
];
async function main() {
console.log("🌱 ReLoop seed start");
// Demo user
const hash = await bcrypt.hash(DEMO_PASSWORD, 10);
const user = await prisma.user.upsert({
where: { email: DEMO_EMAIL },
update: {},
create: {
email: DEMO_EMAIL,
password: hash,
nickname: "데모",
persona: Persona.mid,
currentGrade: 4,
targetGrade: 2,
reviewIntensity: ReviewIntensity.moderate,
onboardedAt: new Date(),
},
});
console.log(` user: ${user.email} (id=${user.id})`);
for (const s of SUBJECTS) {
const subject = await prisma.subject.upsert({
where: { userId_name: { userId: user.id, name: s.name } },
update: { color: s.color },
create: { name: s.name, color: s.color, userId: user.id },
});
console.log(` subject: ${subject.name}`);
for (const tagName of s.tags) {
await prisma.tag.upsert({
where: { subjectId_name: { subjectId: subject.id, name: tagName } },
update: {},
create: { name: tagName, subjectId: subject.id },
});
}
}
const organization = await prisma.organization.upsert({
where: { inviteCode: "de1a0001" },
update: {
name: "ReLoop 데모 학원",
type: OrgType.academy,
},
create: {
name: "ReLoop 데모 학원",
type: OrgType.academy,
inviteCode: "de1a0001",
},
});
console.log(` organization: ${organization.name} (id=${organization.id})`);
await prisma.organizationMember.upsert({
where: {
userId_organizationId: {
userId: user.id,
organizationId: organization.id,
},
},
update: { role: OrgRole.admin },
create: {
userId: user.id,
organizationId: organization.id,
role: OrgRole.admin,
},
});
const existingDemoClass = await prisma.class.findFirst({
where: {
organizationId: organization.id,
teacherId: user.id,
name: "고3 A반",
},
});
const demoClass =
existingDemoClass ??
(await prisma.class.create({
data: {
name: "고3 A반",
organizationId: organization.id,
teacherId: user.id,
},
}));
console.log(` class: ${demoClass.name} (id=${demoClass.id})`);
console.log("✅ seed done");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});