Move review to separate model

This commit is contained in:
2025-08-13 23:53:36 +02:00
parent befc678bdb
commit 900414727f
17 changed files with 403 additions and 155 deletions
@@ -0,0 +1,62 @@
-- CreateTable
CREATE TABLE "public"."Review"
(
"id" SERIAL NOT NULL,
"score" SMALLINT,
"review" TEXT,
"internalNote" TEXT,
"rankingValue" INTEGER,
"showcase" BOOLEAN NOT NULL DEFAULT false,
"answerId" INTEGER NOT NULL,
"reviewerId" INTEGER NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3) NOT NULL,
CONSTRAINT "Review_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "Review_answerId_key" ON "public"."Review" ("answerId");
-- AddForeignKey
ALTER TABLE "public"."Review"
ADD CONSTRAINT "Review_answerId_fkey" FOREIGN KEY ("answerId") REFERENCES "public"."QuestAnswer" ("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "public"."Review"
ADD CONSTRAINT "Review_reviewerId_fkey" FOREIGN KEY ("reviewerId") REFERENCES "public"."User" ("id") ON DELETE CASCADE ON UPDATE CASCADE;
insert into public."Review" ("internalNote",
"rankingValue",
review,
score,
showcase,
"reviewerId",
"answerId",
"updatedAt",
"createdAt")
select "internalNote",
"rankingValue",
review,
score,
showcase,
"reviewerId",
id,
"updatedAt",
"updatedAt"
from "QuestAnswer"
where "reviewerId" is not null;
-- DropForeignKey
ALTER TABLE "public"."QuestAnswer"
DROP CONSTRAINT "QuestAnswer_reviewerId_fkey";
-- AlterTable
ALTER TABLE "public"."QuestAnswer"
DROP COLUMN "internalNote",
DROP COLUMN "rankingValue",
DROP COLUMN "review",
DROP COLUMN "reviewerId",
DROP COLUMN "score",
DROP COLUMN "showcase",
ADD COLUMN "final" BOOLEAN NOT NULL DEFAULT false;
+20 -7
View File
@@ -28,7 +28,7 @@ model User {
teamsOwner HuntTeam[]
teamsMember TeamMember[]
answers QuestAnswer[] @relation("AnswerMember")
reviews QuestAnswer[] @relation("AnswerReview")
reviews Review[]
uploadedFiles File[]
}
@@ -192,6 +192,7 @@ model QuestAnswer {
location String?
lat Decimal? @db.Decimal(10, 8)
lon Decimal? @db.Decimal(10, 8)
final Boolean @default(false)
team HuntTeam @relation(fields: [teamId], references: [id], onUpdate: Cascade, onDelete: Cascade)
teamId Int
@@ -208,8 +209,17 @@ model QuestAnswer {
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
reviewer User? @relation("AnswerReview", fields: [reviewerId], references: [id], onUpdate: Cascade, onDelete: Cascade)
reviewerId Int?
review Review?
oldFiles File[] @relation("OldAnswerFiles")
@@index([teamId])
@@index([memberId])
@@index([questId])
}
model Review {
id Int @id @default(autoincrement())
/// Final score for this answer including bonus
score Int? @db.SmallInt
@@ -222,9 +232,12 @@ model QuestAnswer {
/// If true, this answer will be featured in the end showcase
showcase Boolean @default(false)
oldFiles File[] @relation("OldAnswerFiles")
answer QuestAnswer @relation(fields: [answerId], references: [id], onUpdate: Cascade, onDelete: Cascade)
answerId Int @unique
@@index([teamId])
@@index([memberId])
@@index([questId])
reviewer User @relation(fields: [reviewerId], references: [id], onUpdate: Cascade, onDelete: Cascade)
reviewerId Int
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
}
+83 -52
View File
@@ -236,12 +236,47 @@ async function main() {
const team3 = hunt.teams[2];
const images = [
'/img/dummy/moin1.jpeg',
'/img/dummy/musikanten1.jpg',
'/img/dummy/aussicht1.jpeg',
'https://pichunt.s3.swarm.syma.dev/0197ff6a-ce49-7000-a5b0-f32f1ee1b4ee',
'https://pichunt.s3.swarm.syma.dev/0197ff1a-3c8e-7000-8ba6-fa9c06548f82',
'https://pichunt.s3.swarm.syma.dev/0197ff5b-f74d-7000-864c-20f531481fcc'
'https://pichunt.s3.swarm.syma.dev/0197ff5b-f74d-7000-864c-20f531481fcc',
'/img/dummy/moin1.jpeg',
'/img/dummy/musikanten1.jpg'
];
const reviews = [
{
reviewerId: admin.id,
score: 10,
review: 'Schönes Bild!',
internalNote: 'Wow!'
},
{
score: 17,
reviewerId: huntMember.id,
review: 'Höchstes Team, aber leider gabs andere im AB!',
rankingValue: 10
},
{
score: 13,
reviewerId: admin.id,
review: 'Ihr wart 612m weit weg!',
rankingValue: 612,
internalNote: '612m'
},
{
score: 21,
reviewerId: admin.id,
review: 'Ihr wart 2110m weit weg!',
rankingValue: 2110,
internalNote: 'Bisher am weitesten'
},
{
score: 18,
reviewerId: huntMember.id,
review: 'Ihr wart 945m weit weg!',
rankingValue: 945,
showcase: true
}
];
const answers = await tx.questAnswer.createManyAndReturn({
data: [
@@ -253,10 +288,35 @@ async function main() {
location: 'An der Haltestelle Herdentor',
lat: 53.079138,
lon: 8.809734,
reviewerId: admin.id,
score: 10,
review: 'Schönes Bild!',
internalNote: 'Wow!'
final: true
},
{
teamId: team.id,
memberId: teamMember.id,
questId: hunt.quests[2].id,
text: 'Neustadtswall AB-Gebäude Etage 10',
final: true
},
{
teamId: team.id,
memberId: teamMember.id,
questId: hunt.quests[3].id,
text: 'Theater am Leibnizplatz',
final: true
},
{
teamId: team2.id,
memberId: teamMember2.id,
questId: hunt.quests[3].id,
text: 'Bürgerpark',
final: true
},
{
teamId: team3.id,
memberId: teamMember3.id,
questId: hunt.quests[3].id,
text: 'Am Brill',
final: true
},
{
teamId: team.id,
@@ -264,52 +324,13 @@ async function main() {
questId: hunt.quests[1].id,
text: '14',
location: 'Marktplatz',
score: 10
},
{
teamId: team.id,
memberId: teamMember.id,
questId: hunt.quests[2].id,
text: 'Neustadtswall AB-Gebäude Etage 10',
score: 17,
reviewerId: huntMember.id,
review: 'Höchstes Team, aber leider gabs andere im AB!',
rankingValue: 10
},
{
teamId: team.id,
memberId: teamMember.id,
questId: hunt.quests[3].id,
text: 'Theater am Leibnizplatz',
score: 13,
reviewerId: admin.id,
review: 'Ihr wart 612m weit weg!',
rankingValue: 612,
internalNote: '612m'
},
{
teamId: team2.id,
memberId: teamMember2.id,
questId: hunt.quests[3].id,
text: 'Bürgerpark',
score: 21,
reviewerId: admin.id,
review: 'Ihr wart 2110m weit weg!',
rankingValue: 2110,
internalNote: 'Bisher am weitesten'
},
{
teamId: team3.id,
memberId: teamMember3.id,
questId: hunt.quests[3].id,
text: 'Am Brill',
score: 18,
reviewerId: huntMember.id,
review: 'Ihr wart 945m weit weg!',
rankingValue: 945,
showcase: true
final: false
}
]
],
select: {
id: true,
memberId: true
}
});
await Promise.all(
@@ -325,6 +346,16 @@ async function main() {
})
)
);
await Promise.all(
reviews.map((r, i) =>
tx.review.create({
data: {
answerId: answers[i].id,
...r
}
})
)
);
console.log(JSON.stringify(hunt, null, 2));
});