feat: add prisma schema and migrations

- Define Task and State entities with relations
- Add StateHistory for tracking state changes
- Include seed script for initial data
- Add initial and soft delete migrations
This commit is contained in:
Andres Fabian Patiño Bermudez 2026-05-14 21:32:23 -05:00
parent 691c035130
commit c539c9e01d
5 changed files with 238 additions and 0 deletions

View File

@ -0,0 +1,55 @@
-- CreateTable
CREATE TABLE "State" (
"name" TEXT NOT NULL,
CONSTRAINT "State_pkey" PRIMARY KEY ("name")
);
-- CreateTable
CREATE TABLE "Task" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT NOT NULL,
"dueDate" TEXT NOT NULL,
"completed" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Task_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "StateHistory" (
"id" TEXT NOT NULL,
"state" TEXT NOT NULL,
"date" TEXT NOT NULL,
"taskId" TEXT NOT NULL,
"order" INTEGER NOT NULL,
CONSTRAINT "StateHistory_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Note" (
"id" TEXT NOT NULL,
"content" TEXT NOT NULL,
"taskId" TEXT NOT NULL,
"order" INTEGER NOT NULL,
CONSTRAINT "Note_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "StateHistory_taskId_idx" ON "StateHistory"("taskId");
-- CreateIndex
CREATE INDEX "Note_taskId_idx" ON "Note"("taskId");
-- AddForeignKey
ALTER TABLE "StateHistory" ADD CONSTRAINT "StateHistory_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "Task"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "StateHistory" ADD CONSTRAINT "StateHistory_state_fkey" FOREIGN KEY ("state") REFERENCES "State"("name") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Note" ADD CONSTRAINT "Note_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "Task"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "Task" ADD COLUMN "deletedAt" TIMESTAMP(3);
-- CreateIndex
CREATE INDEX "Task_deletedAt_idx" ON "Task"("deletedAt");

View File

@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

54
prisma/schema.prisma Normal file
View File

@ -0,0 +1,54 @@
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model State {
name String @id
tasks StateHistory[]
}
model Task {
id String @id @default(uuid())
title String
description String
dueDate String
completed Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
stateHistory StateHistory[]
notes Note[]
@@index([deletedAt])
}
model StateHistory {
id String @id @default(uuid())
state String
date String
taskId String
order Int
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
stateRef State @relation(fields: [state], references: [name])
@@index([taskId])
}
model Note {
id String @id @default(uuid())
content String
taskId String
order Int
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
@@index([taskId])
}

121
prisma/seed.ts Normal file
View File

@ -0,0 +1,121 @@
import "dotenv/config";
import { PrismaClient } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
const connectionString = process.env.DATABASE_URL;
if (!connectionString) {
throw new Error("DATABASE_URL is not set");
}
const adapter = new PrismaPg({ connectionString });
const prisma = new PrismaClient({ adapter });
async function seed() {
console.log("Seeding database...");
await prisma.state.createMany({
data: [
{ name: "new" },
{ name: "active" },
{ name: "resolved" },
{ name: "closed" },
],
});
const tasks = [
{
title: "Complete Project Proposal",
description: "Prepare and submit the project proposal for approval.",
dueDate: "2023-12-15",
stateHistory: [
{ state: "new", date: "2023-12-01" },
{ state: "active", date: "2023-12-05" },
],
notes: ["Check proposal guidelines", "Include budget estimates"],
},
{
title: "Design Wireframes",
description: "Create wireframes for the user interface.",
dueDate: "2023-12-20",
stateHistory: [
{ state: "new", date: "2023-12-02" },
{ state: "active", date: "2023-12-06" },
],
notes: ["Review design patterns", "Seek feedback from the team"],
},
{
title: "Implement User Authentication",
description: "Develop user authentication functionality.",
dueDate: "2023-12-25",
stateHistory: [
{ state: "new", date: "2023-12-03" },
{ state: "active", date: "2023-12-07" },
],
notes: ["Research secure authentication methods", "Implement password hashing"],
},
{
title: "Write API Documentation",
description: "Document the RESTful API for external developers.",
dueDate: "2023-12-30",
stateHistory: [
{ state: "new", date: "2023-12-04" },
{ state: "active", date: "2023-12-08" },
],
notes: ["Use Swagger/OpenAPI for documentation", "Provide clear examples"],
},
{
title: "Bug Fixes and Testing",
description: "Address reported bugs and perform thorough testing.",
dueDate: "2024-01-05",
stateHistory: [
{ state: "new", date: "2023-12-05" },
{ state: "active", date: "2023-12-09" },
],
notes: ["Create test cases for critical scenarios", "Perform regression testing"],
},
{
title: "Project Deployment",
description: "Prepare for and deploy the project to production.",
dueDate: "2024-01-10",
stateHistory: [
{ state: "new", date: "2023-12-06" },
{ state: "active", date: "2023-12-10" },
],
notes: ["Coordinate with DevOps for deployment", "Monitor performance after deployment"],
},
];
for (const task of tasks) {
await prisma.task.create({
data: {
title: task.title,
description: task.description,
dueDate: task.dueDate,
stateHistory: {
create: task.stateHistory.map((entry, index) => ({
state: entry.state,
date: entry.date,
order: index,
})),
},
notes: {
create: task.notes.map((content, index) => ({
content,
order: index,
})),
},
},
});
}
console.log("Seed completed!");
}
seed()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});