- 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 확인.
140 lines
3.1 KiB
TypeScript
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();
|
|
});
|